Skip to content

Transkriptformate

Alle Transkript- und Untertitelformate, die Potato liest: Whisper, WhisperX, Deepgram, AssemblyAI, AWS Transcribe, SRT, WebVTT, TTML, YouTube-Untertitel, CTM, Praat TextGrid und ELAN EAF, dazu Begleitdateien und das normalisierte Turn-Modell.

Potato liest 21 Transkript- und Untertiteleingaben und überführt sie alle in dasselbe Turn-Modell, bevor überhaupt etwas angezeigt wird. Was auch immer Ihre ASR-Pipeline oder Ihr Untertitelwerkzeug produziert hat, Sie können Potato darauf ansetzen, ohne ein Konvertierungsskript zu schreiben. Diese Seite ist die Referenz dafür, was funktioniert, wie jedes Format erkannt wird und was es jeweils mitbringt. Die Schritt-für-Schritt-Anleitungen sind Whisper-Transkripte annotieren und YouTube-Untertitel annotieren.

Ein Transkript als farbige Sprecherblasen, jede mit eigenem Abspielknopf, Zeitmarken und einer Beschriftungsfrage pro Turn.Eine SRT-Begleitdatei als Sprecherblasen, mit einer Frage an jedem Turn

Potato transkribiert nicht

Spracherkennung und Sprecherdiarisierung laufen, bevor Potato etwas zu sehen bekommt. Führen Sie zuerst Whisper, WhisperX, pyannote oder eine Cloud-API aus; Potato liest das Ergebnis ein. Nichts auf dieser Seite startet ein Modell.

Note: Der Think-Aloud-Modus führt sehr wohl ein lokales Whisper-Modell aus, aber zu einem anderen Zweck: Er nimmt Annotierende auf, während sie beim Arbeiten sprechen. Das ist eine Aufnahmefunktion, keine Transkriptverarbeitung.

Erkennung erfolgt über den Inhalt, nicht über die Dateiendung

Potato sieht sich an, was in der Datei steht, statt dem Namen zu vertrauen. Eine WebVTT-Datei namens captions.txt wird weiterhin als WebVTT gelesen. Praktisch heißt das: Dasselbe Transkript funktioniert eingebettet in Ihrer Datendatei oder als Begleitdatei auf der Festplatte, ohne Änderung an der Konfiguration.

Unterstützte Formate

ASR-Ausgaben

FormatErkannt anSprecherWortzeiten
Whisper JSONArray segmentsNeinJa, mit --word_timestamps
WhisperX / diarisiertes JSONsegments mit speakerJaJa
whisper.cpp JSONArray transcriptionNeinNein
Whisper TSVKopfzeile start/end/textNeinNein
AWS Transcriberesults.items oder results.audio_segmentsJaJa
Deepgramresults.channels oder results.utterancesJa, mit diarize=trueJa
AssemblyAItext plus words/utterancesJa, mit speaker_labelsJa
Rev.aiArray monologuesJaJa
SPoRCZeilen turn_text/turnTextJa, abgeleitetNein

Untertitel

FormatErkannt anSprecher
SubRip (.srt)Pfeile zwischen Zeitmarken, Trenner ,mmmÜber ein Name:-Präfix
WebVTT (.vtt)Kopfzeile WEBVTTÜber <v Name>-Tags oder ein Name:-Präfix
SubStation Alpha (.ass, .ssa)[Script Info] / Dialogue:Über das Feld Name
TTML / DFXPWurzelelement <tt>Über ein Attribut speaker/agent
YouTube srv1/srv2/srv3XML <transcript><text>Über ein Name:-Präfix
YouTube json3Array eventsKeine; automatische Untertitel haben keine

SubRip und WebVTT decken das meiste ab, was Ihnen begegnen wird. TTML taucht in Rundfunkarchiven und in Exporten professioneller Untertitelwerkzeuge auf.

Alignment und linguistische Annotation

FormatErkannt anSprecher
NIST CTMDurch Leerzeichen getrennte Spalten, numerischer Start und DauerÜber das Kanalfeld
Praat TextGridFile type = "ooTextFile"Eine Ebene pro Sprecher
ELAN EAFWurzel ANNOTATION_DOCUMENTÜber PARTICIPANT, sonst die Ebenen-ID

Sowohl die lange als auch die kurze TextGrid-Serialisierung wird gelesen. Bei ELAN-Dateien löst Potato ALIGNABLE_ANNOTATION und REF_ANNOTATION gegen die TIME_ORDER-Tabelle auf und liest den Medienverweis aus dem Kopfbereich.

Ein Praat TextGrid als zwei Sprecher namens fieldworker und speaker, einer pro Ebene, ohne die Stilleintervalle.Jede TextGrid-Ebene wird zu einem Sprecher, die leeren Intervalle dazwischen entfallen

Alles Übrige

