Découvrez Eleven v4Découvrez Eleven v4, notre modèle le plus expressif à ce jour.

Aller au contenu

Limitation de débit IA pour la voix : Concurrence, files d’attente et erreurs 429

Publié
Dernière mise à jour

ÉcouterÉcouter cet article

La plupart des équipes appliquent la limitation de débit IA à la voix comme pour les autres API : elles plafonnent les requêtes par minute, réessaient lorsque le serveur oppose un refus, puis passent à autre chose. Avec les charges de travail sur ElevenLabs, ce modèle échoue dès le premier pic de trafic, car la limite réellement atteinte est la concurrence, et non le nombre de requêtes.

Ce guide explique pourquoi la concurrence est la véritable contrainte, puis présente les modèles côté client qui permettent de rester dans cette limite. Des pools de concurrence bornés et de la gestion fluide des 429 à l'équité multi-tenant et aux seaux à jetons et à fuite, nous proposons des systèmes pratiques que vous pouvez mettre en œuvre. Chaque modèle est accompagné d'une implémentation TypeScript fonctionnelle à adapter.

Si vous créez des agents vocaux, des pipelines de narration ou tout autre système de production basé sur nos modèles et souhaitez passer à l'échelle, ce guide est fait pour vous.

En résumé

  • La limitation de débit IA pour la voix relève du contrôle de la concurrence, non du comptage des requêtes par minute.
  • Atteindre le plafond de limitation de débit ne rejette pas immédiatement le trafic. Les requêtes entrent plutôt dans une file d'attente prioritaire qui ajoute environ 50 ms.
  • Dépasser la capacité, même après la mise en file d'attente, entraîne une erreur HTTP 429.
  • Les WebSockets augmentent fortement la capacité effective, car seule la génération active est prise en compte dans votre limite.
  • Les systèmes multi-tenant nécessitent une couche d'équité supplémentaire : des seaux par tenant, une mise en file d'attente équitable pondérée, une marge de capacité réservée et une répartition entre les clés pour assurer l'isolation. 
  • Deux en-têtes de réponse, current-concurrent-requests et maximum-concurrent-requests, vous indiquent où vous en êtes avec la limitation de débit IA.

Pourquoi la limite porte sur la concurrence, et non sur les requêtes par minute

La concurrence correspond au nombre de requêtes en cours au même instant. Les requêtes par minute représentent le débit sur une période donnée. Comprendre cette distinction est important, car elle détermine le levier qui vous permet de rester dans votre limite.

Lorsque vous utilisez l'un des modèles ElevenLabs, la charge du serveur évolue avec le nombre d'utilisateurs simultanés. La génération audio occupe un slot pendant toute sa durée, laquelle varie selon la longueur de l'entrée, le modèle et la charge.

Un plafond de requêtes par minute ne vous indique pas combien de slots sont occupés à cet instant, alors que c'est la seule mesure suivie par le serveur.

Les limites par forfait et par famille de modèles

Votre budget de concurrence n'est pas un chiffre unique. Les limites de concurrence diffèrent selon le forfait et la famille de modèles. Par exemple, Speech to Text bénéficie d'une limite plus élevée que Text to Speech, car les requêtes de transcription sont généralement plus courtes et le système peut en absorber davantage simultanément.

Multilingual v2
Free
2
Starter
3
Creator
5
Pro
10
Scale
15
Business
15
Enterprise
Elevated
Flash
Free
4
Starter
6
Creator
10
Pro
20
Scale
30
Business
30
Enterprise
Elevated
STT
Free
8
Starter
12
Creator
20
Pro
40
Scale
60
Business
60
Enterprise
Elevated
Realtime STT
Free
6
Starter
9
Creator
15
Pro
30
Scale
45
Business
45
Enterprise
Elevated
Queue weight
Free
3
Starter
4
Creator
5
Pro
5
Scale
5
Business
5
Enterprise
6

La limite s'applique par famille de modèles. Si vous utilisez Flash pour vos agents et Multilingual v2 pour la narration, vous disposez simultanément de deux budgets distincts. Les chiffres actuels par forfait et la section sur la concurrence sont documentés sur la page des modèles.

Que se passe-t-il lorsque vous atteignez la limite de concurrence ?

