ITSkillsCenter
Intelligence Artificielle

Whisper en local ou en API : choisir selon latence et coût

9 min de lecture

📍 Guide principal de la série : Agents vocaux IA en 2026 : architecture, modèles, latence.

Whisper est devenu le standard de fait du speech-to-text depuis sa publication par OpenAI en 2022. En 2026, il reste le bon choix par défaut pour la transcription d’agents vocaux, mais le bon modèle et le bon mode de déploiement dépendent étroitement de votre profil d’usage. Ce tutoriel benchmarke côte à côte une exécution locale via faster-whisper et l’API gpt-4o-transcribe, mesure les deux dimensions qui comptent (latence et coût par minute), et propose une grille de décision concrète.

Prérequis

  • Python 3.10+, idéalement 3.12
  • Pour le local : GPU NVIDIA avec au moins 12 Go de VRAM (RTX 3060 minimum), ou CPU récent pour les petits modèles
  • CUDA 12.x et cuDNN installés, ou ROCm pour AMD (support partiel)
  • Une clé API OpenAI active
  • Un fichier audio de test (MP3, WAV ou FLAC) d’environ 5 minutes
  • Niveau attendu : Python intermédiaire, notions de GPU
  • Temps estimé : 60 minutes

Étape 1 — Décider entre local et API : la grille de choix

Avant d’installer quoi que ce soit, il faut clarifier l’arbitrage. Quatre dimensions structurent la décision : la latence visée, le volume mensuel, la sensibilité des données et la qualité linguistique attendue. Le tableau ci-dessous résume les seuils de bascule.

Critère API (gpt-4o-transcribe) Local (faster-whisper large-v3)
Latence streaming partiel 150-200 ms 80-150 ms (RTX 3060)
Coût par minute 0,006 USD (0,003 mini) 0 + amortissement matériel
Seuil de rentabilité < 1 200 min/mois ≥ 5 000 min/mois
Confidentialité Audio sur serveurs OpenAI Aucune sortie réseau
Qualité français WER ~6-8 % WER ~7-9 % (large-v3)
Diarisation Native, même prix Plugin externe (pyannote)

En pratique, l’API gagne pour 80 % des projets en démarrage : zéro infrastructure, qualité supérieure, prix marginal. Le local devient pertinent dès qu’on dépasse quelques milliers de minutes par mois, ou si la confidentialité interdit l’envoi d’audio brut à un tiers. Les deux étapes suivantes installent les deux options pour pouvoir les comparer empiriquement sur votre matériel et vos données.

Étape 2 — Installer faster-whisper en local

faster-whisper de SYSTRAN ré-implémente Whisper sur CTranslate2, ce qui le rend 4 fois plus rapide que openai/whisper à qualité équivalente, avec une consommation mémoire divisée par deux. Sur GPU, il supporte la quantization int8 et float16 ; sur CPU, l’int8 ramène une transcription en temps quasi-réel pour les petits modèles.

python -m venv .venv && source .venv/bin/activate
pip install faster-whisper
# Pour GPU NVIDIA, vérifier que cuDNN est dans le PATH
# Sur Linux : sudo apt-get install -y libcudnn8 libcublas-12-3

L’installation télécharge environ 80 Mo. Au premier appel, le modèle (par exemple large-v3 à 1,5 Go) se télécharge depuis Hugging Face vers ~/.cache/huggingface. Vérifier que le GPU est bien détecté : python -c "import ctranslate2; print(ctranslate2.get_supported_compute_types('cuda'))" doit lister float16 et int8_float16. Si la commande renvoie une liste vide, c’est que CUDA ou cuDNN ne sont pas correctement chargés.

Étape 3 — Premier benchmark : transcription d’un fichier

Le code suivant transcrit un fichier audio et imprime chaque segment avec ses bornes temporelles. C’est la base à partir de laquelle on instrumentera les mesures de latence.

# bench_local.py
import time
from faster_whisper import WhisperModel

model = WhisperModel(
    "large-v3",
    device="cuda",
    compute_type="float16",   # int8_float16 pour économiser la VRAM
)

