Skip to content

Come annotare i sottotitoli di YouTube

Come scaricare i sottotitoli con yt-dlp e annotarli in Potato, cosa reggono e cosa non reggono i sottotitoli automatici, come gestire il video e cosa verificare prima di ridistribuire il materiale.

Scarica i sottotitoli con yt-dlp e punta Potato ai file. La cosa da sapere prima di tutto: i sottotitoli generati automaticamente non hanno punteggiatura né etichette dei parlanti, e le loro interruzioni di riga non significano niente, il che limita ciò che ha senso annotare. Potato legge tutti i formati di sottotitolo prodotti da yt-dlp. Per l'elenco completo vedi Formati di trascrizione.

Le piattaforme video sono una fonte ampia e comoda di parlato naturale. I sottotitoli per non udenti trasformano quel parlato in testo, e il testo è leggero, facile da spostare e facile da annotare. Il problema è che non tutti i sottotitoli sono lo stesso tipo di oggetto, e trattarli come se lo fossero è il punto in cui la maggior parte dei progetti basati sui sottotitoli va storta.

Come scarico i sottotitoli?

yt-dlp recupera i sottotitoli con o senza il file multimediale:

bash
# Human-written subtitles, if the uploader provided any
yt-dlp --write-subs --sub-langs en --skip-download <URL>
 
# Auto-generated captions
yt-dlp --write-auto-subs --sub-langs en --sub-format vtt --skip-download <URL>

Potato legge vtt, srt, json3, ttml e le varianti srv1, srv2 e srv3, quindi qualunque --sub-format tu scelga verrà interpretato. Scegli in base a cosa vuoi conservare: json3 mantiene i tempi per parola, mentre WebVTT e SubRip si leggono e si modificano a mano più facilmente.

Che differenza c'è tra sottotitoli umani e sottotitoli automatici?

In un editor di testo si somigliano, come materiale da annotare si comportano in modo molto diverso:

Sottotitoli umaniSottotitoli automatici
PunteggiaturaNo, o inaffidabile
Confini di fraseSignificativiArbitrari
ParlantiA volte, tramite i tag <v Name>Mai
Tempi per parolaNoSì, in json3
Fedeltà al parlatoSpesso condensati per la letturaPiù vicini a quello che è stato detto

Nessuno dei due è migliore in assoluto. I sottotitoli umani si leggono bene ma vengono editati per la leggibilità, quindi eliminano gli intercalari, comprimono le ripetizioni e a volte riscrivono una frase da capo. Quelli automatici sono più fedeli al parlato, che è ciò che serve per qualsiasi ricerca su come le persone parlano davvero, ma arrivano come un flusso senza punteggiatura.

Cosa posso annotare sui sottotitoli automatici?

Non progettare uno schema di annotazione a livello di frase sui sottotitoli automatici. I confini delle battute cadono dove la finestra del sottotitolo si è riempita, non dove finisce una frase. In un file di sottotitoli automatici una battuta è un artefatto di visualizzazione, non un'unità linguistica. Se chiedi agli annotatori di valutare frasi, ognuno sceglierà in silenzio confini di frase diversi, e i tuoi numeri di accordo finiranno per misurare quello invece della cosa che ti interessava.

Due opzioni praticabili:

  • Annota le finestre dei sottotitoli così come sono. Etichetta ogni battuta con quello che le si applica, accettando che l'unità sia arbitraria ma coerente. Va bene per il tema, per la presenza di un fenomeno o per qualsiasi cosa giudicabile su un frammento.
  • Ri-segmenta a monte. Fai girare un modello di ripristino della punteggiatura o un sistema ASR che punteggia, poi riallinea i tempi. Costa più lavoro, ma ottieni unità vere.

Se hai sottotitoli umani, il problema in gran parte sparisce. I confini delle battute sono stati messi da qualcuno che leggeva insieme al video, quindi di solito rispettano le proposizioni.

E il video?

I sottotitoli sono leggeri e facili da ridistribuire. Il video di solito no. Tre opzioni:

bash
# Media hosted somewhere your annotators can reach
potato transcripts ./captions --media-url-prefix https://cdn.example.org/video -o data/talks.json
 
# Media downloaded locally as audio only
yt-dlp -f 'ba' -x --audio-format mp3 -o './audio/%(id)s.%(ext)s' <URL>
potato transcripts ./captions --media-dir ./audio -o data/talks.json

La terza opzione è nessun media. Le trascrizioni senza media si annotano senza problemi: gli annotatori leggono invece di ascoltare. Se è questo il piano, scrivilo nelle istruzioni, perché altrimenti gli annotatori danno per scontato che il lettore mancante sia un bug e lo segnalano come tale.

Attenzione: verifica i tuoi diritti prima di ridistribuire qualcosa che non hai creato tu. Scaricare sottotitoli o materiale per la propria ricerca è una questione diversa dal servire quel materiale a un gruppo di annotatori, e sulla faccenda pesano i termini della piattaforma, il diritto d'autore e le regole del tuo ente. Risolvila prima di costruire la pipeline, non dopo.

Come imposto il task?

Il convertitore scrive un file di dati con la trascrizione già normalizzata:

bash
potato transcripts ./captions --media-dir ./audio -o data/talks.json
json
{
  "id": "talk_01",
  "conversation": {
    "audio": "audio/talk_01.mp3",
    "turns": [
      {"turn_id": "t0", "speaker": null, "start": 0.0, "end": 4.2,
       "text": "so the thing about caption windows is"}
    ]
  }
}

speaker: null è quello che ti dà un sottotitolo automatico. Quei turni compaiono come Non assegnati con un selettore, così gli annotatori possono attribuirli mentre ascoltano.

Tre turni da sottotitoli automatici su sfondo grigio tratteggiato, ciascuno marcato come Non assegnato con una freccia a discesa e una domanda in linea agganciata a ogni turno.I sottotitoli automatici non portano parlanti, quindi ogni battuta resta Non assegnata finché un annotatore non ne sceglie uno

yaml
annotation_task_name: "Talk Annotation"
task_dir: .
data_files:
  - data/talks.json
 
item_properties:
  id_key: id
  text_key: conversation
 
instance_display:
  fields:
    - key: conversation
      type: audio_dialogue
      label: "Captions"
      span_target: true
      display_options:
        show_timestamps: true
        allow_speaker_assignment: auto
 
annotation_schemes:
  - annotation_type: radio
    name: cue_topic
    description: "What is this caption window about?"
    labels: [setup, argument, example, aside]

turn_level: true aggancia la domanda a ogni battuta invece che al video nel suo insieme, che è l'unità giusta quando le battute sono tutto quello che hai. Per avviarlo:

bash
python potato/flask_server.py start config.yaml -p 8000

Puoi anche saltare del tutto il convertitore e far puntare un file di dati ai file di sottotitoli su disco. Vedi Annotare le trascrizioni di Whisper, dove il resto del flusso è identico.

Approfondimenti