Atteindre la limite de concurrence ne rejette pas immédiatement le trafic. Le système se dégrade progressivement grâce à une file d'attente prioritaire et ne passe au rejet complet que si vous dépassez toujours la capacité totale de limitation de débit.

Tant que vous restez sous votre limite, les requêtes s'exécutent immédiatement. Lorsque vous l'atteignez, les requêtes suivantes entrent dans une file ordonnée selon le niveau de priorité de votre forfait. La file ajoute généralement environ 50 ms de latence : un bref dépassement reste donc largement invisible pour les utilisateurs.

Si le système est encore au-delà de sa capacité après la mise en file d'attente, vous recevez une erreur HTTP 429. C'est le signal qu'il faut ralentir plutôt que réessayer immédiatement. Le niveau de priorité du tableau détermine l'ordre de vos requêtes en attente par rapport aux autres trafics : les forfaits supérieurs quittent la file plus rapidement.

HTTP ou WebSocket : incidence de chaque protocole sur votre limite

Le transport choisi influe directement sur la limitation de débit et votre budget. Une même conversation entrante peut consommer des parts très différentes de votre budget de concurrence selon qu'elle passe par HTTP ou WebSocket.

Avec HTTP, chaque requête compte individuellement dans votre limite de concurrence pendant toute sa durée. Avec un WebSocket, seul le temps durant lequel le modèle génère activement de l'audio compte. Un WebSocket ouvert mais inactif ne compte pratiquement pas.

Pour un agent vocal, une conversation comporte de longues périodes où personne ne parle et où le modèle ne génère rien. Avec HTTP, vous occuperiez un slot pendant toute la durée de la requête à chaque tour. Avec un WebSocket, le slot n'est consommé que pendant les millisecondes de génération active, ce qui permet de répartir un slot de concurrence entre de nombreuses conversations. 

Consultez le guide WebSocket TTS en temps réel pour les détails du protocole. Pour le trafic interactif, les WebSockets constituent le bon choix par défaut.

Pourquoi environ 5 requêtes simultanées peuvent prendre en charge environ 100 diffusions

Les calculs liés à la concurrence semblent contre-intuitifs tant que vous ne tenez pas compte du temps de lecture. La génération est bien plus rapide que la lecture, et un slot n'est activement occupé que pendant la génération de l'audio. C'est précisément cet écart qui permet à un petit budget de servir une large audience.

Une requête qui ne prend qu'une fraction de seconde à générer produit plusieurs secondes d'audio que l'auditeur écoute ensuite. Pendant la lecture, le slot est libéré et disponible pour d'autres auditeurs.

En règle générale, une limite de concurrence de 5 peut prendre en charge environ 100 diffusions audio simultanées. Le nombre exact dépend de la voix, du rythme de parole et de la durée des silences entre les énoncés.

Les en-têtes qui indiquent où vous en êtes

Vous n'avez pas besoin de déduire votre position par rapport à votre limite. Chaque réponse contient deux valeurs que vous pouvez utiliser pour mesurer votre marge de capacité au lieu de l'estimer.

Recherchez ces deux en-têtes :

  • current-concurrent-requests : combien de requêtes sont actuellement en cours ?
  • maximum-concurrent-requests : votre limite pour cette famille de modèles.

Ensemble, ces en-têtes offrent une vue en temps réel de votre utilisation actuelle et de la capacité disponible. Vous ne devriez pas avoir à vous fier à des estimations avant de rencontrer des limites de débit IA.

Stratégies côté client pour la limitation de débit IA

Quatre mécanismes couvrent presque tous les scénarios de limitation de débit IA :

  • Un seau à jetons : si des jetons sont disponibles, il laisse les requêtes se poursuivre. Sa capacité se reconstitue au fil du temps, ce qui lui permet d'absorber de courts pics sans atteindre les limites de débit.
  • Un seau à fuite : il lisse le trafic entrant vers un débit de sortie fixe, ce qui empêche les pics soudains de submerger vos systèmes en aval.
  • Un pool de concurrence borné : il plafonne le nombre total de requêtes pouvant être actives simultanément, afin de ne jamais dépasser les limites de requêtes simultanées.
  • Un backoff exponentiel avec jitter complet : il augmente progressivement le délai entre les requêtes échouées pour éviter que tous les clients réessaient en même temps.

Les sections suivantes montrent comment les mettre en place un à un, en commençant par celui qui correspond le plus directement à la limite de concurrence.

