Video e sottotitoli · Toolkit sottotitoli
Come un browser analizza un file SRT: blocchi, indici, codici temporali e testo
· Come funziona
sottotitoli srt formati di file
SRT sembra banale finché non incontri file reali. Questo post illustra come un parser divide i blocchi, legge indici e codici temporali, gestisce il testo su più righe e recupera i blocchi malformati contenuti nei file del mondo reale.
Il file "sembra a posto" ma mancano metà degli spunti: come un formato dall'aspetto indulgente nasconde aspettative rigorose
SRT non ha un corpo di specifica, nessuna registrazione MIME e nessun validatore fornito con i giocatori. Ciò che esiste invece è una forma su cui la maggior parte dei software concorda: un numero, una riga del timecode, una o più righe di testo, quindi una riga vuota. Poiché la forma è convenzionale anziché specificata, due file possono entrambi apparire corretti in un editor di testo mentre solo uno di essi viene caricato e l'errore è solitamente silenzioso. Un giocatore che non riesce a leggere una stecca tende a saltarla invece di segnalarla, quindi un file con un blocco rotto gioca con uno spazio vuoto invece che con un errore.
Un parser ha quindi due lavori che vanno in direzioni opposte. Deve accettare le variazioni che contengono i file reali, perché i file sono prodotti da servizi di trascrizione, editing manuale e convertitori di formato che fanno ciascuno presupposti diversi. Deve anche rifiutare letture che indicherebbero un segnale nel momento sbagliato, perché un timestamp silenziosamente sbagliato è peggiore di un fallimento segnalato.
Divisione in blocchi: righe vuote come separatori e problemi con spazi vuoti e CRLF
La divisione avviene su righe vuote, non sui numeri di indice. Il parser normalizza prima le terminazioni di riga, sostituendo sia la coppia CRLF che un CR solitario con un singolo fine riga, perché un file creato su Windows e modificato su Unix può contenerli entrambi. Quindi si divide su una sequenza di due o più ritorni a capo, ritaglia ciascun blocco risultante e scarta quelli vuoti. Questo ordine è importante: la divisione prima della normalizzazione lascerebbe un ritorno a capo vagante alla fine di una riga del timecode e il timecode non riuscirebbe quindi a corrispondere.
Un contrassegno dell'ordine dei byte viene rimosso prima di tutto ciò. Un UTF-8 BOM all'inizio di un file è composto da tre byte che un parser ingenuo vede come parte del primo numero di indice, il che è sufficiente per rendere illeggibile il primo segnale mentre ogni segnale successivo viene analizzato. Gli spazi finali su una linea di separazione altrimenti vuota vengono gestiti dal taglio, quindi un file le cui linee vuote contengono uno spazio viene comunque diviso correttamente.
La riga dell'indice: perché i numeri sono spesso errati, duplicati o mancanti e perché i parser non dovrebbero fidarsi di loro
Il numero di indice viene letto e quindi ignorato. I file reali numerano gli indizi da zero, riavviano la numerazione dopo un'unione, duplicano un numero dopo una modifica manuale o omettono completamente la riga quando un convertitore ha scritto il file. Fidarsi di quei numeri significa ereditare ognuno di questi difetti, quindi il parser assegna invece il proprio numero sequenziale, contando gli spunti che ha costruito con successo finora.
Questa scelta spiega anche perché il parser non richiede mai la presenza della riga dell'indice. Individua la riga del codice temporale cercando nel blocco la prima riga contenente la freccia, anziché presupporre che il codice temporale sia la seconda riga. Un blocco senza linea di indice viene analizzato normalmente e un blocco con due linee sparse prima del codice temporale viene comunque analizzato, poiché la posizione non è ciò che identifica il codice temporale.
La linea del timecode — HH:MM:SS,mmm --> HH:MM:SS,mmm, variazioni tollerate e quelle che spezzano i lettori
La linea del timecode viene confrontata con una singola espressione regolare e le tolleranze in essa contenute sono intenzionali. Le ore sono facoltative, perché WebVTT consente una lettura a due campi e i convertitori la emettono. Sia una virgola che un punto vengono accettati come separatore di millisecondi indipendentemente dal formato che il file dichiara di essere, poiché i separatori misti sono abbastanza comuni che rifiutarli farebbe fallire più file buoni che quelli cattivi. Le cifre frazionarie vengono riempite a destra, quindi un'indicazione che termina con una singola cifra viene letta come centinaia di millisecondi anziché come unità.
Vengono rifiutate due letture. Un campo dei minuti o dei secondi superiore a cinquantanove viene rifiutato anziché portato, poiché novanta secondi non è una lettura dell'orologio e solitamente indica un file corrotto o convertito in modo errato; normalizzarlo silenziosamente sposterebbe la stecca. Una riga il cui inizio o fine non riesce ad analizzare produce un problema registrato che nomina il testo incriminato e la forma prevista, e il blocco viene saltato anziché indovinato.
Righe di testo: segnali su più righe, tag di formattazione e dove finisce realmente un blocco
Tutto ciò che segue la riga del timecode è il testo di spunto, riunito insieme con i ritorni a capo. Non vi è alcun limite di riga né tentativo di ridisposizione, quindi un'indicazione di tre righe sopravvive come tre righe. Questo è il motivo per cui la riga vuota è portante: è l'unica cosa che dice al parser che il testo è terminato, motivo per cui una cue il cui testo contiene una riga vuota verrà letta come due blocchi e la seconda metà verrà segnalata come priva di timecode.
Le impostazioni della cue sono separate dal timestamp di fine da una sequenza di due o più spazi. WebVTT consente alle direttive di posizionamento come l'allineamento e il posizionamento della linea di seguire l'ora di fine sulla stessa riga, quindi il parser le divide prima che il timestamp venga analizzato e le mantiene accanto al segnale. Un singolo spazio non è un separatore, che impedisce a una linea di timecode semplicemente disordinata di perdere il suo tempo di fine.
Esempio funzionante: analisi di un file di cinque cue con due errori intenzionali: cosa recupera un parser robusto e cosa segnala
Prendi un file di cinque blocchi in cui il blocco tre ha avuto la linea del timecode danneggiata per leggere 00:01:75,000 --> 00:01:78,000 e il blocco quattro ha perso completamente la linea del timecode durante un copia e incolla. Il parser legge normalmente i blocchi uno e due e li numera uno e due. Il blocco tre corrisponde alla forma di un timecode ma contiene un campo dei secondi pari a settantacinque, quindi viene rifiutato e registrato come un timestamp errato che nomina la riga che non è stato in grado di leggere.
Il blocco quattro non contiene alcuna freccia, quindi viene registrato come privo di timestamp, citando i primi quaranta caratteri del blocco in modo che la riga possa essere trovata nel file originale. Blocca cinque analizza e diventa cue tre, non cue cinque, perché la numerazione conta le cue riuscite. Il risultato sono tre segnali utilizzabili e due reclami specifici e localizzati, piuttosto che un'eccezione sul primo errore e nessuna informazione sul secondo.
Cosa non copre: stile ASS/SSA, codici di posizionamento e testo non dei sottotitoli scaricati in SRT
Questo descrive SRT e le parti di WebVTT che condividono la sua forma di indicazione. Non copre ASS e SSA, che contengono un'intestazione di script, definizioni di stile e riferimenti di stile per evento e che non possono essere letti suddividendoli su righe vuote. Il timing del karaoke, i comandi di disegno e i tag di override in linea utilizzati da questi formati sono al di fuori di ciò che modella un parser di cue e timecode.
Inoltre non ripara il testo. Una trascrizione incollata in un file senza timecode produce un elenco di blocchi privi di timestamp, che viene riportato accuratamente ma non può essere trasformato in sottotitoli senza informazioni temporali che non sono presenti. Gli errori di codifica sono una preoccupazione separata: un file decodificato con il set di caratteri sbagliato viene analizzato in segnali perfettamente validi il cui testo è sbagliato e nessun controllo strutturale lo rileverà.
Conclusione: analizza con indulgenza, scrivi rigorosamente: come Subtitle Toolkit legge SRT disordinato e ne riscrive uno pulito
La regola di lavoro è analizzare con indulgenza e scrivere rigorosamente. All'ingresso, accetta orari opzionali, separatori, righe di indice mancanti, terminazioni di riga miste e un segno di ordine dei byte iniziale e registra ogni errore come problema individuato invece di lanciarlo sul primo, in modo che un file possa essere corretto in un unico passaggio. All'uscita, emetti una forma canonica.
Questo è ciò che fa Subtitle Toolkit quando converte. I segnali vengono rinumerati da uno e mantenuti contigui, i timestamp vengono riemessi con una virgola per SRT e un punto per WebVTT e il file che ritorna ha la forma che i giocatori si aspettano indipendentemente da quanto irregolare sia stato l'input. Incolla un file rifiutato da un giocatore nel convertitore e leggi prima i problemi segnalati; danno un nome alla stecca e citano la riga, il che di solito è sufficiente per trovare il difetto nell'originale.