DEV-AI
← Retour au blog

Whisper Python : transcription audio gratuite en français

Publié le 12 mars 2026 — Par l'équipe DEV-AI

Whisper Python — transcription audio gratuite en français
En résumé : OpenAI Whisper est la référence open-source pour la transcription audio en Python. Gratuit, multilingue, sans clé API, excellent en français. Ce guide couvre tout : installation, modèles, faster-whisper, SRT, temps réel.

Qu'est-ce que Whisper ?

Whisper est un modèle de reconnaissance automatique de la parole (ASR) publié en open-source par OpenAI en septembre 2022. Entraîné sur 680 000 heures d'audio multilingue collectées sur le web, il surpasse la plupart des solutions commerciales sur les langues à ressources réduites — dont le français.

Ses points forts :

Whisper est disponible en plusieurs tailles de modèle (tiny → large-v3) selon le compromis vitesse/précision que vous recherchez. On l'utilise via la bibliothèque Python officielle openai-whisper ou via faster-whisper, une réimplémentation optimisée.

Installation

Whisper requiert Python 3.8+ et ffmpeg (pour décoder les fichiers audio). Voici comment tout installer :

1. Installer ffmpeg

# Ubuntu / Debian
sudo apt update && sudo apt install ffmpeg

# macOS (Homebrew)
brew install ffmpeg

# Windows (Chocolatey)
choco install ffmpeg

2. Installer la bibliothèque Python

pip install openai-whisper

Si vous avez un GPU NVIDIA, installez la version CUDA de PyTorch pour profiter de l'accélération matérielle :

# PyTorch avec CUDA 11.8
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install openai-whisper

Vérifiez l'installation :

python -c "import whisper; print(whisper.__version__)"

Première transcription en 5 lignes

Voici le code minimal pour transcrire un fichier audio :

import whisper

model = whisper.load_model("base")
result = model.transcribe("audio.mp3")
print(result["text"])

C'est tout. Whisper détecte automatiquement la langue, découpe l'audio en segments et retourne le texte complet dans result["text"]. Le dictionnaire result contient aussi :

Exemple de sortie

import whisper, json

model = whisper.load_model("base")
result = model.transcribe("conference.mp3")

print("Langue détectée :", result["language"])
print("Texte complet :\n", result["text"])
print("\nPremier segment :")
print(json.dumps(result["segments"][0], indent=2, ensure_ascii=False))

Sortie typique :

Langue détectée : fr
Texte complet :
 Bonjour et bienvenue dans cette conférence sur l'intelligence artificielle...

Premier segment :
{
  "id": 0,
  "seek": 0,
  "start": 0.0,
  "end": 4.5,
  "text": " Bonjour et bienvenue dans cette conférence sur l'intelligence artificielle...",
  "tokens": [...],
  "temperature": 0.0,
  "avg_logprob": -0.21,
  "compression_ratio": 1.34,
  "no_speech_prob": 0.02
}

Choisir le bon modèle

Whisper propose cinq tailles de modèle. Plus le modèle est grand, plus la précision est élevée — mais plus la transcription est lente et gourmande en mémoire.

Modèle Paramètres VRAM requise Vitesse (CPU) Précision FR Cas d'usage
tiny 39 M ~1 Go ~32× Correcte Tests rapides, microcontrôleurs
base 74 M ~1 Go ~16× Bonne Prototypage, démo
small 244 M ~2 Go ~6× Très bonne Production légère, podcasts
medium 769 M ~5 Go ~2× Excellente Réunions, sous-titres
large-v3 1550 M ~10 Go ~1× Maximale Transcription critique, juridique

Recommandation pratique : commencez avec small sur CPU, passez à medium si vous avez un GPU ou via faster-whisper. Réservez large-v3 aux cas où la précision est critique (contenu médical, juridique, sous-titres professionnels).

Pour charger un modèle spécifique :

import whisper

# Modèle léger pour CPU
model = whisper.load_model("small")

# Modèle large sur GPU
model = whisper.load_model("large-v3", device="cuda")

# Forcer le CPU même si GPU disponible
model = whisper.load_model("medium", device="cpu")

Transcrire en français

Par défaut, Whisper détecte automatiquement la langue. Mais pour du contenu majoritairement français, il est recommandé de forcer la langue afin d'éviter les erreurs de détection (utile pour les accents forts ou les extraits courts) :