t0 = time.perf_counter()
segments, info = model.transcribe(
    "sample_5min.mp3",
    beam_size=5,
    language="fr",
    vad_filter=True,
)

text = []
for seg in segments:
    text.append(seg.text)
elapsed = time.perf_counter() - t0
print(f"Audio: {info.duration:.1f}s | Transcription: {elapsed:.1f}s "
      f"| RTF={elapsed/info.duration:.3f}")
print(" ".join(text))

Sur une RTX 3060 avec un fichier de 5 minutes, la durée de transcription tourne autour de 45 secondes, soit un real-time factor de 0,15 — exactement la valeur publique annoncée par SYSTRAN. Le RTF est la métrique qui compte : 0,15 signifie qu’il faut 0,15 seconde de calcul par seconde d’audio, donc on peut transcrire sept flux temps réel en parallèle sur la même carte. vad_filter=True active le VAD intégré qui saute les silences et fait gagner 20 à 40 % sur les enregistrements bavards.

Étape 4 — Mesurer le streaming partiel en temps réel

Pour un agent vocal, on n’attend pas la fin du fichier : on transcrit chunk par chunk au fur et à mesure que l’utilisateur parle. faster-whisper fournit un mode generator qui rend les segments dès qu’ils sont stables.

# streaming_local.py
import asyncio, time
from faster_whisper import WhisperModel

model = WhisperModel("large-v3", device="cuda", compute_type="float16")

async def stream_chunks(audio_chunks):
    buffer = b""
    for chunk in audio_chunks:
        buffer += chunk
        # toutes les 0,5 s (8000 samples à 16 kHz mono Int16)
        if len(buffer) >= 16000:
            t0 = time.perf_counter()
            segments, _ = model.transcribe(buffer, beam_size=1, language="fr")
            for s in segments:
                print(f"+{(time.perf_counter()-t0)*1000:.0f}ms : {s.text}")
            buffer = b""

En pratique, on lit l’audio depuis un WebSocket (LiveKit, Twilio Media Streams) et on appelle transcribe sur les fenêtres glissantes. La latence par chunk de 500 ms est typiquement de 80 à 120 ms sur RTX 3060. beam_size=1 est un compromis pertinent en streaming : la qualité baisse marginalement par rapport à beam_size=5, mais on gagne 30 à 50 ms par chunk — précieux dans le budget temps réel de l’agent.

Étape 5 — Brancher l’API gpt-4o-transcribe

Côté API, le SDK officiel d’OpenAI fournit un client minimal. Le modèle gpt-4o-transcribe remplace en pratique whisper-1 au même tarif tout en supportant la diarisation et un meilleur taux d’erreur sur les langues non-anglo. gpt-4o-mini-transcribe est facturé moitié prix pour une qualité légèrement inférieure.

# bench_api.py
import time
from openai import OpenAI
client = OpenAI()

t0 = time.perf_counter()
with open("sample_5min.mp3", "rb") as f:
    transcript = client.audio.transcriptions.create(
        model="gpt-4o-transcribe",
        file=f,
        language="fr",
        response_format="text",
    )
print(f"Latence: {(time.perf_counter()-t0):.1f}s")
print(transcript)

Sur le même fichier de 5 minutes, l’API renvoie typiquement la transcription complète en 25 à 35 secondes selon la charge réseau, soit un RTF apparent de 0,08 à 0,12. Pour le streaming, l’endpoint /v1/audio/transcriptions accepte depuis fin 2025 un mode chunked transfer encoding qui rend les segments en flux ; en pratique, on lui préfère le passage par gpt-realtime ou par LiveKit qui s’occupe de la mécanique du streaming.

Étape 6 — Comparer côté qualité (WER)

Le seul vrai juge entre local et API est le taux d’erreur sur vos données. La métrique standard est le WER (word error rate). On la calcule sur un échantillon de 30 minutes étiqueté à la main pour chaque modèle.

