Transcription vocale par batch avec Whisper
Utilisez OpenAI Whisper large-v3-turbo pour transcrire un batch d'enregistrements de paroles en anglais sur un Runtime AI A10 associé. Ce notebook montre comment :
- Charger le modèle Whisper large-v3-turbo avec le pipeline Transformers.
- Créez un batch d'échantillons audio à partir du jeu de test LibriSpeech.
- Visualisez la forme d’onde et le spectrogramme de chaque échantillon.
- Exécuter une transcription par batch et comparer son throughput avec l'inférence séquentielle.
Cet exemple requiert l'environnement Databricks AI version 6 ou une version ultérieure.
Se connecter au compute GPU serverless
- Dans le sélecteur de compute du notebook, sélectionnez Serverless GPU .
- Dans le panneau Environment , sélectionnez l'accélérateur A10 et l'environnement AI v6 .
- Cliquez sur Appliquer , puis confirmez l'environnement.
Le modèle Whisper et le dataset d'échantillons LibriSpeech sont publics et ne nécessitent pas d'authentification Hugging Face.
Importer des bibliothèques
L'environnement IA comprend les packages PyTorch, Transformers et Hugging Face Datasets utilisés dans ce notebook, de sorte qu'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
Charger le modèle Whisper
Charger openai/whisper-large-v3-turbo, un modèle à 809M-parameter distillé qui offre une précision quasi optimale à une vitesse d'inférence plus rapide. Le pipeline Transformers gère l'extraction de caractéristiques, 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
Charger et explorer des échantillons audio
Chargez le jeu de test LibriSpeech ASR, une collection d'enregistrements de paroles en anglais propres avec des transcriptions de référence, et écoutez 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’ondes audio
Tracer la forme d'onde et le spectrogramme de chaque échantillon côte à côte. La forme d'onde montre l'amplitude au fil du temps, et le spectrogramme montre le contenu fréquentiel, où l'énergie vocale se concentre dans la bande vocale 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()
Transcrire un seul échantillon
Transcrire un échantillon pour vérifier le pipeline, puis comparer 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écuter l'inférence par batch
Transcrire tous les échantillons avec un batch_size configurable. Le batching permet au GPU de traiter plusieurs clips audio en parallèle, ce qui améliore le throughput par rapport à l'inférence séquentielle. Cette cellule mesure également le temps d'une référence séquentielle à 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 notebook a démontré :
- Inférence GPU sans configuration requise : l'environnement Runtime AI intègre
torch,transformersetdatasetspréinstallés ; aucun%pip installn'est nécessaire - Lecture audio intégrée : écoutez des échantillons directement dans le Notebook avec
IPython.display.Audio - Visualisation des formes d'onde et des spectrogrammes : rendue avec
matplotlib, également préinstallé - Inférence par batch efficace : utilisation du
batch_sizeparameter pour la transcription parallèle sur GPU - Whisper large-v3-turbo : un modèle rapide et précis pour la conversion parole-texte de niveau production
Pour adapter ceci à vos propres données, remplacez le dataset HuggingFace par des fichiers audio provenant d'un volume Unity Catalog ou d'un chemin de stockage cloud.