Formati di trascrizione
Tutti i formati di trascrizione e sottotitoli che Potato legge: Whisper, WhisperX, Deepgram, AssemblyAI, AWS Transcribe, SRT, WebVTT, TTML, sottotitoli di YouTube, CTM, Praat TextGrid ed ELAN EAF, oltre ai file affiancati e al modello di turni normalizzato.
Potato legge 21 tipi di input tra trascrizioni e sottotitoli e li converte tutti nello stesso modello di turni prima di mostrare qualsiasi cosa. Qualunque cosa abbia prodotto la tua pipeline di riconoscimento vocale o il tuo strumento di sottotitolaggio, puoi puntarci Potato senza scrivere uno script di conversione. Questa pagina è il riferimento su cosa funziona, su come viene riconosciuto ogni formato e su cosa ciascuno porta con sé. Per il percorso passo passo, vedi Come annotare trascrizioni Whisper e Come annotare sottotitoli di YouTube.
Un file SRT affiancato mostrato come fumetti per parlante, con una domanda su ogni turno
Potato non trascrive
Il riconoscimento vocale e la diarizzazione dei parlanti avvengono prima che Potato veda qualcosa. Esegui prima Whisper, WhisperX, pyannote o un'API in cloud; Potato ne acquisisce il risultato. Niente in questa pagina esegue un modello.
Note: La modalità Think-Aloud esegue davvero un modello Whisper locale, ma con un altro scopo: registra chi annota mentre parla lavorando. È una funzione di cattura, non di acquisizione di trascrizioni.
Il riconoscimento avviene sul contenuto, non sull'estensione
Potato guarda cosa c'è dentro il file invece di fidarsi del nome. Un file WebVTT chiamato captions.txt viene comunque interpretato come WebVTT. La conseguenza pratica è che la stessa trascrizione funziona incorporata nel file di dati oppure letta da un file affiancato su disco, senza cambiare la configurazione.
Formati supportati
Output di riconoscimento vocale
| Formato | Riconosciuto da | Parlanti | Tempi per parola |
|---|---|---|---|
| Whisper JSON | Array segments | No | Sì, con --word_timestamps |
| WhisperX / JSON diarizzato | segments con speaker | Sì | Sì |
| whisper.cpp JSON | Array transcription | No | No |
| Whisper TSV | Intestazione start/end/text | No | No |
| AWS Transcribe | results.items o results.audio_segments | Sì | Sì |
| Deepgram | results.channels o results.utterances | Sì, con diarize=true | Sì |
| AssemblyAI | text più words/utterances | Sì, con speaker_labels | Sì |
| Rev.ai | Array monologues | Sì | Sì |
| SPoRC | Righe turn_text/turnText | Sì, dedotti | No |
Sottotitoli
| Formato | Riconosciuto da | Parlanti |
|---|---|---|
SubRip (.srt) | Frecce tra i tempi, separatore ,mmm | Da un prefisso Name: |
WebVTT (.vtt) | Intestazione WEBVTT | Da tag <v Name> o da un prefisso Name: |
SubStation Alpha (.ass, .ssa) | [Script Info] / Dialogue: | Dal campo Name |
| TTML / DFXP | Elemento radice <tt> | Da un attributo speaker/agent |
| YouTube srv1/srv2/srv3 | XML <transcript><text> | Da un prefisso Name: |
| YouTube json3 | Array events | Nessuno; i sottotitoli automatici non ne hanno |
SubRip e WebVTT coprono quasi tutto quello che incontrerai. TTML compare negli archivi televisivi e nelle esportazioni degli strumenti professionali di sottotitolaggio.
Allineamento e annotazione linguistica
| Formato | Riconosciuto da | Parlanti |
|---|---|---|
| NIST CTM | Colonne separate da spazi, inizio e durata numerici | Dal campo di canale |
| Praat TextGrid | File type = "ooTextFile" | Un livello per parlante |
| ELAN EAF | Radice ANNOTATION_DOCUMENT | Da PARTICIPANT, altrimenti l'id del livello |
Vengono interpretate sia la serializzazione lunga sia quella breve di TextGrid. Per i file ELAN, Potato risolve ALIGNABLE_ANNOTATION e REF_ANNOTATION rispetto alla tabella TIME_ORDER e legge il riferimento al media dall'intestazione.
Ogni livello del TextGrid diventa un parlante, e gli intervalli vuoti in mezzo vengono saltati
Tutto il resto
Tre forme generiche completano i 21:
- Un semplice elenco di dizionari
{speaker, start, end, text}. - Un oggetto
{"audio": ..., "turns": [...]}. - Un paragrafo semplice senza alcun tempo, mostrato come un unico fumetto.
Non supportati
Per questi non esiste alcun parser. Convertili prima.
- SAMI (
.smi), MicroDVD (.sub), SubViewer (.sbv) - Transcriber (
.trs), EXMARaLDA, CHAT/CHILDES (.cha) - Output nativi di Montreal Forced Aligner e Gentle. Esporta invece CTM o TextGrid da quegli strumenti.
- Azure Speech, Google Speech-to-Text e il
verbose_jsondell'API Whisper dentro involucri inusuali - File di diarizzazione RTTM da soli
La confidenza a livello di parola viene letta e conservata nel modello dati quando la sorgente la fornisce, ma al momento non esiste un'interfaccia per visualizzarla.
Il modello di turni normalizzato
Tutti i formati elencati sopra diventano questo:
{
"audio": "media/interview_01.mp3",
"turns": [
{
"turn_id": "t0",
"speaker": "host",
"start": 0.0,
"end": 6.5,
"text": "Welcome back.",
"words": [{"word": "Welcome", "start": 0.0, "end": 0.4, "confidence": 0.99}],
"confidence": 0.97
}
]
}words e confidence compaiono solo se la sorgente li portava. speaker è null per i turni non diarizzati, che appaiono come Unassigned con un selettore così che chi annota possa completarli.
I sottotitoli automatici di YouTube arrivano senza parlanti, quindi ogni turno resta Unassigned finché qualcuno non ne sceglie uno
turn_id è la chiave di persistenza per le annotazioni per turno e per le assegnazioni di parlante. Deriva da una stringa turn_id o step_id esplicita nella sorgente quando c'è, altrimenti da t{indice}. Lo stesso file produce sempre gli stessi identificatori, quindi le annotazioni sopravvivono a un ricaricamento.
Warning: Le unità di tempo cambiano da strumento a strumento. Whisper e Deepgram usano secondi in virgola mobile; AssemblyAI, gli offset di whisper.cpp e l'output TSV di Whisper usano millisecondi interi. Potato converte al confine così che tutto il resto sia in secondi. Se il tuo pre-processing mescola i due, i tempi escono sbagliati di mille volte.
File affiancati
Un valore di campo che sia un percorso breve su una sola riga terminante con un'estensione di trascrizione nota viene letto da disco invece di essere trattato come testo. Così la disposizione che il tuo strumento di riconoscimento vocale ha già prodotto, con i file multimediali accanto al loro .srt o .json, funziona senza alcun passaggio di pre-elaborazione:
{
"id": "int_001",
"conversation": {
"audio": "media/int_001.mp3",
"transcript": "media/int_001.srt"
}
}I percorsi si risolvono rispetto a task_dir e passano dalla stessa validazione di sicurezza di ogni altro percorso configurato, quindi un file di dati non può leggere fuori dal progetto.
Estensioni riconosciute: .srt .vtt .webvtt .json .json3 .srv1 .srv2 .srv3 .ttml .dfxp .xml .ass .ssa .tsv .ctm .TextGrid .eaf .txt
Se i tuoi dati contengono davvero trascrizioni di una riga che sembrano nomi di file, disattiva l'euristica:
display_options:
transcript_is_path: auto # auto (default) | true | falseConfigurazione
Visualizzazione: audio_dialogue
La visualizzazione a dialogo audio mostra i turni come fumetti per parlante sincronizzati con l'audio, con un pulsante di riproduzione su ogni turno.
instance_display:
fields:
- key: conversation
type: audio_dialogue
label: "Transcript"
span_target: true
display_options:
audio_key: audio
turns_key: turns
speaker_key: speaker
text_key: text
transcript_is_path: auto
show_timestamps: true
allow_speaker_assignment: auto
scroll_height: 460px| Opzione | Predefinito | Cosa fa |
|---|---|---|
audio_key | audio | Sottochiave del valore di campo che contiene l'URL o il percorso dell'audio. |
turns_key | turns | Sottochiave che contiene l'elenco dei turni. Accetta anche segments. |
speaker_key / text_key | speaker / text | Chiavi per turno. |
speakers | [] | Elenco di {id, name, color, side}. I parlanti non elencati ricevono un colore deterministico e un lato alternato. |
allow_speaker_assignment | auto | auto attiva l'assegnazione con un clic quando ci sono turni non diarizzati o un elenco da correggere. true la forza, false la disattiva. |
transcript_is_path | auto | Se leggere il valore del campo come percorso a un file affiancato. |
show_timestamps | true | Mostra mm:ss–mm:ss su ogni turno. |
scroll_height | 480px | Altezza del riquadro di trascrizione scorrevole. |
playback_rates | [1, 1.25, 1.5, 2] | Opzioni nel selettore di velocità. |
Schemi
Dalla 2.7.1, speech_transcript, voice_interaction e tiered_annotation leggono una trascrizione direttamente dal record dell'istanza e accettano tutti i formati di questa pagina. Prima lo faceva solo la visualizzazione audio_dialogue.
annotation_schemes:
- annotation_type: speech_transcript
name: transcript_review
description: "Mark transcription errors"
segments_key: segments # record field holding the transcript
- annotation_type: voice_interaction
name: barge_in
description: "Mark overlaps and barge-in"
turns_key: turnsL'annotazione a livelli può precompilare un livello a partire dalla trascrizione, così chi annota corregge un allineamento esistente invece di risegmentare il parlato a mano:
- annotation_type: tiered_annotation
name: tiers
source_field: audio_url
media_type: audio
transcript_field: asr_output # opt-in; omit to start from a blank timeline
transcript_tier: utterance # defaults to the first tier
tiers:
- name: utterance
labels:
- name: speech
color: "#7c3aed"Le annotazioni precompilate non vengono salvate finché chi annota non fa una modifica vera, così nulla viene attribuito a chi si è limitato ad aprire l'istanza.
Costruire un file di dati con potato transcripts
Punta il convertitore a una cartella di output di riconoscimento vocale e scriverà un file di dati pronto per l'annotazione:
# Pair transcripts to media by basename
potato transcripts ./whisper_out --media-dir ./audio -o data/interviews.json
# Media served from elsewhere
potato transcripts './captions/*.vtt' \
--media-url-prefix https://cdn.example.org/audio -o data/talks.json
# What did it detect? Writes nothing.
potato transcripts ./whisper_out --dry-run--dry-run riferisce cosa ha trovato senza scrivere niente, ed è il modo più rapido per accorgersi di una cartella con il file di output Whisper sbagliato:
Scanned 3 file(s):
talk_01.srt SRT 2 turns 5.0s 2 speaker(s): Alice, Bob
talk_02.vtt WebVTT 1 turns 3.0s undiarized
talk_03.json whisper.cpp JSON 1 turns 2.4s undiarized
3 item(s), 4 turn(s).
1 item(s) have no media. Pass --media-dir or --media-url-prefix to enable playback.
| Opzione | A cosa serve |
|---|---|
-o, --output | Dove scrivere. Obbligatorio tranne che con --dry-run. |
--format | json (predefinito) o jsonl. |
--media-dir | Cartella di file multimediali da abbinare per nome base. |
--media-url-prefix | URL di base dei media invece di file locali. |
--field | Campo dell'elemento in cui va la trascrizione. Predefinito conversation. |
--id-prefix | Stringa anteposta a ogni id generato. |
--speaker-key | Chiave di origine che contiene l'etichetta di parlante. |
-r, --recursive | Percorre le sottocartelle. |
--dry-run | Riferisce il formato riconosciuto e il numero di turni per file. |
--emit-config | Stampa anche un frammento di config.yaml corrispondente. |
-q, --quiet | Silenzia il resoconto per file. |
Gli identificatori degli elementi derivano dal nome del file privato di un'estensione multimediale finale, quindi interview_01.mp3.json di Whisper diventa interview_01 e non interview_01.mp3.
Esportare di nuovo
Le annotazioni a livelli si esportano in ELAN EAF e Praat TextGrid, quindi una trascrizione può fare andata e ritorno: acquisirla, annotarla in Potato, esportarla, rifinirla in ELAN o Praat e rileggere il risultato.
python -m potato.export --config config.yaml --format eaf --output ./out/
python -m potato.export --config config.yaml --format textgrid --output ./out/Entrambi gli esportatori partono dall'output di tiered_annotation. Gli altri schemi si esportano attraverso i formati standard.
Risoluzione dei problemi
| Sintomo | Cosa è successo |
|---|---|
| Tutto appare come un unico grande fumetto | Il formato non è stato riconosciuto ed è ricaduto sul ripiego a paragrafo semplice. Esegui potato transcripts <file> --dry-run; se riporta plain text, i tempi non sono mai stati letti. Di solito il file è un .txt di Whisper, che non ha alcun tempo, invece del .json o del .srt. |
| Nessun parlante, tutto Unassigned | La sorgente non contiene etichette di parlante. Whisper da solo non diarizza, e nemmeno i sottotitoli automatici di YouTube. Esegui la diarizzazione a monte oppure lascia che chi annota assegni i parlanti nell'interfaccia. |
| I tempi sono sbagliati di mille volte | Secondi e millisecondi sono stati mescolati a monte. Gli offsets di whisper.cpp, AssemblyAI e il TSV di Whisper sono tutti in millisecondi. |
| Il percorso della trascrizione appare come testo | Il file affiancato non è stato leggibile, quindi il percorso è stato mostrato come contenuto. Verifica che si risolva dentro task_dir. I log del server indicano il motivo preciso. |
| Una trascrizione su una riga viene letta come nome di file | Imposta transcript_is_path: false sul campo di visualizzazione. |
Progetto di esempio
examples/audio/transcript-formats/ nel repository di Potato mostra sei formati affiancati, ciascuno caricato da un file esterno: SubRip, WebVTT, Whisper JSON, YouTube json3, Praat TextGrid e Deepgram. Tutti e sei producono gli stessi fumetti per parlante.
python potato/flask_server.py start examples/audio/transcript-formats/config.yaml -p 8000Lo stesso compito è disponibile come progetto scaricabile: Transcript Format Ingestion.
Per i dettagli di implementazione, vedi la documentazione di origine.
Approfondimenti
- Come annotare trascrizioni Whisper, il percorso completo
- Come annotare sottotitoli di YouTube, per i sottotitoli e i loro limiti
- Annotazione di dialoghi, la visualizzazione a fumetti per parlante
- Annotazione audio, la segmentazione della forma d'onda da zero
- Progettare formati di dati per l'annotazione