pip install jiwer
from jiwer import wer
reference = "le texte exact prononcé dans l'enregistrement"
hypothesis = "le texte produit par le modèle"
print(f"WER: {wer(reference, hypothesis)*100:.2f}%")

Sur des enregistrements de centre d’appels en français standard, on observe couramment 4-5 % de WER sur gpt-4o-transcribe et large-v3 sur les benchmarks publics MLS et FLEURS. L’écart se creuse sur les locuteurs avec accent, les bruits de fond ou les superpositions de voix : gpt-4o-transcribe peut grimper à 10-15 % de WER là où large-v3 peut atteindre 15-20 %. Pour des cas d’usage métier exigeants, le test sur vos données reste obligatoire — les benchmarks publics ne reflètent pas toujours votre acoustique.

Étape 7 — Choisir le bon modèle local selon le matériel

faster-whisper expose plusieurs tailles de modèles. La taille adéquate dépend du couple VRAM disponible / qualité acceptée.

Modèle Taille VRAM (fp16) WER fr Cas typique
tiny 39 M ~1 Go 22-28 % Dictation rapide, puces ARM
base 74 M ~1,5 Go 15-19 % Sous-titrage approximatif
small 244 M ~2 Go 10-13 % Voix claire, conversation 1-1
medium 769 M ~5 Go 7-9 % Bon compromis sur RTX 3060
large-v3 1 550 M ~10 Go 4-5 % Production sur GPU dédié
large-v3-turbo 809 M ~6 Go 5-6 % Quasi-large, 2× plus rapide

Pour la majorité des cas d’usage français, large-v3-turbo est le sweet spot en 2026 : qualité proche du large-v3 standard, vitesse divisée par deux, VRAM divisée par deux. Sur GPU desktop limité (RTX 3060), il permet de servir trois flux temps réel simultanés avec une marge confortable.

Étape 8 — Mettre en place une bascule API ↔ local

En production, la stratégie qui fonctionne le mieux n’est pas un choix exclusif mais une bascule conditionnelle : API par défaut, local en fallback (ou inversement). Le pattern de service ci-dessous l’illustre.

# transcriber.py
import os
from openai import OpenAI

class Transcriber:
    def __init__(self, prefer="api"):
        self.prefer = prefer
        self._openai = OpenAI()
        self._local = None  # lazy load
    def _load_local(self):
        if self._local is None:
            from faster_whisper import WhisperModel
            self._local = WhisperModel("large-v3-turbo", device="cuda")
    def transcribe(self, audio_bytes, language="fr"):
        if self.prefer == "api":
            try:
                return self._openai.audio.transcriptions.create(
                    model="gpt-4o-transcribe",
                    file=("a.wav", audio_bytes),
                    language=language,
                ).text
            except Exception:
                self._load_local()
                segs, _ = self._local.transcribe(audio_bytes, language=language)
                return " ".join(s.text for s in segs)

Le pattern API d’abord, local en secours fonctionne particulièrement bien quand le local sert de filet de sécurité contre les coupures réseau ou les rate limits temporaires de l’API. À l’inverse, certaines architectures préfèrent local d’abord, API si la confiance est faible : on transcrit en local, et seulement si le score de confiance descend sous un seuil on rejoue le segment sur l’API pour vérifier. Le coût marginal reste ainsi bas tout en gardant la qualité maximale sur les segments douteux.

Erreurs fréquentes

Symptôme Cause Solution
« Could not load library libcudnn » cuDNN absent ou incompatible Installer cuDNN 8.x correspondant à votre CUDA
RTF > 1 sur GPU compute_type=float32 par défaut Forcer float16 ou int8_float16
Hallucinations sur silence Whisper invente sur audio vide Activer vad_filter=True
WER catastrophique sur dialecte Modèle pas spécialisé Fine-tuner sur 5-10 h de données étiquetées
Coût API surprise Pas de monitoring des minutes envoyées Mettre en place un compteur côté client
Audio chopped en streaming Chunks < 1 s + pas d’overlap Fenêtre glissante 1,5 s avec 200 ms d’overlap

À lire ensuite

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité