Transcription audio en texte par lots avec Whisper

Utilisez OpenAI Whisper large-v3-turbo pour transcrire un lot d’enregistrements de voix anglais sur un A10 AI Runtime attaché. Ce carnet montre comment :

  • Chargez le modèle Whisper large-v3-turbo avec le pipeline Transformers.
  • Construis un lot d’échantillons audio à partir du test LibriSpeech.
  • Visualisez la forme d’onde et le spectrogramme de chaque échantillon.
  • Exécutez la transcription en lot et comparez son débit avec l’inférence séquentielle.

Note

Cet exemple nécessite l’environnement IA Databricks version 6 ou supérieure.

Connecter au calcul GPU sans serveur

  1. Depuis le sélecteur de calcul du portable, sélectionnez GPU Serverless.
  2. Dans le panneau Environnement , sélectionnez l’accélérateur A10 et l’environnement AI v6 .
  3. Cliquez sur Appliquer, puis confirmez l’environnement.

Le modèle Whisper et l’ensemble de données d’échantillons LibriSpeech sont publics et ne nécessitent pas d’authentification Hugging Face.

Importer des bibliothèques

L’environnement IA inclut les packages PyTorch, Transformers et Hugging Face Datasets utilisés dans ce carnet, donc aucune installation de package n’est requise. Cette cellule les importe et confirme qu’un GPU est connecté.

import torch
import transformers
import datasets

print(f"Environment")
print(f"   PyTorch:      {torch.__version__}")
print(f"   Transformers: {transformers.__version__}")
print(f"   Datasets:     {datasets.__version__}")
print(f"\nGPU")
print(f"   Available:    {torch.cuda.is_available()}")
if torch.cuda.is_available():
    print(f"   Device:       {torch.cuda.get_device_name(0)}")
    mem_gb = torch.cuda.get_device_properties(0).total_memory / 1e9
    print(f"   Memory:       {mem_gb:.1f} GB")
Environment
   PyTorch:      2.11.0+cu130
   Transformers: 5.8.1
   Datasets:     4.8.5

GPU
   Available:    True
   Device:       NVIDIA A10G
   Memory:       23.7 GB

Chargez le modèle Whisper

Charge openai/whisper-large-v3-turbo, un modèle distillé à paramètres 809M qui offre une précision quasi à la pointe de la technologie à une vitesse d’inférence plus rapide. Le pipeline Transformers gère l’extraction des fonctionnalités, la tokenisation et le décodage en un seul appel.

from transformers import pipeline
import torch

whisper_pipe = pipeline(
    "automatic-speech-recognition",
    model="openai/whisper-large-v3-turbo",
    torch_dtype=torch.float16,
    device="cuda",
)
print(f"Model loaded on {whisper_pipe.device}")
Model loaded on cuda

Chargez et explorez les échantillons audio

Chargez le jeu de test LibriSpeech ASR , une collection d’enregistrements clairs de voix anglaise avec transcriptions de référence, et lancez le premier échantillon.

from datasets import load_dataset, Audio as AudioFeature
from IPython.display import display, Audio
import numpy as np
import soundfile as sf
import io

# Load the LibriSpeech test samples (decode=False to avoid torchcodec/FFmpeg dependency)
ds = load_dataset(
    "hf-internal-testing/librispeech_asr_dummy", "clean", split="validation"
)
ds = ds.cast_column("audio", AudioFeature(decode=False))
print(f"Loaded {len(ds)} audio samples\n")

def decode_audio(raw):
    """Decode raw audio bytes with soundfile."""
    arr, sr = sf.read(io.BytesIO(raw["bytes"]))
    return {"array": arr, "sampling_rate": sr}

# Show metadata for first few samples
for i in range(5):
    audio = decode_audio(ds[i]["audio"])
    duration = len(audio["array"]) / audio["sampling_rate"]
    text_preview = ds[i]["text"][:80]
    print(f"  Sample {i+1}:  {duration:.2f}s  |  {audio['sampling_rate']} Hz  |  \"{text_preview}...\"")

# Play the first sample inline
print("\n>> Playing Sample 1:")
audio_0 = decode_audio(ds[0]["audio"])
display(Audio(audio_0["array"], rate=audio_0["sampling_rate"]))
Loaded 73 audio samples

  Sample 1:  5.86s  |  16000 Hz  |  "MISTER QUILTER IS THE APOSTLE OF THE MIDDLE CLASSES AND WE ARE GLAD TO WELCOME H..."
  Sample 2:  4.82s  |  16000 Hz  |  "NOR IS MISTER QUILTER'S MANNER LESS INTERESTING THAN HIS MATTER..."
  Sample 3:  12.48s  |  16000 Hz  |  "HE TELLS US THAT AT THIS FESTIVE SEASON OF THE YEAR WITH CHRISTMAS AND ROAST BEE..."
  Sample 4:  9.90s  |  16000 Hz  |  "HE HAS GRAVE DOUBTS WHETHER SIR FREDERICK LEIGHTON'S WORK IS REALLY GREEK AFTER ..."
  Sample 5:  29.40s  |  16000 Hz  |  "LINNELL'S PICTURES ARE A SORT OF UP GUARDS AND AT EM PAINTINGS AND MASON'S EXQUI..."

>> Playing Sample 1:

Visualisez les formes d’onde audio

Tracez la forme d’onde et le spectrogramme de chaque échantillon côte à côte. La forme d’onde montre l’amplitude dans le temps, et le spectrogramme montre le contenu en fréquence, où l’énergie vocale se concentre dans la bande de parole de 100 à 4 000 Hz.

import matplotlib.pyplot as plt
import numpy as np