Tous les extraits ci-dessous supposent un seul client, initialisé une fois :

import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient({ apiKey: process.env.ELEVENLABS_API_KEY });

Concurrence bornée : le mécanisme adapté à la limite

Puisque le serveur mesure la concurrence, le contrôle côté client le plus direct consiste à utiliser un pool de workers borné, qui plafonne le nombre de requêtes en cours simultanément. Fixez ce plafond légèrement sous la limite de votre forfait afin de garder de la place pour la file prioritaire et le jitter.

async function pool<T, R>(
  items: T[],
  maxInFlight: number,
  worker: (item: T) => Promise<R>,
): Promise<R[]> {
  const results: R[] = new Array(items.length);
  let next = 0;

  async function run(): Promise<void> {
    while (next < items.length) {
      const i = next++;
      results[i] = await worker(items[i]); // never more than maxInFlight of these run at once
    }
  }

  await Promise.all(
    Array.from({ length: Math.min(maxInFlight, items.length) }, run),
  );
  return results;
}

async function synthesize(text: string): Promise<Buffer> {
  const stream = await elevenlabs.textToSpeech.stream("JBFqnCBsd6RMkjVDRZzb", {
    text,
    modelId: "eleven_flash_v2_5",
    outputFormat: "mp3_44100_128",
  });
  const chunks: Buffer[] = [];
  for await (const chunk of stream) chunks.push(Buffer.from(chunk));
  return Buffer.concat(chunks);
}

// Plan Flash limit is, say, 10. Stay under it.
const texts = Array.from({ length: 50 }, (_, i) => `Sentence number ${i}.`);
const audio = await pool(texts, 8, synthesize); // never more than 8 in flight

Seau à jetons : autoriser les pics, plafonner la moyenne

Un seau à jetons peut contenir jusqu'à capacity jetons et se recharge de refillRate jetons par seconde. Chaque requête consomme un jeton : le seau autorise donc de courts pics jusqu'à sa taille, tout en limitant le débit sur la durée. 

C'est l'outil adapté pour lisser l'arrivée soudaine d'une file de tâches, afin de ne pas tout lancer simultanément et faire grimper la concurrence.

class TokenBucket {
  private tokens: number;
  private updated = performance.now();

  constructor(private capacity: number, private refillPerSec: number) {
    this.tokens = capacity;
  }

  private refill(): void {
    const now = performance.now();
    const elapsed = (now - this.updated) / 1000;
    this.tokens = Math.min(this.capacity, this.tokens + elapsed * this.refillPerSec);
    this.updated = now;
  }

  tryAcquire(cost = 1): boolean {
    this.refill();
    if (this.tokens >= cost) {
      this.tokens -= cost;
      return true;
    }
    return false;
  }

  timeUntil(cost = 1): number {
    this.refill();
    return this.tokens >= cost ? 0 : ((cost - this.tokens) / this.refillPerSec) * 1000;
  }
}

Seau à fuite : imposer un débit constant

Dans certains cas, vous ne souhaitez tolérer aucun pic. Un seau à fuite admet les tâches à un rythme fixe et constant, quelle que soit l'irrégularité des entrées. C'est le meilleur choix lorsque le système en aval préfère une charge lisse et prévisible à des pics occasionnels.

Par exemple, lorsque vous choisissez délibérément de rester largement dans un petit budget de concurrence partagé avec d'autres services.

class LeakyBucket {
  private next = performance.now();
  constructor(private intervalMs: number) {} // admit at most one item per intervalMs

  async acquire(): Promise<void> {
    const now = performance.now();
    const wait = Math.max(0, this.next - now);
    this.next = Math.max(now, this.next) + this.intervalMs;
    if (wait > 0) await new Promise((r) => setTimeout(r, wait));
  }
}

Backoff exponentiel avec jitter complet

Lorsqu'une requête échoue avec un statut réessayable, réessayer immédiatement aggrave la situation. Le backoff espace les tentatives, et le jitter complet répartit aléatoirement chaque délai sur tout l'intervalle, évitant que de nombreux clients réessaient de manière synchronisée et recréent le pic à l'origine de l'échec.

L'extrait ci-dessous fait référence à RetryableError, une petite classe qui contient le statut en échec et toute valeur Retry-After. Elle est définie dans la section suivante sur la gestion fluide des 429.