import whisper

model = whisper.load_model("small")

# Forcer la langue française
result = model.transcribe("reunion.mp3", language="fr")
print(result["text"])

Traduire vers l'anglais

Whisper peut aussi traduire directement depuis le français (ou toute autre langue) vers l'anglais en passant task="translate" :

import whisper

model = whisper.load_model("small")

# Transcription en français
result_fr = model.transcribe("discours.mp3", language="fr")
print("FR :", result_fr["text"])

# Traduction automatique vers l'anglais
result_en = model.transcribe("discours.mp3", task="translate")
print("EN :", result_en["text"])

Générer des sous-titres SRT

Les segments horodatés de Whisper se transforment facilement en fichier SRT pour les sous-titres vidéo :

import whisper

def format_timestamp(seconds: float) -> str:
    """Convertit des secondes en format SRT HH:MM:SS,mmm"""
    hours = int(seconds // 3600)
    minutes = int((seconds % 3600) // 60)
    secs = int(seconds % 60)
    millis = int((seconds % 1) * 1000)
    return f"{hours:02d}:{minutes:02d}:{secs:02d},{millis:03d}"

def transcribe_to_srt(audio_path: str, output_path: str, language: str = "fr"):
    model = whisper.load_model("small")
    result = model.transcribe(audio_path, language=language)

    srt_lines = []
    for i, segment in enumerate(result["segments"], start=1):
        start = format_timestamp(segment["start"])
        end = format_timestamp(segment["end"])
        text = segment["text"].strip()
        srt_lines.append(f"{i}\n{start} --> {end}\n{text}\n")

    with open(output_path, "w", encoding="utf-8") as f:
        f.write("\n".join(srt_lines))

    print(f"Fichier SRT généré : {output_path}")
    return result

# Utilisation
transcribe_to_srt("video.mp4", "sous-titres.srt", language="fr")

Traiter différents formats audio

Whisper accepte nativement MP3, WAV, M4A, FLAC, OGG, MP4, MKV et bien d'autres formats grâce à ffmpeg. Voici quelques exemples pratiques :

Traitement par lot (batch processing)

import whisper
from pathlib import Path

def batch_transcribe(folder: str, language: str = "fr", model_name: str = "small"):
    """Transcrit tous les fichiers audio d'un dossier."""
    model = whisper.load_model(model_name)
    audio_extensions = {".mp3", ".wav", ".m4a", ".flac", ".ogg", ".mp4"}
    results = {}

    for audio_file in Path(folder).iterdir():
        if audio_file.suffix.lower() in audio_extensions:
            print(f"Traitement : {audio_file.name}")
            result = model.transcribe(str(audio_file), language=language)
            results[audio_file.name] = result["text"]

            # Sauvegarde du texte
            output = audio_file.with_suffix(".txt")
            output.write_text(result["text"], encoding="utf-8")
            print(f"  -> Sauvegardé dans {output.name}")

    return results

# Transcrire tous les MP3 d'un dossier
transcriptions = batch_transcribe("./podcasts", language="fr")
print(f"{len(transcriptions)} fichier(s) traité(s)")

Extraire l'audio d'une vidéo avant transcription

import subprocess
import whisper

def transcribe_video(video_path: str, language: str = "fr") -> str:
    """Extrait l'audio d'une vidéo puis transcrit."""
    audio_path = video_path.replace(".mp4", "_audio.wav")

    # Extraction avec ffmpeg
    subprocess.run([
        "ffmpeg", "-i", video_path,
        "-ar", "16000",      # 16 kHz optimal pour Whisper
        "-ac", "1",          # Mono
        "-c:a", "pcm_s16le", # WAV PCM 16 bits
        audio_path, "-y"
    ], check=True, capture_output=True)

    model = whisper.load_model("small")
    result = model.transcribe(audio_path, language=language)
    return result["text"]

texte = transcribe_video("formation-nlp.mp4")
print(texte)

Transcription en temps réel depuis le micro

Whisper n'est pas conçu pour le streaming pur (il fonctionne sur des segments entiers), mais on peut simuler une transcription "quasi temps réel" en enregistrant par morceaux de quelques secondes :

pip install sounddevice numpy scipy
import whisper
import sounddevice as sd
import numpy as np
import scipy.io.wavfile as wav
import tempfile
import os

SAMPLE_RATE = 16000    # Hz
CHUNK_DURATION = 5     # secondes par segment

model = whisper.load_model("base")

print("Transcription en cours... (Ctrl+C pour arrêter)")

try:
    while True:
        # Enregistrement d'un chunk
        audio_data = sd.rec(
            int(CHUNK_DURATION * SAMPLE_RATE),
            samplerate=SAMPLE_RATE,
            channels=1,
            dtype="float32"
        )
        sd.wait()

        # Sauvegarde temporaire
        with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
            wav.write(tmp.name, SAMPLE_RATE, audio_data)
            tmp_path = tmp.name

        # Transcription du chunk
        result = model.transcribe(tmp_path, language="fr")
        if result["text"].strip():
            print(result["text"].strip())

        os.unlink(tmp_path)

except KeyboardInterrupt:
    print("\nTranscription arrêtée.")

Astuce : pour une vraie transcription en continu avec faible latence, orientez-vous vers whisper-streaming ou whisper_live, des bibliothèques qui implémentent des stratégies de buffer et VAD (Voice Activity Detection).

faster-whisper : 4× plus rapide sur CPU

faster-whisper est une réimplémentation de Whisper basée sur CTranslate2, un moteur d'inférence optimisé. Il offre :

Installation

pip install faster-whisper

Utilisation de base

from faster_whisper import WhisperModel

# Chargement avec quantification INT8 (CPU)
model = WhisperModel("small", device="cpu", compute_type="int8")

# Transcription
segments, info = model.transcribe("audio.mp3", language="fr")

print(f"Langue détectée : {info.language} (confiance : {info.language_probability:.0%})")

for segment in segments:
    print(f"[{segment.start:.1f}s -> {segment.end:.1f}s] {segment.text}")

Générer un SRT avec faster-whisper

from faster_whisper import WhisperModel

def format_ts(seconds: float) -> str:
    h = int(seconds // 3600)
    m = int((seconds % 3600) // 60)
    s = int(seconds % 60)
    ms = int((seconds % 1) * 1000)
    return f"{h:02d}:{m:02d}:{s:02d},{ms:03d}"

model = WhisperModel("small", device="cpu", compute_type="int8")
segments, info = model.transcribe("video.mp4", language="fr")

with open("sous-titres.srt", "w", encoding="utf-8") as f:
    for i, seg in enumerate(segments, start=1):
        f.write(f"{i}\n")
        f.write(f"{format_ts(seg.start)} --> {format_ts(seg.end)}\n")
        f.write(f"{seg.text.strip()}\n\n")

print("Fichier SRT généré avec faster-whisper !")

Comparatif faster-whisper vs openai-whisper

Critère openai-whisper faster-whisper
Vitesse CPU Référence (1×) 2× à 4×
Mémoire RAM Standard Moitié moins (INT8)
Précision Référence Quasi identique
GPU (CUDA) Oui Oui (float16)
Streaming segments Non Oui (générateur)
API Simple Légèrement différente
Maintenu par OpenAI Communauté (SYSTRAN)

Cas d'usage concrets

1. Transcription automatique de réunions

import whisper
from pathlib import Path
from datetime import datetime

def transcribe_meeting(audio_path: str) -> dict:
    """Transcrit une réunion et génère un compte-rendu structuré."""
    model = whisper.load_model("medium")
    result = model.transcribe(audio_path, language="fr")

    # Durée totale
    duration = result["segments"][-1]["end"] if result["segments"] else 0

    # Résumé par blocs de 5 minutes
    blocks = {}
    for seg in result["segments"]:
        block_key = int(seg["start"] // 300) * 5
        label = f"{block_key:02d}min"
        if label not in blocks:
            blocks[label] = []
        blocks[label].append(seg["text"].strip())

    return {
        "date": datetime.now().strftime("%Y-%m-%d"),
        "duration_min": round(duration / 60, 1),
        "full_text": result["text"],
        "blocks": {k: " ".join(v) for k, v in blocks.items()}
    }

meeting = transcribe_meeting("reunion-equipe.mp3")
print(f"Durée : {meeting['duration_min']} min")
print("\nCompte-rendu par blocs :")
for time, text in meeting["blocks"].items():
    print(f"\n[{time}] {text[:200]}...")

2. Pipeline sous-titrage vidéo

from faster_whisper import WhisperModel
import subprocess
from pathlib import Path

def subtitle_video(video_path: str, lang: str = "fr", burn_in: bool = False):
    """Transcrit une vidéo, génère SRT et optionnellement incruste les sous-titres."""
    model = WhisperModel("small", device="cpu", compute_type="int8")
    segments, _ = model.transcribe(video_path, language=lang)

    # Génération du SRT
    srt_path = Path(video_path).with_suffix(".srt")
    with open(srt_path, "w", encoding="utf-8") as f:
        for i, seg in enumerate(segments, 1):
            def ts(s):
                h,m = int(s//3600), int((s%3600)//60)
                return f"{h:02d}:{m:02d}:{int(s%60):02d},{int((s%1)*1000):03d}"
            f.write(f"{i}\n{ts(seg.start)} --> {ts(seg.end)}\n{seg.text.strip()}\n\n")

    print(f"SRT généré : {srt_path}")

    if burn_in:
        # Incruster les sous-titres dans la vidéo via ffmpeg
        out_path = Path(video_path).stem + "_sous-titres.mp4"
        subprocess.run([
            "ffmpeg", "-i", video_path,
            "-vf", f"subtitles={srt_path}",
            out_path, "-y"
        ], check=True)
        print(f"Vidéo avec sous-titres : {out_path}")

subtitle_video("webinaire.mp4", lang="fr", burn_in=True)

3. Indexation de contenus audio pour moteur de recherche

import whisper
import json
from pathlib import Path

def index_audio_library(folder: str) -> list:
    """Indexe une bibliothèque audio pour la recherche full-text."""
    model = whisper.load_model("small")
    index = []

    for audio_file in Path(folder).glob("**/*.mp3"):
        result = model.transcribe(str(audio_file), language="fr")
        entry = {
            "file": str(audio_file),
            "title": audio_file.stem.replace("-", " ").title(),
            "text": result["text"],
            "language": result["language"],
            "segments": [
                {"start": s["start"], "end": s["end"], "text": s["text"]}
                for s in result["segments"]
            ]
        }
        index.append(entry)
        print(f"Indexé : {audio_file.name}")

    # Sauvegarde de l'index
    with open("audio_index.json", "w", encoding="utf-8") as f:
        json.dump(index, f, ensure_ascii=False, indent=2)

    return index

def search_index(query: str, index_path: str = "audio_index.json") -> list:
    """Recherche dans l'index."""
    with open(index_path, encoding="utf-8") as f:
        index = json.load(f)

    query_lower = query.lower()
    results = []
    for entry in index:
        if query_lower in entry["text"].lower():
            # Trouver les segments correspondants
            matching = [s for s in entry["segments"] if query_lower in s["text"].lower()]
            results.append({
                "file": entry["file"],
                "title": entry["title"],
                "matches": matching
            })
    return results

# Utilisation
index = index_audio_library("./podcasts")
hits = search_index("intelligence artificielle")
for hit in hits:
    print(f"\n{hit['title']} :")
    for match in hit["matches"]:
        print(f"  [{match['start']:.0f}s] {match['text']}")

Limites et alternatives

Limites de Whisper

Comparatif Whisper vs solutions alternatives

Solution Prix Qualité FR Streaming RGPD / Local
Whisper (local) Gratuit Excellent Non natif 100 % local
OpenAI Whisper API 0,006 $/min Excellent Non Cloud US
Google Speech-to-Text 0,016 $/min Très bon Oui Cloud Google
AWS Transcribe 0,024 $/min Bon Oui Cloud AWS
AssemblyAI 0,012 $/min Très bon Oui Cloud US
vosk Gratuit Moyen Oui 100 % local

Conclusion : si vous avez des contraintes RGPD ou budgétaires, Whisper local (ou faster-whisper) est le meilleur choix. Pour du streaming temps réel avec diarisation, les APIs cloud restent plus adaptées — mais impliquent l'envoi de données vers des serveurs étrangers.

Aller plus loin avec le NLP

Notre formation NLP couvre la transcription, la vectorisation, les Transformers et la classification de texte — avec des exemples de code prêts à déployer.

Découvrir la formation NLP →
← Retour au blog

Partager cet article :

Lire aussi