Offre à durée limitée- 50% DE RÉDUCTION ANNUELLEÉchanger
23 juil. 2026Research

Comment nous avons rendu notre API Text-to-Speech gratuite : L'ingénierie d'inférence derrière S2.1 Pro

Comment nous avons rendu notre API Text-to-Speech gratuite : L'ingénierie d'inférence derrière S2.1 Pro

En bref

  • Fish Audio S2.1 Pro est désormais disponible en tant qu'API text-to-speech gratuite : 83 langues, pas de limite d'utilisation stricte, chaîne de modèle s2.1-pro-free. L'accès gratuit est disponible pour une période initiale ; nous communiquerons tout changement avec un préavis. Pour plus d'informations, consultez ici.
  • L'optimisation de l'inférence de bout en bout a multiplié par 4 la capacité de requêtes par GPU : la même charge de travail qui nécessitait auparavant quatre H200 fonctionne désormais sur un seul.
  • Leviers clés : noyaux CUDA personnalisés (2,1 à 4,3 fois plus rapides que cuBLAS sur les formes de décodage), batching continu (mise à l'échelle du débit par 52 de c=1→64), utilisation du GPU augmentée d'environ 50 % à plus de 90 %.
  • La même pile technique alimente notre API de clonage vocal — mêmes poids de modèle, même infrastructure, niveau gratuit inclus. S2.1 Pro s'appuie sur Fish Speech, notre modèle de fondation à poids ouverts.
  • La bibliothèque de noyaux centrale fish-scales-ops est open source.

Découvrez pourquoi les développeurs quittent d'autres plateformes → Commencez à construire gratuitement

Juillet 2026 | Fish Audio a reconstruit la pile d'inférence et a rendu S2.1 Pro gratuit pour chaque développeur


La véritable raison pour laquelle l'IA vocale coûte cher

L'inférence de l'IA vocale présente un problème structurel que les pages de tarification n'expliquent pas : le décodage autorégressif est par défaut hostile à l'utilisation des ressources GPU.

Chaque appel à une API TTS entraîne une boucle de décodage qui génère des jetons audio un par un. Chaque étape est une petite multiplication de matrice — M ≤ 128 en pratique — suivie d'une lecture en mémoire du cache KV pour cette séquence. Les cœurs CUDA restent principalement inactifs pendant que le sous-système mémoire rattrape son retard. Sur un H200 à 30 000 $, vous payez pour de la puissance de calcul et vous la gaspillez dans des interruptions mémoire (memory stalls).

À faible concurrence, c'est encore pire. Une boucle de décodage à requête unique occupe le GPU par rafales de 10 à 20 µs séparées par des frais de planification (overhead). L'utilisation du GPU sur un point de terminaison TTS servi naïvement à c=1 peut être inférieure à 10 %. Le matériel est présent, mais le travail ne le remplit pas.

Timeline montrant qu'une seule requête TTS n'occupe le GPU qu'environ 10 % du temps, avec de longs intervalles d'attente mémoire entre chaque étape de génération de jetons

La réponse de l'industrie a été de répercuter le coût sur les développeurs via une tarification par caractère. Notre réponse a été de résoudre le problème d'utilisation au niveau de la couche d'infrastructure. Lorsqu'un seul GPU peut effectuer le travail qui en nécessitait auparavant quatre, l'économie d'un niveau gratuit devient viable.

Voici ce que cela a nécessité.


Optimisation de bout en bout : la pile complète

Une pile d'optimisation à cinq couches, du service à l'infrastructure, montrant le gain d'efficacité à chaque niveau : débit multiplié par 52, accélération du noyau de 2,1 à 4,3 fois, utilisation du GPU de ~50 % à ~90 %+, pas de marge cloud, coût de transfert de données supprimé

Aucun changement unique ne permet d'obtenir une amélioration de l'efficacité par 4. Les gains proviennent de l'optimisation simultanée de chaque couche et de leur effet cumulé :

  • Noyaux CUDA personnalisés — élimination du gaspillage de calcul par jeton
  • Quantification FP8 — réduction de moitié de la pression sur la bande passante mémoire
  • Batching continu — remplissage du GPU via des requêtes concurrentes
  • Planification GPU — élimination de la capacité inutilisée entre les charges de travail
  • Réseau et stockage en propre — suppression des marges sur l'infrastructure cloud

Chaque couche est décrite ci-dessous. Les chiffres de débit et de coût à la fin sont le produit de toutes ces optimisations réunies.


Noyaux CUDA personnalisés : fish-scales-ops

Pourquoi cuBLAS ne suffisait pas

Les formes de décodage dans le service TTS (M ≤ 128) ne sont pas celles pour lesquelles cuBLAS, les noyaux GEMM de PyTorch, ou même torch.compile sont optimisés. Ces bibliothèques ciblent l'entraînement et le pré-remplissage à large lot — avec M se comptant en milliers. Pour les petits M, elles sous-utilisent la bande passante mémoire et manquent des opportunités de fusion qui n'existent qu'aux tailles de batch de décodage.

L'écart spécifique : pour un passage en avant (forward) SwiGLU MLP à M=1 (décodage d'une seule requête), cuBLAS scaled_mm lance trois noyaux distincts — activation, multiplication de porte (gate), projection descendante — avec des résultats intermédiaires écrits et relus depuis la mémoire HBM entre chaque étape. À M=1, cet aller-retour est le goulot d'étranglement, pas le calcul.