async function withBackoff<T>(
  call: () => Promise<T>,
  opts: { maxAttempts?: number; baseMs?: number; capMs?: number } = {},
): Promise<T> {
  const { maxAttempts = 5, baseMs = 500, capMs = 20_000 } = opts;
  let attempt = 0;
  for (;;) {
    try {
      return await call();
    } catch (e) {
      if (!(e instanceof RetryableError) || ++attempt >= maxAttempts) throw e;
      // honor Retry-After if present; otherwise capped exponential growth with full jitter
      const delay =
        e.retryAfterMs ?? Math.random() * Math.min(capMs, baseMs * 2 ** attempt);
      await new Promise((r) => setTimeout(r, delay));
    }
  }
}

Gestion fluide des 429 : que faire lorsque vous atteignez le plafond

Un code 429 signifie que vous étiez au-delà de la capacité, même après la file prioritaire. La bonne réponse est donc de ralentir plutôt que de réessayer plus agressivement. Il existe quatre façons de le gérer, qui se résument à quatre stratégies :

  • Détection
  • Respect de Retry-After
  • Signalement de la contre-pression
  • Prévention des tempêtes de tentatives avec un disjoncteur

Examinons-les plus en détail.

La première est la détection. Traitez les HTTP 429, ainsi que les 500, 502, 503 et 504 transitoires, comme réessayables, et les 400, 401, 403 et 422 comme non réessayables. Réessayer une requête malformée ou non autorisée ne réussira jamais et ne fait que gaspiller un slot.

La deuxième consiste à respecter Retry-After. Si la réponse contient cet en-tête, respectez-le exactement au lieu de calculer votre propre délai. Le serveur vous indique quand il prévoit de disposer de capacité et le sait mieux que votre formule exponentielle. N'utilisez un backoff avec jitter qu'en l'absence de cet en-tête.

class RetryableError extends Error {
  constructor(public status: number, public retryAfterMs?: number) {
    super(`retryable ${status}`);
  }
}

function classify(resp: Response): void {
  if ([429, 500, 502, 503, 504].includes(resp.status)) {
    const ra = resp.headers.get("retry-after");
    throw new RetryableError(resp.status, ra ? Number(ra) * 1000 : undefined);
  }
  if (!resp.ok) throw new Error(`non-retryable ${resp.status}`);
}

Le troisième axe consiste à signaler la contre-pression. Ne laissez pas les tentatives s'accumuler de manière invisible. Si la profondeur de votre file ou la marge de capacité mesurée indique que vous ne pourrez pas traiter une nouvelle requête prochainement, rejetez-la à la périphérie avec un signal clair pour l'appelant, plutôt que d'accepter un travail que vous ne pouvez pas effectuer.

Le quatrième axe consiste à éviter les tempêtes de tentatives à l'aide d'un disjoncteur. Si les échecs franchissent un seuil, ouvrez le circuit et échouez rapidement pendant une période de refroidissement, au lieu d'envoyer des requêtes dont vous prévoyez l'échec. Après cette période, envoyez quelques requêtes de test : si elles réussissent, fermez le circuit.

class CircuitBreaker {
  private failures = 0;
  private openedAt: number | null = null;
  constructor(private threshold = 5, private cooldownMs = 10_000) {}

  allow(): boolean {
    if (this.openedAt === null) return true;
    if (performance.now() - this.openedAt >= this.cooldownMs) {
      this.openedAt = null; // half-open: allow a probe
      this.failures = 0;
      return true;
    }
    return false;
  }

  record(ok: boolean): void {
    if (ok) {
      this.failures = 0;
      this.openedAt = null;
    } else if (++this.failures >= this.threshold) {
      this.openedAt = performance.now();
    }
  }
}

Modèles de quotas multi-tenant pour la limitation de débit IA

Jusqu'ici, tout suppose une application unique avec un budget unique. Lorsque vous créez un SaaS sur ElevenLabs, le problème change : votre budget de concurrence est partagé entre tous vos propres clients, et le traitement par lots d'un tenant ne doit pas priver tous les autres tenants de leur trafic en direct. Vous avez besoin d'une couche d'équité entre vos tenants et l'unique limite amont.

La base repose sur des seaux à jetons par tenant. Attribuez à chaque tenant son propre seau, dimensionné selon ses droits, et n'admettez une requête que lorsque le seau du tenant et un limiteur global l'autorisent tous les deux.

class MultiTenantAdmission {
  private tenantBuckets = new Map<string, TokenBucket>();
  constructor(private globalMaxInFlight: number) {}

  private bucket(tenant: string): TokenBucket {
    let b = this.tenantBuckets.get(tenant);
    if (!b) {
      // Each tenant: burst of 5, sustained 2 starts/sec. Tune per tier.
      b = new TokenBucket(5, 2);
      this.tenantBuckets.set(tenant, b);
    }
    return b;
  }

  async run<R>(tenant: string, work: () => Promise<R>): Promise<R> {
    const b = this.bucket(tenant);
    if (!b.tryAcquire()) {
      throw new RetryableError(429, b.timeUntil());
    }
    // ... then admit through the global limiter (e.g. the bounded pool above)
    return work();
  }
}

Les seaux empêchent chaque tenant de dépasser ses droits, mais ils ne déterminent pas qui l'emporte lorsque les tenants se disputent le limiteur global. Pour cela, utilisez une mise en file d'attente équitable pondérée. 

N'appliquez pas le principe du premier arrivé, premier servi : un pic d'un tenant pourrait monopoliser les slots. Maintenez une file par tenant et répartissez les tâches proportionnellement au poids de chacun, afin qu'un tenant payant bénéficie d'une part plus importante de la capacité disputée qu'un tenant gratuit.

En plus de l'équité, réservez une marge de capacité. Ne laissez jamais le trafic normal consommer 100 % de la limite de concurrence. Conservez-en une part, par exemple 15 à 20 %, comme tampon pour les requêtes interactives sensibles à la latence et pour la file prioritaire.

Lorsque l'équité au sein d'un budget unique ne suffit plus, répartissez la charge entre plusieurs Workspaces ou clés. Un budget de concurrence unique finit par devenir le goulot d'étranglement, quelle que soit l'équité de sa répartition. 

À ce stade, séparez les charges de travail entre des Workspaces distincts ou des clés API dotées de leurs propres budgets : par exemple, une clé pour le trafic d'agents en temps réel et une autre pour la narration en arrière-plan, afin qu'un retard de narration n'affecte pas la capacité des agents.

Les Workspaces vous permettent aussi d'appliquer des restrictions de portée, des quotas de crédits et des contrôles par clé, décrits dans la documentation d'authentification.

Surveiller l'utilisation de votre concurrence

Aucun de ces éléments ne peut être ajusté sans mesure : vous ne pouvez pas gérer une marge de capacité que vous ne mesurez pas. Enregistrez current-concurrent-requests et maximum-concurrent-requests sur chaque réponse, étiquetés par famille de modèles, et émettez le ratio d'utilisation sous forme de jauge.

function recordHeadroom(resp: Response, metrics: Metrics): void {
  const cur = Number(resp.headers.get("current-concurrent-requests"));
  const max = Number(resp.headers.get("maximum-concurrent-requests"));
  if (Number.isFinite(cur) && Number.isFinite(max)) {
    metrics.gauge("el.concurrency.current", cur);
    metrics.gauge("el.concurrency.max", max);
    if (max > 0) metrics.gauge("el.concurrency.utilization", cur / max);
  }
}

Quatre signaux à suivre :

  • Utilisation (actuelle / maximale).
  • Taux de 429 en proportion du total des requêtes.
  • Profondeur des tentatives, soit le nombre de tentatives par requête logique.
  • Temps jusqu'au premier audio, mesuré depuis votre application, et non à partir des chiffres d'inférence du modèle. Consultez la section sur la compréhension de la latence pour savoir ce que comprend le TTFA.

Un système sain maintient son utilisation confortablement sous la saturation et ne rencontre des 429 que lors de pics occasionnels. Surveiller ces signaux vous donne de la visibilité sur la pression liée à la limitation de débit, bien avant qu'elle ne provoque une indisponibilité.

Quand aller au-delà de la limitation de débit côté client

Les modèles côté client peuvent accomplir beaucoup, mais la demande continue finira par les dépasser. Lorsque cela arrive, il est temps d'apporter des changements qui réduisent à la fois le coût et les efforts. 

Chacune des étapes suivantes vous apportera de la capacité supplémentaire.