NUM_SAMPLES = 4
fig, axes = plt.subplots(NUM_SAMPLES, 2, figsize=(16, 3 * NUM_SAMPLES))
fig.suptitle(
    "Waveform & Spectrogram Profiles", fontsize=16, fontweight="bold", y=1.01
)

for i in range(NUM_SAMPLES):
    audio = decode_audio(ds[i]["audio"])
    samples = audio["array"]
    sr = audio["sampling_rate"]
    t = np.arange(len(samples)) / sr

    # --- Waveform ---
    ax_wave = axes[i, 0]
    ax_wave.plot(t, samples, linewidth=0.4, color="#1f77b4", alpha=0.8)
    ax_wave.fill_between(t, samples, alpha=0.15, color="#1f77b4")
    ax_wave.set_ylabel("Amplitude", fontsize=9)
    ax_wave.set_title(f"Sample {i+1} — Waveform ({len(samples)/sr:.1f}s)", fontsize=10)
    ax_wave.set_xlim(0, t[-1])
    ax_wave.grid(True, alpha=0.3)
    if i == NUM_SAMPLES - 1:
        ax_wave.set_xlabel("Time (seconds)", fontsize=9)

    # --- Spectrogram ---
    ax_spec = axes[i, 1]
    ax_spec.specgram(samples, Fs=sr, NFFT=1024, noverlap=512, cmap="magma")
    ax_spec.set_ylabel("Frequency (Hz)", fontsize=9)
    ax_spec.set_title(f"Sample {i+1} — Spectrogram", fontsize=10)
    ax_spec.set_ylim(0, 8000)  # Focus on speech frequencies
    if i == NUM_SAMPLES - 1:
        ax_spec.set_xlabel("Time (seconds)", fontsize=9)

plt.tight_layout()
plt.show()

Transcrivez un seul échantillon

Transcrivez un échantillon pour vérifier le pipeline, puis comparez la prédiction avec le texte de référence.

import time

audio_input = decode_audio(ds[0]["audio"])

start = time.perf_counter()
result = whisper_pipe(
    audio_input["array"],
    generate_kwargs={"language": "en"},
)
elapsed = time.perf_counter() - start

duration = len(audio_input["array"]) / audio_input["sampling_rate"]

print(f"Inference time:   {elapsed:.2f}s for {duration:.1f}s audio ({duration/elapsed:.1f}x realtime)")
print(f"\nPredicted:  {result['text'].strip()}")
print(f"Reference:  {ds[0]['text']}")
Inference time:   12.23s for 5.9s audio (0.5x realtime)

Predicted:  Mr. Quilter is the apostle of the middle classes, and we are glad to welcome his gospel.
Reference:  MISTER QUILTER IS THE APOSTLE OF THE MIDDLE CLASSES AND WE ARE GLAD TO WELCOME HIS GOSPEL

Exécutez l’inférence par lots

Transcrivez tous les échantillons avec un batch_size configurable. Le batching permet au GPU de traiter plusieurs extraits audio en parallèle, ce qui améliore le débit par rapport à l’inférence séquentielle. Cette cellule mesure également le temps d’exécution d’une version séquentielle de référence à des fins de comparaison.

import time
import pandas as pd

_decoded = [decode_audio(ds[i]["audio"]) for i in range(len(ds))]
audio_inputs = [d["array"] for d in _decoded]
_sr = _decoded[0]["sampling_rate"]

# --- Sequential baseline ---
start = time.perf_counter()
seq_results = [
    whisper_pipe(a, generate_kwargs={"language": "en"}) for a in audio_inputs
]
seq_time = time.perf_counter() - start

# --- Batched inference ---
start = time.perf_counter()
batch_results = whisper_pipe(
    audio_inputs, batch_size=8, generate_kwargs={"language": "en"}
)
batch_time = time.perf_counter() - start

total_audio_sec = sum(
    len(a) / _sr for a in audio_inputs
)

print(f"Performance Comparison ({len(audio_inputs)} samples, {total_audio_sec:.1f}s total audio)")
print(f"   Sequential:  {seq_time:.2f}s  ({total_audio_sec/seq_time:.1f}x realtime)")
print(f"   Batched (8): {batch_time:.2f}s  ({total_audio_sec/batch_time:.1f}x realtime)")
print(f"   Speedup:     {seq_time/batch_time:.2f}x\n")

# --- Results table ---
rows = []
for i, res in enumerate(batch_results):
    duration = len(audio_inputs[i]) / _sr
    rows.append({
        "Sample": i + 1,
        "Duration (s)": round(duration, 1),
        "Transcription": res["text"].strip(),
        "Reference": ds[i]["text"],
    })

df = pd.DataFrame(rows)
display(df)
Performance Comparison (73 samples, 481.0s total audio)
   Sequential:  16.02s  (30.0x realtime)
   Batched (8): 9.56s  (50.3x realtime)
   Speedup:     1.68x

Résumé

Ce carnet démontrait :

  • Inférence GPU sans configuration : l’environnement d’exécution IA est livré avec torch, transformers et datasets préinstallés ; sans %pip install
  • Lecture audio en ligne : écoutez les échantillons directement dans le carnet avec IPython.display.Audio
  • Visualisation de formes d’onde et spectrogrammes : rendue avec matplotlib, également préinstallée
  • Inférence par lots efficace : utilisation du batch_size paramètre pour la transcription GPU-parallèle
  • Whisper large-v3-turbo : un modèle rapide et précis pour la transcription vocale adapté à la production

Pour adapter cela à vos propres données, remplacez l’ensemble de données HuggingFace par des fichiers audio issus d’un Unity Catalog Volume ou d’un chemin de stockage cloud.

Exemple de bloc-notes

Conversion vocale en série avec Whisper

Obtenir un ordinateur portable