Drei generische Formen vervollständigen die 21:

  • Eine einfache Liste von {speaker, start, end, text}-Dictionaries.
  • Ein Objekt {"audio": ..., "turns": [...]}.
  • Ein reiner Absatz ganz ohne Zeitangaben, der als eine einzige Blase erscheint.

Nicht unterstützt

Dafür existiert kein Parser. Konvertieren Sie diese vorher.

  • SAMI (.smi), MicroDVD (.sub), SubViewer (.sbv)
  • Transcriber (.trs), EXMARaLDA, CHAT/CHILDES (.cha)
  • Native Ausgaben von Montreal Forced Aligner und Gentle. Exportieren Sie von dort stattdessen CTM oder TextGrid.
  • Azure Speech, Google Speech-to-Text und verbose_json der Whisper-API in ungewöhnlichen Hüllen
  • RTTM-Diarisierungsdateien für sich allein

Wortweise Konfidenz wird gelesen und im Datenmodell behalten, sofern die Quelle sie liefert, aber es gibt derzeit keine Oberfläche, um sie anzusehen.

Das normalisierte Turn-Modell

Aus allen obigen Formaten wird dies:

json
{
  "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 und confidence erscheinen nur, wenn die Quelle sie mitgebracht hat. speaker ist null bei nicht diarisierten Turns, die als Unassigned mit einer Auswahl erscheinen, damit Annotierende sie ergänzen können.

Drei Transkript-Turns mit grau schraffiertem Hintergrund, jeweils als Unassigned mit Auswahlpfeil beschriftet, weil das Quellformat keine Sprecherlabels enthielt.Automatische YouTube-Untertitel kommen ohne Sprecher an, also bleibt jeder Turn Unassigned, bis jemand einen auswählt

turn_id ist der Persistenzschlüssel für Annotationen pro Turn und für Sprecherzuweisungen. Sie stammt aus einem expliziten turn_id- oder step_id-String in der Quelle, sonst aus t{Index}. Dieselbe Datei erzeugt immer dieselben IDs, sodass Annotationen ein Neuladen überstehen.

Warning: Die Zeiteinheiten unterscheiden sich je nach Werkzeug. Whisper und Deepgram verwenden Sekunden als Fließkommazahl; AssemblyAI, die Offsets von whisper.cpp und die TSV-Ausgabe von Whisper verwenden ganzzahlige Millisekunden. Potato konvertiert an der Grenze, damit alles Weitere in Sekunden vorliegt. Wenn Ihre eigene Vorverarbeitung beides vermischt, sind die Zeiten um den Faktor 1000 falsch.

Begleitdateien

Ein Feldwert, der ein kurzer einzeiliger Pfad mit bekannter Transkriptendung ist, wird von der Festplatte gelesen statt als Text behandelt. So funktioniert genau die Ablage, die Ihr ASR-Werkzeug ohnehin erzeugt hat, mit den Mediendateien neben ihrer .srt oder .json, ganz ohne Vorverarbeitung:

json
{
  "id": "int_001",
  "conversation": {
    "audio": "media/int_001.mp3",
    "transcript": "media/int_001.srt"
  }
}

Pfade werden relativ zu task_dir aufgelöst und durchlaufen dieselbe Pfadsicherheitsprüfung wie jeder andere konfigurierte Pfad, sodass eine Datendatei nicht außerhalb des Projekts lesen kann.

Erkannte Endungen: .srt .vtt .webvtt .json .json3 .srv1 .srv2 .srv3 .ttml .dfxp .xml .ass .ssa .tsv .ctm .TextGrid .eaf .txt

Wenn Ihre Daten tatsächlich einzeilige Transkripte enthalten, die wie Dateinamen aussehen, schalten Sie die Heuristik ab:

yaml
display_options:
  transcript_is_path: auto   # auto (default) | true | false

Konfiguration

Anzeige: audio_dialogue

Die Audio-Dialoganzeige stellt Turns als Sprecherblasen dar, synchron zum Audio, mit einem Abspielknopf an jedem Turn.

yaml
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
OptionStandardWirkung
audio_keyaudioUnterschlüssel des Feldwerts mit der Audio-URL oder dem Pfad.
turns_keyturnsUnterschlüssel mit der Turn-Liste. Akzeptiert auch segments.
speaker_key / text_keyspeaker / textSchlüssel pro Turn.
speakers[]Liste aus {id, name, color, side}. Nicht aufgeführte Sprecher erhalten eine deterministische Farbe und eine abwechselnde Seite.
allow_speaker_assignmentautoauto aktiviert die Zuweisung per Klick, wenn es nicht diarisierte Turns oder eine zu korrigierende Liste gibt. true erzwingt sie, false schaltet sie ab.
transcript_is_pathautoOb der Feldwert als Pfad zu einer Begleitdatei gelesen wird.
show_timestampstrueZeigt mm:ss–mm:ss an jedem Turn.
scroll_height480pxHöhe des scrollbaren Transkriptbereichs.
playback_rates[1, 1.25, 1.5, 2]Optionen im Geschwindigkeitsmenü.

Schemata

Seit 2.7.1 lesen speech_transcript, voice_interaction und tiered_annotation ein Transkript direkt aus dem Instanzdatensatz und akzeptieren alle Formate auf dieser Seite. Vorher tat das nur die Anzeige audio_dialogue.

yaml
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: turns

Die Ebenen-Annotation kann eine Ebene aus dem Transkript vorbefüllen, sodass Annotierende ein bestehendes Alignment korrigieren, statt die Sprache von Hand neu zu segmentieren:

yaml
  - 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"

Vorbefüllte Annotationen werden erst geschrieben, wenn jemand tatsächlich etwas ändert, sodass niemandem etwas zugerechnet wird, der die Instanz nur geöffnet hat.

Eine Datendatei mit potato transcripts bauen

Richten Sie den Konverter auf einen Ordner mit ASR-Ausgaben, und er schreibt eine annotationsfertige Datendatei:

bash
# 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 meldet, was gefunden wurde, ohne etwas zu schreiben. Das ist der schnellste Weg, einen Ordner mit der falschen Whisper-Ausgabedatei zu erkennen:

text
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.
OptionZweck
-o, --outputWohin geschrieben wird. Pflicht, außer bei --dry-run.
--formatjson (Standard) oder jsonl.
--media-dirMedienordner, der über den Basisnamen zugeordnet wird.
--media-url-prefixBasis-URL für Medien statt lokaler Dateien.
--fieldFeld des Items, in das das Transkript kommt. Standard conversation.
--id-prefixZeichenkette, die jeder erzeugten ID vorangestellt wird.
--speaker-keyQuellschlüssel mit dem Sprecherlabel.
-r, --recursiveBezieht Unterordner ein.
--dry-runMeldet erkanntes Format und Turn-Anzahl je Datei.
--emit-configGibt zusätzlich ein passendes config.yaml-Fragment aus.
-q, --quietUnterdrückt den Bericht pro Datei.

Item-IDs stammen aus dem Dateinamen ohne eine abschließende Medienendung, also wird aus Whispers interview_01.mp3.json ein interview_01 und nicht interview_01.mp3.

Wieder hinausexportieren

Ebenen-Annotationen lassen sich nach ELAN EAF und Praat TextGrid exportieren, sodass ein Transkript einen vollen Kreis läuft: einlesen, in Potato annotieren, exportieren, in ELAN oder Praat verfeinern und das Ergebnis wieder einlesen.

bash
python -m potato.export --config config.yaml --format eaf --output ./out/
python -m potato.export --config config.yaml --format textgrid --output ./out/

Beide Exporter arbeiten mit der Ausgabe von tiered_annotation. Andere Schemata werden über die Standardformate exportiert.

Fehlersuche

SymptomWas passiert ist
Alles erscheint als eine große BlaseDas Format wurde nicht erkannt und fiel auf die Absatz-Rückfallebene zurück. Führen Sie potato transcripts <file> --dry-run aus; meldet es plain text, wurden die Zeiten nie gelesen. Meist ist die Datei ein Whisper-.txt ohne jede Zeitangabe statt der .json oder .srt.
Keine Sprecher, alles UnassignedDie Quelle enthält keine Sprecherlabels. Whisper allein diarisiert nicht, automatische YouTube-Untertitel auch nicht. Diarisieren Sie vorher oder lassen Sie Annotierende die Sprecher in der Oberfläche zuweisen.
Die Zeiten sind um Faktor 1000 falschSekunden und Millisekunden wurden vorher vermischt. Die offsets von whisper.cpp, AssemblyAI und Whispers TSV sind alle in Millisekunden.
Der Transkriptpfad erscheint als TranskripttextDie Begleitdatei war nicht lesbar, also wurde der Pfad als Inhalt angezeigt. Prüfen Sie, ob er unterhalb von task_dir aufgelöst wird. Die Serverprotokolle nennen den genauen Grund.
Ein einzeiliges Inline-Transkript wird als Dateiname gelesenSetzen Sie transcript_is_path: false am Anzeigefeld.

Beispielprojekt

examples/audio/transcript-formats/ im Potato-Repository zeigt sechs Formate nebeneinander, jedes aus einer Begleitdatei geladen: SubRip, WebVTT, Whisper JSON, YouTube json3, Praat TextGrid und Deepgram. Alle sechs erzeugen dieselben Sprecherblasen.

bash
python potato/flask_server.py start examples/audio/transcript-formats/config.yaml -p 8000

Dieselbe Aufgabe gibt es als herunterladbares Showcase-Design: Transcript Format Ingestion.

Implementierungsdetails stehen in der Quelldokumentation.

Weiterführend