Aller au contenu principal

Transcription vocale par batch avec Whisper

Ouvrir dans Databricks

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.
remarque

Cet exemple requiert l'environnement Databricks AI version 6 ou une version ultérieure.

Se connecter au compute GPU serverless

  1. Dans le sélecteur de compute du notebook, sélectionnez Serverless GPU .
  2. Dans le panneau Environment , 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 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é.

Python
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")
Output
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.

Python
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}")
Output
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.

Python
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"]))
Output
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.

Python
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.

Python
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']}")
Output
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.

Python
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)
Output
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, transformers et datasets préinstallés ; aucun %pip install n'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_size parameter 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.

Exemple de Notebook

Discours-texte par batch avec Whisper