Trascrizione Audio con Whisper: Integrarla nei Tuoi Progetti
Perché la Trascrizione Audio tramite API nel 2026
Nel 2026 la trascrizione audio non è più un lusso per grandi aziende: è diventata un mattoncino fondamentale in pipeline di automazione, prodotti SaaS e workflow da developer solitario. Whisper, il modello open-source di OpenAI, ha cambiato le regole del gioco: accuratezza vicina al livello umano, supporto per oltre 90 lingue (italiano incluso), e un’API ufficiale che puoi chiamare con poche righe di codice.
Se stai costruendo un’app che registra note vocali, un sistema di sottotitoli automatici, un bot che trascrive riunioni Zoom, o un pipeline di analisi del parlato, Whisper via API è la scelta più pragmatica. Niente GPU da affittare, niente modello da hostare: carichi il file audio, ricevi il testo. Punto.
In questo articolo vedremo come integrare Whisper nei tuoi progetti con esempi reali e funzionanti sia in Python che in Node.js. Scopriremo come gestire file lunghi, come estrarre timestamp per i sottotitoli, come integrarlo in un workflow con n8n + Claude AI e come ottimizzare costi e latenza. Se lavori già con le API di AI, noterai subito i parallelismi con le tecniche che usi per altri servizi.
Come Funziona Whisper: Modelli e Endpoint
Whisper è disponibile sia come modello open-source (eseguibile in locale) che tramite l’API di OpenAI. Per la maggior parte dei progetti, l’API hosted è la scelta giusta: non devi gestire infrastruttura, il costo è basso (0.006$ al minuto a giugno 2026), e la latenza è accettabile per workflow asincroni.
L’endpoint principale è POST /v1/audio/transcriptions. Accetta file audio in formato mp3, mp4, mpeg, mpga, m4a, wav e webm, con un limite di 25 MB per file. Il parametro più utile è response_format: puoi scegliere tra json (solo testo), verbose_json (con timestamp per ogni parola), srt e vtt (formati sottotitoli).
- whisper-1: il modello attuale nell’API, bilanciato tra velocità e accuratezza
- Parametro language: specifica
itper l’italiano e migliori sensibilmente la qualità - Parametro prompt: fornisce contesto (nomi propri, terminologia tecnica) per ridurre errori
- Parametro temperature: valori bassi (0-0.2) per trascrizione, valori più alti per stili creativi
Prima Chiamata API: Python in 10 Righe
Iniziamo dal caso più semplice: trascrivere un file audio in Python usando l’SDK ufficiale di OpenAI. Assicurati di avere la libreria installata con pip install openai.
from openai import OpenAI
import os
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
def trascrivi_audio(percorso_file: str, lingua: str = "it") -> str:
# Trascrive un file audio usando Whisper API.
with open(percorso_file, "rb") as audio_file:
trascrizione = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
language=lingua,
response_format="text"
)
return trascrizione
# Utilizzo
testo = trascrivi_audio("riunione.mp3")
print(testo)
Questo è il punto di partenza. Nota response_format="text": restituisce direttamente la stringa senza wrapper JSON. Per la maggior parte dei casi d’uso è la scelta più pulita.
Se vuoi anche i timestamp per ogni segmento (utilissimo per sottotitoli o per sincronizzare testo e audio), usa response_format="verbose_json":
from openai import OpenAI
import json
client = OpenAI()
def trascrivi_con_timestamp(percorso_file: str) -> dict:
# Restituisce testo + segmenti con timestamp.
with open(percorso_file, "rb") as audio_file:
risposta = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
language="it",
response_format="verbose_json",
timestamp_granularities=["segment"]
)
risultato = {
"testo_completo": risposta.text,
"durata": risposta.duration,
"segmenti": [
{
"inizio": seg.start,
"fine": seg.end,
"testo": seg.text.strip()
}
for seg in risposta.segments
]
}
return risultato
# Esempio output
dati = trascrivi_con_timestamp("podcast.mp3")
print(f"Durata: {dati['durata']:.1f}s")
for seg in dati['segmenti'][:3]:
print(f"[{seg['inizio']:.1f}s -> {seg['fine']:.1f}s] {seg['testo']}")
Integrazione in Node.js con Fetch Nativo
Se lavori su un backend Node.js o un’app Next.js, puoi chiamare l’API Whisper senza librerie aggiuntive usando il fetch nativo (disponibile da Node 18+) e la FormData API. Questo approccio è ideale per route handler Next.js o endpoint Express che ricevono upload audio.
import fs from 'fs';
import path from 'path';
/**
* Trascrive un file audio usando Whisper API.
* Compatibile con Node 18+ (fetch nativo).
*/
async function trascriviAudio(filePath, options = {}) {
const {
language = 'it',
responseFormat = 'json',
prompt = '',
} = options;
const fileBuffer = fs.readFileSync(filePath);
const fileName = path.basename(filePath);
const formData = new FormData();
formData.append('model', 'whisper-1');
formData.append('language', language);
formData.append('response_format', responseFormat);
if (prompt) formData.append('prompt', prompt);
// Crea il Blob con il tipo MIME corretto
const mimeType = getMimeType(fileName);
const blob = new Blob([fileBuffer], { type: mimeType });
formData.append('file', blob, fileName);
const response = await fetch('https://api.openai.com/v1/audio/transcriptions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
},
body: formData,
});
if (!response.ok) {
const errore = await response.json();
throw new Error(`Whisper API error: ${errore.error?.message}`);
}
const risultato = await response.json();
return risultato.text;
}
function getMimeType(fileName) {
const ext = path.extname(fileName).toLowerCase();
const mimeTypes = {
'.mp3': 'audio/mpeg',
'.mp4': 'audio/mp4',
'.wav': 'audio/wav',
'.webm': 'audio/webm',
'.m4a': 'audio/mp4',
};
return mimeTypes[ext] || 'audio/mpeg';
}
// Utilizzo
const testo = await trascriviAudio('./nota-vocale.mp3', {
prompt: 'CyberAlchimista, sviluppo web, JavaScript, API REST'
});
console.log(testo);
Il parametro prompt è spesso sottovalutato ma fa una differenza enorme: inserire nomi propri, acronimi tecnici e termini di dominio riduce drasticamente gli errori di trascrizione. Se trascrivi riunioni di un team di sviluppo, includi nel prompt i nomi dei framework e delle tecnologie che usate.
Gestire File Audio Lunghi: Chunking e Parallelismo
Il limite di 25 MB per file è il vincolo principale di Whisper API. Per un file MP3 a bitrate normale (128 kbps), 25 MB corrispondono a circa 25 minuti di audio. Riunioni lunghe, podcast o videoconferenze superano spesso questo limite.
La soluzione è il chunking: dividere il file in segmenti sovrapposti e trascrivere ciascuno in parallelo. L’overlapping (sovrapposizione di qualche secondo tra i chunk) è fondamentale per evitare frasi troncate ai confini. Questa tecnica si sposa bene con i pattern di streaming asincrono che potresti già usare per altri servizi AI.
from openai import OpenAI
from pydub import AudioSegment
import tempfile
import os
from concurrent.futures import ThreadPoolExecutor
client = OpenAI()
def dividi_audio(percorso: str, durata_chunk_ms: int = 600000, overlap_ms: int = 5000):
# Divide un file audio in chunk da 10 minuti con 5 secondi di overlap.
# Richiede: pip install pydub + ffmpeg installato sul sistema
audio = AudioSegment.from_file(percorso)
chunk_paths = []
inizio = 0
indice = 0
while inizio < len(audio):
fine = min(inizio + durata_chunk_ms, len(audio))
chunk = audio[inizio:fine]
with tempfile.NamedTemporaryFile(
suffix=".mp3", delete=False, prefix=f"chunk_{indice}_"
) as tmp:
chunk.export(tmp.name, format="mp3", bitrate="128k")
chunk_paths.append((indice, tmp.name))
inizio = fine - overlap_ms # overlap per non perdere frasi a cavallo
indice += 1
return chunk_paths
def trascrivi_chunk(args):
indice, percorso, lingua = args
with open(percorso, "rb") as f:
t = client.audio.transcriptions.create(
model="whisper-1",
file=f,
language=lingua,
response_format="text"
)
os.unlink(percorso) # pulisci il temp file
return (indice, t)
def trascrivi_audio_lungo(percorso: str, lingua: str = "it") -> str:
# Trascrive file audio di qualsiasi lunghezza via chunking parallelo.
chunks = dividi_audio(percorso)
if len(chunks) == 1:
_, risultato = trascrivi_chunk((0, chunks[0][1], lingua))
return risultato
print(f"File diviso in {len(chunks)} chunk, trascrizione parallela...")
args = [(idx, path, lingua) for idx, path in chunks]
with ThreadPoolExecutor(max_workers=4) as executor:
risultati = list(executor.map(trascrivi_chunk, args))
risultati.sort(key=lambda x: x[0])
return " ".join(testo for _, testo in risultati)
# Utilizzo
trascrizione = trascrivi_audio_lungo("webinar-2h.mp4")
print(f"Parole trascritte: {len(trascrizione.split())}")
Nota: pydub richiede ffmpeg installato sul sistema. Su macOS: brew install ffmpeg. Su Linux: apt-get install ffmpeg.
Workflow Avanzato: Trascrizione + Analisi AI
La trascrizione da sola è utile, ma il vero potere emerge quando la concateni con un’analisi AI. Un pattern comune è Whisper → LLM → output strutturato: trascrivi la riunione, poi chiedi all’AI di estrarre action items, decisioni prese e punti aperti.
Questo si integra perfettamente con i workflow di automazione. Se usi già n8n con subflow e error handling, puoi costruire un nodo custom che chiama Whisper, poi passa il testo a Claude o GPT-4, e salva il risultato su Notion o manda un email di riepilogo.
from openai import OpenAI
import json
client = OpenAI()
def analizza_riunione(percorso_audio: str) -> dict:
# Pipeline completa: trascrizione + estrazione strutturata.
# Restituisce un dizionario con summary, action items e decisioni.
# Step 1: Trascrizione
print("Trascrizione in corso...")
with open(percorso_audio, "rb") as f:
trascrizione = client.audio.transcriptions.create(
model="whisper-1",
file=f,
language="it",
response_format="text"
)
# Step 2: Analisi strutturata con GPT-4o
print("Analisi AI in corso...")
prompt_sistema = (
"Sei un assistente specializzato nell'analisi di trascrizioni di riunioni. "
"Estrai le informazioni in formato JSON con questa struttura: "
'{"riassunto": "...", "action_items": [{"chi": "...", "cosa": "...", "scadenza": "..."}], '
'"decisioni": ["..."], "punti_aperti": ["..."]}. '
"Rispondi SOLO con JSON valido, senza markdown o testo aggiuntivo."
)
risposta = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": prompt_sistema},
{"role": "user", "content": f"Analizza questa trascrizione:
{trascrizione}"}
],
temperature=0.1,
response_format={"type": "json_object"}
)
analisi = json.loads(risposta.choices[0].message.content)
analisi["trascrizione_completa"] = trascrizione
return analisi
# Utilizzo
risultato = analizza_riunione("stand-up-2026-08-03.mp3")
print("RIASSUNTO:", risultato["riassunto"])
print("
ACTION ITEMS:")
for item in risultato["action_items"]:
print(f" - {item['chi']}: {item['cosa']} (entro {item['scadenza']})")
Questo pattern è lo stesso che applico nei miei workflow di automazione: il modello di trascrizione fa ciò che sa fare meglio (convertire audio in testo), e il modello di linguaggio fa ciò che sa fare meglio (capire e strutturare il testo). Separare le responsabilità rende il sistema più robusto e più facile da debuggare.
Se stai costruendo qualcosa di più complesso con agenti AI, vale la pena leggere come funziona il RAG con Claude API: puoi indicizzare le trascrizioni e renderle interrogabili con linguaggio naturale.
Generare Sottotitoli SRT e VTT
Whisper genera direttamente file SRT e VTT pronti per essere allegati a video. È una delle funzionalità più sottovalutate dell’API: niente parsing manuale, niente conversioni, solo un parametro diverso per response_format.
from openai import OpenAI
import os
client = OpenAI()
def genera_sottotitoli(percorso_audio: str, formato: str = "srt") -> str:
# Genera sottotitoli nel formato specificato (srt o vtt).
assert formato in ("srt", "vtt"), "Formato deve essere 'srt' o 'vtt'"
with open(percorso_audio, "rb") as f:
sottotitoli = client.audio.transcriptions.create(
model="whisper-1",
file=f,
language="it",
response_format=formato
)
return sottotitoli
def salva_sottotitoli(percorso_audio: str, percorso_output: str = None):
# Genera e salva i sottotitoli SRT vicino al file audio.
if percorso_output is None:
base = os.path.splitext(percorso_audio)[0]
percorso_output = f"{base}.srt"
srt_content = genera_sottotitoli(percorso_audio, "srt")
with open(percorso_output, "w", encoding="utf-8") as f:
f.write(srt_content)
print(f"Sottotitoli salvati in: {percorso_output}")
# Mostra le prime 3 entry
righe = srt_content.strip().split("
")[:3]
for riga in righe:
print(riga)
print()
# Utilizzo
salva_sottotitoli("tutorial-javascript.mp4")
# Output esempio:
# 1
# 00:00:00,000 --> 00:00:03,500
# Oggi vedremo come usare Whisper per trascrivere audio in Python.
#
# 2
# 00:00:03,500 --> 00:00:07,200
# L'API di OpenAI rende tutto incredibilmente semplice.
I sottotitoli generati da Whisper hanno una qualità sorprendente anche per l’italiano: gestisce bene accenti regionali, gergo tecnico (specialmente se aiutato dal parametro prompt) e frasi sovrapposte. Per contenuti editoriali di qualità, una revisione manuale rapida è sempre consigliata, ma il 90% del lavoro è già fatto.
Stai costruendo un tool di automazione che incorpora sia la trascrizione che la pubblicazione? Dai un’occhiata a Tool Use con Claude API: puoi dare a un agente AI il “tool” di trascrizione e lasciare che decida autonomamente quando trascrivere un file audio ricevuto via webhook.
Ottimizzazione Costi e Best Practice
A 0.006$ al minuto, Whisper API è già economica. Ma in un’app con molti utenti o con audio lunghi, i costi si accumulano. Ecco le best practice per tenerli sotto controllo:
- Comprimi l’audio prima di inviarlo: converti a MP3 mono a 64 kbps. L’accuratezza cala marginalmente, ma il file è 4x più piccolo — e il costo si basa sui minuti, non sui byte.
- Specifica sempre la lingua: il parametro
languageaccelera la trascrizione e migliora l’accuratezza. Senza di esso Whisper deve “indovinare” la lingua. - Usa il parametro prompt: fornisci nomi propri e terminologia tecnica. Riduce le allucinazioni su parole specialistiche.
- Implementa caching: se lo stesso audio viene trascritto più volte (es. utenti che rielaborano lo stesso file), salva il risultato su Redis o database. Simile al Prompt Caching di Claude API.
- Trascrivi solo se necessario: usa silence detection per saltare sezioni di silenzio. Librerie come
pyduboffronodetect_silence()per questo scopo. - Valuta il modello locale: per volumi altissimi o per dati sensibili, Whisper open-source gira localmente. Con una GPU moderna (RTX 3090+) è più economico dell’API oltre le 1000 ore/mese.
🔧 Tip operativo: Per la maggior parte dei Micro SaaS, l’API hosted è la scelta corretta fino a quando il tuo volume non supera le 500 ore di audio al mese. Sotto quella soglia, il costo di gestire l’infrastruttura GPU supera abbondantemente il risparmio.
FAQ e Domande Frequenti
Whisper API supporta lo streaming in tempo reale?
No, l’API di OpenAI per Whisper non supporta lo streaming in tempo reale. Ogni chiamata è sincrona: invii il file, aspetti, ricevi il testo. Per la trascrizione in tempo reale (es. live captioning) esistono alternative come l’API di Deepgram o AssemblyAI, che supportano WebSocket e streaming. Whisper è ottimale per workflow asincroni dove hai il file audio completo prima di iniziare.
Qual è l’accuratezza di Whisper sull’italiano?
Molto alta, specialmente con il parametro language="it" impostato esplicitamente. Nei benchmark pubblici, Whisper large-v3 (il modello alla base dell’API) raggiunge un Word Error Rate (WER) del 4-6% sull’italiano standard. Per dialetti regionali marcati o audio di bassa qualità (telefonate, ambienti rumorosi) il WER può salire al 10-15%. Il parametro prompt con terminologia di dominio riduce ulteriormente gli errori su testo tecnico.
Come gestisco audio con più speaker?
Whisper di base non fa diarizzazione (non distingue chi sta parlando). Per identificare i diversi speaker hai due opzioni: usare un servizio specializzato come AssemblyAI che offre diarizzazione integrata, oppure combinare Whisper con una libreria di diarizzazione open-source come pyannote.audio. Con pyannote puoi prima identificare i segmenti per speaker, poi trascrivere ciascun segmento con Whisper, ottenendo una trascrizione con speaker labels.
Posso usare Whisper per la traduzione oltre che per la trascrizione?
Sì, ma con limitazioni. L’endpoint /v1/audio/translations (invece di /v1/audio/transcriptions) traduce direttamente in inglese qualsiasi lingua supportata. Quindi puoi prendere audio in italiano e ottenere testo in inglese in un solo passaggio. Non è possibile tradurre verso altre lingue diverse dall’inglese direttamente: per quello devi prima trascrivere nella lingua originale, poi usare un modello di traduzione separato come GPT-4o.
Conclusione
Whisper API è uno di quei building block che, una volta integrato, apre scenari che non avevi considerato. Trascrizioni di riunioni, sottotitoli automatici, note vocali indicizzabili, analisi del sentiment su chiamate di supporto: tutto diventa possibile con poche righe di codice.
La chiave è trattarla come un componente di una pipeline più ampia: Whisper converte l’audio in testo, poi passi quel testo ad altri strumenti AI per analisi, estrazione di informazioni o generazione di contenuti. Se stai già costruendo workflow di automazione o Micro SaaS da sviluppatore solitario, aggiungere la trascrizione audio al tuo stack è un investimento a bassissimo costo con ritorni concreti. Inizia da un caso d’uso semplice, misura il valore generato, e poi scala.
Suggerimenti e Risorse
🔧 Strumento: pydub è la libreria Python più comoda per manipolare file audio prima di inviarli a Whisper. Installa con
pip install pydube assicurati di avere ffmpeg sul sistema.
💡 Pro tip: Usa sempre il parametro
promptcon nomi propri e termini tecnici del tuo dominio. Una stringa di 50-100 parole con la terminologia specifica può ridurre gli errori del 30-40% su audio specializzati.
🎯 Strategia: Prima di implementare Whisper in un prodotto SaaS, definisci chiaramente il tuo budget per le trascrizioni. Calcola il costo medio per utente (minuti di audio al mese × 0.006$) e assicurati che sia coperto dal tuo piano pricing.