Commencez par passer de HTTP aux WebSockets pour le trafic interactif. Si vos agents ou cas d'usage en direct fonctionnent via HTTP, basculer vers un WebSocket modifie le décompte afin que seule la génération active soit prise en compte. Pour les charges conversationnelles, cela multiplie souvent la capacité effective sans changer de forfait, car les périodes d'inactivité de la conversation cessent de consommer des slots.

Si vos pics sont irréguliers, mais que votre charge moyenne respecte le budget, un seau à jetons ou à fuite associé à un pool borné ramène les pics vers la moyenne.

Choisissez ensuite le bon modèle. Une génération plus rapide occupe chaque slot moins longtemps, ce qui augmente le nombre de diffusions qu'une limite de concurrence fixe peut prendre en charge. Eleven Flash v2.5 est l'option à la latence la plus faible pour le temps réel. L'associer à un Instant Voice Clone ou à une voix par défaut évite la surcharge par génération des clones vocaux professionnels.

N'envisagez l'upgrade du forfait qu'après cela. Lorsque votre demande continue dépasse réellement le budget, malgré un client bien configuré, un forfait supérieur augmente à la fois la limite de concurrence par modèle et votre priorité dans la file. Comparez les niveaux sur la page des tarifs de l'API.

Si vous avez besoin de limites supérieures à celles publiées, les forfaits Enterprise proposent des limites de concurrence élevées et personnalisées, ainsi que la priorité maximale dans la file. Des contrôles supplémentaires sont disponibles pour les cas d'usage éligibles, comme la liste blanche d'adresses IP, en préversion Enterprise, et les modes zéro rétention. Contactez votre responsable de compte pour augmenter vos limites.

Récapitulatif des points essentiels sur la limitation de débit IA 

L'erreur fondamentale consiste à traiter la limitation de débit de l'IA vocale comme un comptage de requêtes. Tout repose ici sur le contrôle de la concurrence. Le chiffre qui détermine votre réussite est le nombre de requêtes générant de l'audio au même instant et la durée pendant laquelle chacune occupe son slot.

Construisez votre client en tenant compte de cette réalité. 

Plafonnez les requêtes en cours avec un pool borné, contrôlez les admissions avec un seau à jetons ou à fuite, réessayez avec un backoff exponentiel plafonné et un jitter complet, respectez Retry-After et interrompez le circuit avant qu'une tempête de tentatives ne se forme. 

Pour les systèmes multi-tenant, ajoutez des seaux par tenant, une équité pondérée, une marge de capacité réservée et une répartition pour l'isolation. Surveillez les en-têtes current-concurrent-requests et maximum-concurrent-requests, et déclenchez des alertes sur la tendance d'utilisation plutôt que sur les échecs. 

Lorsque vous avez réellement besoin de davantage de capacité, procédez dans l'ordre : WebSockets et meilleur comportement côté client d'abord, puis le bon modèle, ensuite l'upgrade du forfait et enfin les limites Enterprise.

Créez des applications vocales avec ElevenAPI

Une limitation de débit IA adaptée à la production commence par le bon transport, le bon modèle et des en-têtes qui vous indiquent précisément où vous en êtes.

ElevenAPI propose des modèles à faible latence comme Eleven Flash v2.5, le streaming WebSocket en temps réel, Speech to Text et les API Text to Speech, ainsi que des en-têtes de concurrence dans chaque réponse qui vous permettent de créer des agents vocaux évolutifs tout en respectant vos limites. 

Associées aux stratégies de limitation de débit IA présentées dans cet article, ces fonctionnalités vous permettent d'offrir des expériences vocales réactives tout en maintenant des performances prévisibles, même sous charge. 

Explorez ElevenAPI pour découvrir toute la gamme de modèles en action, ou créez un compte pour commencer à développer avec ElevenLabs dès aujourd'hui.

FAQ sur la limitation de débit IA

Rédigé par

Tadas Petra est ingénieur en relations développeurs et aide les développeurs à utiliser la suite de produits ElevenLabs. Il est aussi le fondateur de Hungrimind, une plateforme d’apprentissage pour développeurs. Auparavant, il était Lead Developer Advocate chez Agora et formateur chez Zero To Mastery.

Articles similaires

Créez avec l'audio IA de la plus haute qualité