Nous avons construit fish-scales-ops pour combler cet écart : une bibliothèque GEMM FP8 et FlashAttention de qualité production ciblant les architectures NVIDIA Hopper (H200, sm_90a) et Blackwell (sm_120a), en open source.

Stratégie de quantification FP8

Nous avons implémenté deux schémas de quantification pour différentes générations de matériel :

bsgemm (FP8 à mise à l'échelle par bloc 128×128) pour H200/Hopper. La mise à l'échelle par bloc avec une granularité de 128×128 offre une bonne stabilité numérique sans les risques de précision liés à la quantification par tenseur.

mxfp8 (1×32, format OCP UE8M0) pour Blackwell (RTX 5090, RTX 6000 PRO). La mise à l'échelle microscopique avec des exposants partagés sur 32 éléments — le standard OCP MX — offre une fidélité numérique plus fine aux échelles cruciales pour la génération de jetons audio.

Un bug non évident dans le chemin mxfp8 a nécessité un débogage important : quantize_blockscale.py matérialisait les tenseurs weight_scale avec .contiguous() pour la compatibilité safetensors, mais linear_mxfp8_raw lit les échelles avec un pas K-major (1, N). Le chargement d'un format row-major contigu [N, K/128] faisait produire à chaque GEMM des logits incorrects à pleine vitesse du noyau — le mode d'échantillonnage en aval s'effondrait sur un seul jeton sémantique répété, ce qui ressemble à un problème de qualité de modèle mais est en réalité un bug de disposition mémoire. Le correctif a consisté à modifier le pas (re-striding) dans MXFP8LinearMethod.process_weights_after_loading. Après correction, le décodage glouton correspond exactement aux jetons bf16 sur les cinq premières trames audio.

Résultats des tests de performance (Benchmark) des noyaux

Graphique à barres comparant fish-scales-ops MXFP8 par rapport à cuBLAS et torch.compile pour les tailles de batch de décodage M=1, 4, 16, 64. fish-scales-ops est 6,2 fois plus rapide que cuBLAS à M=1, convergeant vers 1,7 fois à M=64

Sur les formes de décodage (M ≤ 128), les benchmarks internes sur matériel équivalent — méthodologie complète dans le dépôt fish-scales-ops :

  • Le chemin MXFP8 bat torch.nn.functional.scaled_mm sur 8 des 10 formes carrées de 1024³ à 16384³, jusqu'à +21 %
  • Passage forward Qwen3-4B SwiGLU MLP de bout en bout : 1,7 à 6,2 fois plus rapide que cuBLAS brut scaled_mm pour chaque M de 1 à 4096
  • Contre cuBLAS fusionné par torch.compile sur les formes de décodage : 2,1 à 4,3 fois plus rapide
  • FlashAttention MXFP8 sur sm_120a : 7 à 19 fois plus rapide que le décodage SDPA de PyTorch, 1,2 à 2,7 fois plus rapide que FlashInfer BF16

Les deux noyaux fusionnés générant la majeure partie du gain : l'un fusionne la quantification de l'activation + le pack d'échelle UE8M0 en un seul lancement ; l'autre fusionne le prologue SwiGLU directement dans la quantification d'activation du down-GEMM, éliminant une écriture et une lecture intermédiaires BF16 complètes que PyTorch matérialiserait autrement entre les deux opérations.


Architecture d'inférence par lots : le compromis Latence–Débit

Batching continu pour le TTS autorégressif

L'efficacité du noyau améliore le coût par jeton. Le batching est ce qui convertit l'efficacité par jeton en utilisation du GPU à travers le flux de requêtes.

Le batching statique — remplir toutes les séquences à la même longueur (padding), exécuter comme un lot fixe — gaspille du calcul sur le padding et bloque les nouvelles requêtes jusqu'à ce que la séquence la plus lente du lot soit terminée. Pour le TTS avec des longueurs de sortie variables, la pénalité de latence de queue est significative.

Nous utilisons le batching continu adapté de sglang : les nouvelles requêtes rejoignent le lot de décodage actif dès que des emplacements se libèrent, sans attendre une limite de lot. La boucle de décodage du GPU ne s'arrête jamais pour une requête aberrante lente.

DualAR : Contraintes de batching spécifiques à S2

L'architecture DualAR de S2.1 Pro génère des jetons audio en deux étapes — des livres de codes grossiers (coarse codebooks) suivis de livres de codes fins (fine codebooks) — avec une fenêtre glissante previous_tokens qui conditionne chaque étape. Cela crée une contrainte de justesse que le batching LLM standard n'a pas : le noyau prev_tokens_shift_inplace nécessite un contrat strict de forme/type (prev int32 [bs, W, cw], next_tokens int32 [bs, cw]). Tout ajustement de forme dans l'appelant — .unsqueeze(), promotion de type implicite — corrompt la fenêtre et produit un audio dégradé difficile à distinguer d'une régression de qualité du modèle.

Pour les charges de travail de clonage vocal, cette contrainte est particulièrement importante : le conditionnement du locuteur passe par le même chemin de décodage, et la corruption de la fenêtre se manifeste par une dérive de l'identité du locuteur sur de longues sorties plutôt que par des artefacts audio évidents.

Résultats de débit

H200, bsgemm FP8, balayage de concurrence :

ConcurrenceDébit globalTTFB p50
1154 jetons/s73,2 ms
4595 jetons/s75,5 ms
81 206 jetons/s81,2 ms
162 373 jetons/s79,6 ms
324 099 jetons/s96,9 ms
648 006 jetons/s109,8 ms

Graphique à deux axes montrant la montée en charge du débit global de 154 jetons/s à une concurrence de 1 jusqu'à 19 517 jetons/s à une concurrence de 512, tandis que le TTFB p50 augmente progressivement de 73ms à 525ms

Le débit est multiplié par ~52 de c=1 à c=64, tandis que le TTFB n'augmente que de 36,6 ms — de 73 ms à 110 ms. Le GPU effectue 52 fois plus de travail pour une pénalité de latence imperceptible dans la plupart des charges de travail de production.

À c=64, un seul H200 maintient 8 006 jetons/s. Ce chiffre est le mécanisme direct derrière le niveau gratuit : plus de débit par GPU signifie un coût par requête plus bas.

Ce sont les chiffres qui tournent derrière chaque appel à l'API gratuite. Commencez à construire →

Mode temps réel : approche architecturale pour les charges de travail à faible latence

Pour les agents vocaux et les applications de conversation, nous exposons un point de terminaison en temps réel séparé, optimisé pour le délai avant le premier audio (TTFA) plutôt que pour le débit global.

La décision architecturale clé : le pré-remplissage (prefill) se produit à l'ouverture de la connexion, totalement en dehors du chemin critique de la latence. Le chronomètre de la latence de streaming démarre à l'envoi du premier segment audio, pas à l'établissement de la connexion. Cela signifie que le coût du prefill, qui augmente avec la longueur du prompt, n'apparaît pas du tout dans le chiffre TTFA.

Au niveau de l'ordonnanceur, une conception en ping-pong exécute le décodage et le prefill sur des threads séparés sans barrière hôte par cycle. La suppression de la barrière est la principale amélioration du TTFA à c≥4 : dans une implémentation naïve, la synchronisation côté hôte après chaque étape de décodage sérialise ce qui devrait être un travail concurrent. La boucle de décodage pipelinée et les transferts mémoire H2D épinglés traitent le TTFB et la gigue (jitter) à haute concurrence.

La conception complète et la décomposition de la latence sont disponibles dans arXiv:2603.08823.


Validation de la qualité : comment nous avons vérifié que l'optimisation ne dégradait pas l'audio

Schéma montrant que chaque changement de la pile d'inférence doit passer à la fois une porte de justesse (correspondance exacte des jetons vs bf16 sur les 5 premières trames) et une porte de performance (décode_tps dans une marge de 5 % à c=1, 16, 64) avant le déploiement en production

La quantification et le batching peuvent introduire des régressions de qualité difficiles à détecter avec les seuls benchmarks de débit — le GPU tourne à pleine vitesse en produisant des sorties incorrectes.

Nous avons détecté un exemple de cela pendant le développement de mxfp8 : le bug de disposition des poids décrit plus haut produisait une erreur relative de logit de ~53 % alors que la latence du noyau était tout à fait normale. La régression n'apparaissait que dans l'analyse des jetons de sortie, pas dans les mesures de performance.

Notre pipeline de validation comporte deux portes :

Porte de justesse : Le décodage glouton après quantification doit correspondre exactement au jeton bf16 sur les cinq premières trames audio pour une entrée de référence fixe. La correspondance exacte des jetons dès les premières trames permet de détecter une corruption systématique des logits — si le modèle quantifié produit des distributions de probabilité différentes, il divergera immédiatement du bf16 sur des entrées déterministes.

Porte de régression de performance : Le decode_tps par requête doit rester dans une marge de 5 % par rapport aux chiffres de base figés à chaque point de concurrence. Tout changement qui dégrade le débit au-delà de 5 % à n'importe quelle concurrence — c=1, c=16, c=64 — nécessite une justification explicite avant d'être fusionné. Cette porte protège contre les corrections de justesse qui ajouteraient silencieusement de la synchronisation à la boucle de décodage.

Les deux portes s'exécutent sur chaque modification de la pile d'inférence. Résultat : les poids du modèle S2.1 Pro Free sont identiques à ceux du niveau payant, et le chemin de service quantifié est validé par rapport à la base non quantifiée lors de chaque déploiement.


Clonage vocal à grande échelle : pourquoi l'efficacité de l'inférence est cruciale

Diagramme comparatif montrant le TTS standard (texte en entrée → modèle S2.1 Pro → sortie audio) et le clonage vocal (texte en entrée plus échantillon audio de référence → modèle S2.1 Pro avec conditionnement du locuteur → sortie vocale clonée)

Le clonage vocal de Fish Audio a toujours été gratuit — et il reste, selon notre propre évaluation et les retours des développeurs, le meilleur de sa catégorie. La cohérence du locuteur à travers 83 langues, la prosodie naturelle et la stabilité des performances selon les accents ne sont pas des fonctionnalités que nous avons ajoutées à un niveau payant. C'est la base. S2.1 Pro s'appuie sur Fish Speech S2 Pro, notre modèle de fondation à poids ouverts publié plus tôt cette année.

Ce que l'optimisation de l'inférence change, c'est l'économie du maintien de cet engagement à grande échelle. Les charges de travail de clonage vocal entraînent un coût par requête plus élevé que le TTS standard : chaque appel doit se conditionner sur un embedding de locuteur de référence, maintenir l'identité du locuteur sur des sorties de longueur variable, et faire les deux de manière cohérente dans toutes les langues. Sans les gains d'efficacité décrits dans cet article, le clonage vocal gratuit à l'échelle de la production nécessiterait de subventionner une charge de travail structurellement coûteuse. Avec eux, ce n'est plus nécessaire.

Trois optimisations sont particulièrement importantes pour le clonage vocal :

Le FP8 préserve le conditionnement du locuteur. La validation de la justesse exacte des jetons — qui détecte la corruption au niveau des logits — valide directement que la quantification ne dégrade pas le signal de l'embedding du locuteur. La cohérence du locuteur dans les sorties clonées correspond à la base de référence bf16.

Le batching continu gère les types de requêtes mixtes. Le trafic de clonage vocal en production mélange des requêtes conditionnées par une référence et des requêtes non conditionnées, des longueurs de sortie variées et des langues différentes. Le batching continu remplit le lot de décodage quel que soit le type de requête — il n'y a pas de pénalité pour l'hétérogénéité de la charge de travail.

La mise à l'échelle du débit par 52 rend la génération de masse viable. À 8 006 jetons/s sur un seul H200, la génération de grandes bibliothèques audio en voix clonée — livres audio, dialogues de jeux, contenu localisé à grande échelle — est économiquement viable au sein du niveau gratuit.

Le niveau gratuit n'inclut pas le clonage vocal parce que nous avons optimisé nos coûts pour pouvoir nous l'offrir. Nous l'incluons parce que cela a toujours été le produit — et le travail d'ingénierie décrit ici est ce qui nous permet de tenir cette promesse à mesure que l'utilisation augmente. Pour intégrer le clonage vocal dans les flux de travail des agents, consultez notre support MCP et compétences d'agent.

Clonez une voix en moins de 60 secondes → Essayer gratuitement


Infrastructure GPU : posséder l'intégralité de la pile

Matériel et approvisionnement

Notre cluster GPU compte environ 500 cartes réparties sur plusieurs centres de données. La topologie multi-DC était une décision d'approvisionnement avant d'être une décision de fiabilité : l'offre et les prix des GPU sont volatils, et le verrouillage sur un seul fournisseur signifie absorber directement cette volatilité. L'approvisionnement multi-fournisseurs et multi-DC couvre simultanément les risques de prix et les contraintes d'approvisionnement, au prix d'une complexité opérationnelle accrue.

Pour l'inférence, nous utilisons une flotte mixte. Le H200 SXM5 gère le service de production à haute concurrence où le débit global bsgemm FP8 domine. Les RTX 5090 et RTX 6000 PRO (sm_120a) servent les points de terminaison périphériques — à c=64, la 5090 mxfp8 atteint 5 869 jetons/s, soit environ 71 % du débit bsgemm du H200 pour un coût matériel par carte nettement inférieur.

Le déploiement sm_120a a nécessité un correctif non évident : la limite initiale cuda_graph_max_bs = 24 pour les GPU de 32 Go produisait une chute sévère du débit à haute concurrence — c=32 tombait à ~31 jetons/s/req, c=64 à ~35 jetons/s/req. Lever la limite à min(max_running_requests, 64) a permis de retrouver la courbe de débit complète. Le problème sous-jacent : la capture du graphe CUDA à bs=24 laissait le GPU sous-utilisé aux tailles de lot de décodage qui apparaissent réellement à c=32+.

Planification GPU : éliminer la capacité inactive

Schéma avant et après montrant la chronologie et la barre d'utilisation du GPU. Avant : les tâches d'inférence laissent ~50 % de vides inactifs. Après : l'inférence, l'entraînement et les tâches de nettoyage de données remplissent l'utilisation à ~90 %+

L'utilisation de base d'un GPU sur un cluster dédié uniquement à l'inférence est d'environ 50 %. Le trafic d'inférence est intrinsèquement irrégulier ; le GPU reste inactif pendant les heures creuses, entre les sessions d'entraînement et pendant les phases de chargement des jeux de données.

Nous gérons deux systèmes de planification parallèles — Kubernetes pour l'inférence, Slurm pour l'entraînement — avec un principe partagé : les tâches de nettoyage et de prétraitement des données s'exécutent comme un travail de remplissage élastique au niveau de priorité le plus bas dans les deux clusters. Les tâches de nettoyage occupent la capacité GPU inactive chaque fois que l'inférence ou l'entraînement ne l'utilisent pas. Elles sont interruptibles et peuvent reprendre là où elles s'étaient arrêtées (checkpointable), elles disparaissent donc immédiatement sans coût de justesse dès qu'un travail réel arrive.

Ordre de priorité : inférence > nettoyage dans le cluster K8s ; entraînement > nettoyage dans Slurm. L'autoscaler côté inférence utilise des signaux de trafic réel — et non des heuristiques basées sur le temps — de sorte que les tâches de nettoyage sont évincées dès que la charge augmente.

Résultat : une utilisation du GPU passant de ~50 % à ~90 % et plus. À l'échelle du cluster, cet écart divise environ par deux le coût effectif par requête d'inférence — le budget matériel est fixe, mais deux fois plus de requêtes sont servies avec.

Infrastructure réseau

Nous exploitons notre propre réseau : approvisionnement direct en bande passante auprès des FAI, numéro d'ASN, connectivité 300 Gbps et peering Cloudflare. Deux implications en termes de coûts pour le TTS spécifiquement.

Le transfert de données sortantes (egress) à l'échelle du TTS est non négligeable. Les tarifs d'egress des fournisseurs de cloud sont structurellement à marge élevée ; posséder la couche réseau supprime entièrement cette marge.

La latence est la seconde raison. Chaque milliseconde d'aller-retour réseau apparaît dans le TTFB perçu par l'utilisateur. Le peering Cloudflare place les points de terminaison de Fish Audio au plus près des utilisateurs acheminés via le réseau de Cloudflare — une fraction substantielle du trafic API mondial. Le déploiement multi-DC signifie que la plupart des requêtes atteignent un nœud d'inférence proche sans traverser l'intégralité de l'Internet public.

Stockage : architecture hiérarchisée

Les données d'entraînement, les checkpoints de modèles et le cache d'inférence ont des schémas d'accès et des exigences de coûts différents. Nous utilisons une architecture à trois niveaux :

  • Hot (NVMe flash) : données d'entraînement actives, poids des modèles pour le service
  • Warm (mixte flash/HDD) : checkpoints récents, jeux de données prétraités
  • Cold (cluster HDD Ceph auto-hébergé) : données d'entraînement historiques, stockage à long terme

Le niveau cold a remplacé le stockage objet tiers pour les données volumineuses. Une couche de cache local devant le stockage cold signifie que les lectures répétées — courantes dans les pipelines de données d'entraînement — sont servies depuis le NVMe plutôt que depuis le HDD cold.


Le résultat : ce que produit la pile technique

Schéma avant et après montrant que le même volume de requêtes nécessitait auparavant quatre GPU H200 à ~50 % d'utilisation, désormais géré par un seul H200 à ~90 %+ d'utilisation après une amélioration de l'efficacité par 4

À travers toutes les couches :

  • Noyaux FP8 personnalisés : 2,1 à 4,3 fois plus rapides que le cuBLAS standard sur les formes de décodage
  • Batching continu : débit multiplié par 52 de c=1 à c=64, augmentation de latence de seulement 37 ms
  • Planification GPU : utilisation de ~50 % → ~90 %+, divisant approximativement par deux le coût par requête
  • Infrastructure en propre : marge cloud supprimée du calcul, du réseau et du stockage

Combinés, le même volume de requêtes qui nécessitait auparavant quatre H200 fonctionne désormais sur un seul. L'amélioration de l'efficacité par 4 est ce qui rend le niveau gratuit économiquement viable — non pas une subvention, mais une réduction structurelle des coûts. La période d'accès gratuit reflète le fait que l'économie unitaire fonctionne ; consultez les Tarifs pour la disponibilité actuelle.


Comparaison de la pile d'inférence de Fish Audio

Données d'infrastructure basées sur la documentation publique, les dépôts GitHub et les blogs d'ingénierie en date de juin 2026.

Fish Audio S2.1 ProElevenLabsOpenAI TTSGoogle Cloud TTS
Architecture d'inférenceBatching continu (basé sur sglang)Non divulguéNon divulguéNon divulgué
Noyaux d'inférence personnalisés✅ fish-scales-ops (open source)Non divulguéNon divulguéNon divulgué
Quantification FP8✅ bsgemm + mxfp8Non divulguéNon divulguéNon divulgué
Infrastructure GPUPropre, ~500 cartes, multi-DCHébergé cloudPropre (Azure)Propre (TPU)
Pile de service open source✅ Partielle (fish-scales-ops)
Benchmarks de débit publiés✅ 8 006 jetons/s à c=64 (H200)Non publiésNon publiésNon publiés

Le schéma est cohérent : Fish Audio est le seul grand fournisseur de TTS à avoir documenté publiquement son architecture d'inférence, ouvert sa bibliothèque de noyaux en open source et publié des chiffres de débit concrets. "Non divulgué" n'est pas une critique — c'est une observation sur ce qui est vérifiable. Pour une évaluation indépendante de la qualité vocale entre fournisseurs, consultez notre comparaison de fournisseurs TTS à l'aveugle.


Ce qui est en open source

fish-scales-ops est disponible dès maintenant : FP8 GEMM et FlashAttention pour Hopper et Blackwell, de qualité production, compatibles avec la capture de graphes CUDA.

Si vous construisez une infrastructure d'inférence pour des modèles autorégressifs sur H200 ou RTX 5090/6000 PRO, l'écart de performance sur les formes de décodage par rapport aux bibliothèques standard est réel et les noyaux sont là pour le combler.

Contenu de la bibliothèque :

  • GEMM FP8 : bsgemm (1×128 act × 128×128 wgt) pour Hopper ; MXFP8 1×32 (OCP UE8M0) pour Blackwell
  • FlashAttention MXFP8 pour sm_120a : prefill contigu, paged-prefill (extension), paged decode avec GQA natif via diffusion (broadcast) K/V à pas nul (stride-0)
  • Entièrement compatible avec la capture de graphes CUDA

Et après ?

Le support du B300 est sur la feuille de route. Les cœurs tenseurs FP8 natifs et la bande passante NVLink 5 sur Blackwell repousseront encore la courbe de débit.

L'optimisation de l'inférence se poursuit. Les chiffres de benchmark figés sont une porte de régression, pas un objectif final. Chaque point de concurrence est un record à battre.

Une plus grande partie de la pile de service est candidate à l'open source à mesure qu'elle se stabilise — les modifications sglang_lite, la logique de batching spécifique à DualAR, la gestion des graphes CUDA sm_120a. L'infrastructure qui rend le niveau gratuit durable est la même infrastructure sur laquelle nous souhaiterions que la communauté s'appuie.


Premiers pas avec l'API TTS gratuite

Chaîne du modèle : s2.1-pro-free. Un seul changement d'en-tête par rapport à tout appel API Fish Audio existant.

python

import httpx

body = {
    "text": "Bonjour le monde !",
    "reference_id": "votre_id_modele",
    "format": "mp3",
}

with httpx.Client() as client:
    res = client.post(
        "https://api.fish.audio/v1/tts",
        headers={
            "Authorization": "Bearer <VOTRE_CLE_API>",
            "Content-Type": "application/json",
            "model": "s2.1-pro-free",
        },
        json=body,
    )

res.raise_for_status()

with open("output.mp3", "wb") as f:
    f.write(res.content)

JavaScript

import { writeFile } from "fs/promises";

const body = {
  text: "Bonjour le monde !",
  reference_id: "votre_id_modele",
  format: "mp3",
};

const res = await fetch("https://api.fish.audio/v1/tts", {
  method: "POST",
  headers: {
    Authorization: "Bearer <VOTRE_CLE_API>",
    "Content-Type": "application/json",
    model: "s2.1-pro-free",
  },
  body: JSON.stringify(body),
});

if (!res.ok) {
  throw new Error(`Échec de la requête TTS : ${res.status} ${await res.text()}`);
}

const buffer = Buffer.from(await res.arrayBuffer());
await writeFile("output.mp3", buffer);

83 langues. Pas de limite d'utilisation stricte. Pas de carte de crédit. Clonage vocal inclus.

Toutes les autres API TTS de pointe facturent dès le premier jeton. S2.1 Pro ne le fait pas.

Clonez une voix en moins de 60 secondes →

Documentation API complète →" , "image_alt": "Comment nous avons rendu S2.1 Pro gratuit — Reconstruction de la pile d'inférence à partir de zéro", "article_tags": ["Recherche"], "faq": [ { "question": "Qu'est-ce que le batching continu et pourquoi est-ce important pour le coût du TTS ?", "answer": "Le batching continu permet de maintenir la boucle de décodage du GPU active sans attendre qu'un lot complet soit terminé. Dans le batching statique, une seule requête lente retient toutes les autres requêtes du lot — le GPU reste inactif jusqu'à ce que la séquence la plus lente soit finie. Le batching continu ajoute de nouvelles requêtes au lot de décodage actif dès que des emplacements se libèrent, de sorte que l'utilisation du GPU reste élevée quelle que soit la variation de la longueur de sortie. Pour le TTS spécifiquement, où la longueur de sortie varie considérablement d'une requête à l'autre (une courte phrase vs un paragraphe), la différence d'utilisation entre le batching statique et continu est substantielle." }, { "question": "Pourquoi la quantification FP8 ne dégrade-t-elle pas la qualité vocale ?", "answer": "La quantification FP8 réduit la précision numérique des représentations des poids de 16 bits à 8 bits, ce qui peut introduire des régressions de qualité si elle est appliquée sans validation minutieuse. Notre validation exécute deux portes lors de chaque déploiement : une vérification de justesse exacte des jetons (le décodage glouton quantifié doit correspondre jeton pour jeton au bf16 sur les cinq premières trames audio d'une entrée de référence fixe) et une porte de régression du débit (le débit de décodage doit rester à moins de 5 % de la base de référence figée à chaque point de concurrence). La vérification de justesse détecte directement la corruption au niveau des logits — si la quantification dégrade les distributions de probabilité du modèle, cela se voit immédiatement sur des entrées déterministes. S2.1 Pro Free utilise des poids de modèle identiques à ceux du niveau payant ; la quantification n'intervient que dans la couche de service." }, { "question": "Comment l'inférence par lots affecte-t-elle la latence des requêtes individuelles ?", "answer": "À c=64 contre c=1, le TTFB augmente de 73 ms à 110 ms — soit une différence de 37 ms. Pour la plupart des charges de travail en production, cet écart est imperceptible. Le compromis est explicite : un débit global 52 fois plus élevé pour une latence supplémentaire de 37 ms par requête. Pour les applications sensibles à la latence comme les agents vocaux, un point de terminaison en temps réel séparé est disponible avec une architecture optimisée pour le TTFA plutôt que pour le débit — le prefill est entièrement retiré du chemin critique lors de l'ouverture de la connexion, et un ordonnanceur en ping-pong élimine les barrières hôtes par cycle." }, { "question": "Qu'est-ce que fish-scales-ops et qui devrait l'utiliser ?", "answer": "fish-scales-ops est la bibliothèque open source de Fish Audio pour le GEMM FP8 et FlashAttention, destinée aux architectures NVIDIA Hopper (H200) et Blackwell (RTX 5090, RTX 6000 PRO). Elle cible les formes de décodage à petit M (M ≤ 128) qui dominent l'inférence autorégressive — des formes pour lesquelles les bibliothèques standard comme cuBLAS et PyTorch ne sont pas optimisées. Si vous exécutez un modèle autorégressif (TTS, LLM ou autre) sur du matériel H200 ou Blackwell et que vous servez à une concurrence faible à moyenne, l'écart de performance sur les formes de décodage par rapport aux bibliothèques standard est réel. La bibliothèque est compatible avec la capture de graphes CUDA et testée en production sur l'infrastructure de service de Fish Audio." }, { "question": "En quoi l'infrastructure de Fish Audio diffère-t-elle de celle des fournisseurs de TTS hébergés sur le cloud ?", "answer": "La plupart des fournisseurs de TTS fonctionnent sur une infrastructure GPU gérée par le cloud (AWS, Azure, GCP) et répercutent les tarifs du cloud sur les coûts de l'API. Fish Audio possède son propre cluster GPU (~500 cartes, multi-DC), son infrastructure réseau (ASN, 300 Gbps, peering Cloudflare) et son stockage (Ceph auto-hébergé). Posséder la pile complète supprime la marge du cloud à chaque niveau — calcul, transfert de données et stockage — ce qui constitue un avantage structurel sur les coûts à grande échelle. Cela permet également des optimisations spécifiques au matériel (comme le travail sur les graphes CUDA sm_120a pour la RTX 6000 PRO) qui ne sont pas possibles dans un environnement cloud géré." } ] }```

Questions Fréquemment Posées

What is continuous batching and why does it matter to TTS cost?
Continuous batching keeps the GPU decode loop running without waiting for a full batch to complete. In static batching, a single slow request holds up every other request in the batch — the GPU idles until the slowest sequence finishes. Continuous batching adds new requests to the active decode batch as slots free up, so GPU utilization stays high regardless of output length variance. For TTS specifically, where output length varies significantly across requests (a short phrase vs. a paragraph), the utilization difference between static and continuous batching is substantial.
Why doesn't FP8 quantization degrade voice quality?
FP8 quantization reduces the numeric precision of weight representations from 16-bit to 8-bit, which can introduce quality regressions if applied without careful validation. Our validation runs two gates on every deployment: a token-exact correctness check (quantized greedy decode must match bf16 token-for-token on the first five audio frames of a fixed reference input) and a throughput regression gate (decode throughput must stay within 5% of frozen baseline at every concurrency point). The token-exact check catches logit-level corruption directly — if quantization is degrading the model's probability distributions, it shows up immediately on deterministic inputs. S2.1 Pro Free uses identical model weights to the paid tier; quantization occurs only in the serving layer.
How does batch inference affect latency for individual requests?
At c=64 versus c=1, TTFB increases from 73ms to 110ms — a 37ms difference. For most production workloads, that delta is imperceptible. The trade-off is explicit: 52× more aggregate throughput for 37ms additional per-request latency. For latency-sensitive applications like voice agents, a separate real-time endpoint is available with an architecture optimized for TTFA over throughput — prefill is taken off the critical path entirely at connection open, and a pingpong scheduler eliminates per-cycle host barriers.
What is fish-scales-ops and who should use it?
fish-scales-ops is Fish Audio's open-source FP8 GEMM and FlashAttention library for NVIDIA Hopper (H200) and Blackwell (RTX 5090, RTX 6000 PRO) architectures. It targets the small-M decode shapes (M ≤ 128) that dominate the autoregressive inference — shapes that standard libraries like cuBLAS and PyTorch are not optimized for. If you're running any autoregressive model (TTS, LLM, or otherwise) on H200 or Blackwell hardware and serving at low-to-medium concurrency, the decode-shape performance gap versus standard libraries is real. The library is CUDA Graph capture-safe and production-tested on Fish Audio's serving infrastructure.
How does Fish Audio's infrastructure differ from cloud-hosted TTS providers?
Most TTS providers run on cloud-managed GPU infrastructure (AWS, Azure, GCP) and pass cloud pricing through to API costs. Fish Audio owns its GPU cluster (~500 cards, multi-DC), network infrastructure (ASN, 300Gbps, Cloudflare peering), and storage (self-hosted Ceph). Owning the stack removes cloud markup from every layer — compute, egress, and storage — which is a structural cost advantage at scale. It also enables hardware-specific optimizations (like the sm_120a CUDA graph work for RTX 6000 PRO) that aren't possible in a managed cloud environment.
Shijia Liao

Shijia LiaoX

Founder & Chief-Scientist of Fish Audio.

Lire plus de Shijia Liao

Créez des voix qui semblent réelles

Commencez à générer un son de la plus haute qualité dès aujourd'hui.

Vous avez déjà un compte ? Se connecter