Skip to content

ट्रांसक्रिप्ट प्रारूप

Potato जिन सभी ट्रांसक्रिप्ट और सबटाइटल प्रारूपों को पढ़ता है: Whisper, WhisperX, Deepgram, AssemblyAI, AWS Transcribe, SRT, WebVTT, TTML, YouTube कैप्शन, CTM, Praat TextGrid और ELAN EAF, साथ ही साइडकार फ़ाइलें और सामान्यीकृत टर्न मॉडल।

Potato 21 तरह के ट्रांसक्रिप्ट और सबटाइटल इनपुट पढ़ता है और कुछ भी दिखाने से पहले उन सबको एक ही टर्न मॉडल में बदल देता है। आपकी ASR पाइपलाइन या कैप्शनिंग टूल ने जो भी बनाया हो, आप Potato को सीधे उसी पर लगा सकते हैं, कोई कन्वर्ज़न स्क्रिप्ट लिखे बिना। यह पृष्ठ इस बात का संदर्भ है कि क्या काम करता है, हर प्रारूप कैसे पहचाना जाता है और हर एक क्या देता है। चरण-दर-चरण मार्गदर्शन के लिए देखें Whisper ट्रांसक्रिप्ट कैसे एनोटेट करें और YouTube सबटाइटल कैसे एनोटेट करें

एक ट्रांसक्रिप्ट रंगीन वक्ता बुलबुलों के रूप में, हर एक में अपना प्ले बटन, समय-चिह्न और प्रति-टर्न लेबलिंग प्रश्न।एक साइडकार SRT फ़ाइल वक्ता बुलबुलों के रूप में, हर टर्न के साथ एक प्रश्न

Potato ट्रांसक्रिप्शन नहीं करता

वाक् पहचान और वक्ता डायराइज़ेशन Potato के कुछ भी देखने से पहले होते हैं। पहले Whisper, WhisperX, pyannote या कोई क्लाउड API चलाइए; Potato उसका परिणाम पढ़ता है। इस पृष्ठ पर कुछ भी कोई मॉडल नहीं चलाता।

Note: Think-Aloud मोड वाकई एक स्थानीय Whisper मॉडल चलाता है, पर दूसरे उद्देश्य से: वह एनोटेटर्स को काम करते हुए बोलते समय रिकॉर्ड करता है। वह एक रिकॉर्डिंग सुविधा है, ट्रांसक्रिप्ट पढ़ने की नहीं।

पहचान सामग्री से होती है, एक्सटेंशन से नहीं

Potato फ़ाइल के नाम पर भरोसा करने के बजाय उसके भीतर देखता है। captions.txt नाम की WebVTT फ़ाइल फिर भी WebVTT की तरह पढ़ी जाती है। व्यावहारिक परिणाम यह है कि वही ट्रांसक्रिप्ट आपकी डेटा फ़ाइल में सीधे लिखा हो या डिस्क पर अलग फ़ाइल से पढ़ा जाए, दोनों तरह काम करता है, कॉन्फ़िगरेशन बदले बिना।

समर्थित प्रारूप

ASR आउटपुट

प्रारूपकिससे पहचाना जाता हैवक्ताशब्द-स्तरीय समय
Whisper JSONsegments सरणीनहींहाँ, --word_timestamps के साथ
WhisperX / डायराइज़्ड JSONspeaker वाले segmentsहाँहाँ
whisper.cpp JSONtranscription सरणीनहींनहीं
Whisper TSVstart/end/text शीर्षकनहींनहीं
AWS Transcriberesults.items या results.audio_segmentsहाँहाँ
Deepgramresults.channels या results.utterancesहाँ, diarize=true के साथहाँ
AssemblyAItext के साथ words/utterancesहाँ, speaker_labels के साथहाँ
Rev.aimonologues सरणीहाँहाँ
SPoRCturn_text/turnText पंक्तियाँहाँ, अनुमानितनहीं

सबटाइटल और कैप्शन

प्रारूपकिससे पहचाना जाता हैवक्ता
SubRip (.srt)क्यू तीर, ,mmm विभाजकName: उपसर्ग से
WebVTT (.vtt)WEBVTT शीर्षक<v Name> टैग या Name: उपसर्ग से
SubStation Alpha (.ass, .ssa)[Script Info] / Dialogue:Name फ़ील्ड से
TTML / DFXP<tt> मूल तत्वspeaker/agent विशेषता से
YouTube srv1/srv2/srv3<transcript><text> XMLName: उपसर्ग से
YouTube json3events सरणीकोई नहीं; स्वतः कैप्शन में वक्ता नहीं होते

SubRip और WebVTT उन ज़्यादातर चीज़ों को कवर करते हैं जो आपको मिलेंगी। TTML प्रसारण अभिलेखागार में और पेशेवर कैप्शनिंग टूल से निर्यात की गई फ़ाइलों में दिखता है।

संरेखण और भाषाई एनोटेशन

प्रारूपकिससे पहचाना जाता हैवक्ता
NIST CTMरिक्त स्थान से अलग किए स्तंभ, संख्यात्मक आरंभ और अवधिचैनल फ़ील्ड से
Praat TextGridFile type = "ooTextFile"प्रति वक्ता एक स्तर
ELAN EAFANNOTATION_DOCUMENT मूलPARTICIPANT से, अन्यथा स्तर की आईडी

TextGrid के लंबे और छोटे दोनों क्रमबद्धीकरण पढ़े जाते हैं। ELAN फ़ाइलों के लिए Potato ALIGNABLE_ANNOTATION और REF_ANNOTATION को TIME_ORDER तालिका के विरुद्ध हल करता है और शीर्षलेख से मीडिया संदर्भ पढ़ता है।

एक Praat TextGrid जो fieldworker और speaker नाम के दो वक्ताओं के रूप में दिखता है, प्रति स्तर एक, और मौन अंतराल छोड़ दिए गए हैं।TextGrid का हर स्तर एक वक्ता बन जाता है, और बीच के खाली अंतराल छोड़ दिए जाते हैं

बाकी सब कुछ

तीन सामान्य रूप 21 की गिनती पूरी करते हैं:

  • {speaker, start, end, text} शब्दकोशों की सादी सूची।
  • एक {"audio": ..., "turns": [...]} ऑब्जेक्ट।
  • बिना किसी समय के सादा अनुच्छेद, जो एक ही बुलबुले के रूप में दिखता है।

असमर्थित

इनके लिए कोई पार्सर नहीं है। पहले इन्हें बदल लीजिए।

  • SAMI (.smi), MicroDVD (.sub), SubViewer (.sbv)
  • Transcriber (.trs), EXMARaLDA, CHAT/CHILDES (.cha)
  • Montreal Forced Aligner और Gentle का मूल आउटपुट। उनसे CTM या TextGrid निर्यात कीजिए।
  • असामान्य रैपर के भीतर Azure Speech, Google Speech-to-Text और Whisper API का verbose_json
  • अकेले RTTM डायराइज़ेशन फ़ाइलें

जहाँ स्रोत उपलब्ध कराता है वहाँ शब्द-स्तरीय कॉन्फ़िडेंस पढ़ी और डेटा मॉडल में रखी जाती है, पर उसे देखने के लिए फ़िलहाल कोई इंटरफ़ेस नहीं है।

सामान्यीकृत टर्न मॉडल

ऊपर के सभी प्रारूप इसमें बदल जाते हैं:

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 और confidence तभी दिखते हैं जब स्रोत में मौजूद हों। बिना डायराइज़ेशन वाले टर्न में speaker null होता है, और वे Unassigned के रूप में एक चयनकर्ता के साथ दिखते हैं ताकि एनोटेटर उन्हें भर सकें।

तीन ट्रांसक्रिप्ट टर्न जिनकी पृष्ठभूमि धूसर धारीदार है, हर एक पर ड्रॉपडाउन तीर के साथ Unassigned लिखा है, क्योंकि स्रोत प्रारूप में वक्ता लेबल नहीं थे।YouTube के स्वतः कैप्शन बिना वक्ताओं के आते हैं, इसलिए हर टर्न तब तक Unassigned रहता है जब तक कोई एनोटेटर चुन न ले

turn_id प्रति-टर्न एनोटेशन और वक्ता असाइनमेंट के लिए स्थायित्व कुंजी है। यह स्रोत में मौजूद स्पष्ट turn_id या step_id स्ट्रिंग से आती है, वरना t{सूचकांक} से। एक ही फ़ाइल हमेशा एक ही आईडी बनाती है, इसलिए एनोटेशन पुनः लोड करने पर भी बचे रहते हैं।

Warning: अलग-अलग टूल में समय की इकाइयाँ अलग होती हैं। Whisper और Deepgram दशमलव सेकंड इस्तेमाल करते हैं; AssemblyAI, whisper.cpp के ऑफ़सेट और Whisper का TSV आउटपुट पूर्णांक मिलीसेकंड इस्तेमाल करते हैं। Potato सीमा पर रूपांतरण कर देता है ताकि आगे सब कुछ सेकंड में रहे। अगर आपकी अपनी प्री-प्रोसेसिंग इन दोनों को मिला दे, तो समय 1000 गुना ग़लत निकलते हैं।

साइडकार फ़ाइलें

ऐसा फ़ील्ड मान जो एक ही पंक्ति का छोटा पथ हो और किसी ज्ञात ट्रांसक्रिप्ट एक्सटेंशन पर ख़त्म होता हो, उसे पाठ मानने के बजाय डिस्क से पढ़ा जाता है। इसलिए आपके ASR टूल ने जो व्यवस्था पहले ही बनाई है, जिसमें मीडिया फ़ाइलें अपनी .srt या .json के बगल में हैं, वह बिना किसी प्री-प्रोसेसिंग चरण के काम करती है:

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

पथ task_dir के सापेक्ष हल होते हैं और हर दूसरे कॉन्फ़िगर किए पथ जैसी ही पथ-सुरक्षा जाँच से गुज़रते हैं, इसलिए कोई डेटा फ़ाइल परियोजना के बाहर नहीं पढ़ सकती।

पहचाने जाने वाले एक्सटेंशन: .srt .vtt .webvtt .json .json3 .srv1 .srv2 .srv3 .ttml .dfxp .xml .ass .ssa .tsv .ctm .TextGrid .eaf .txt

अगर आपके डेटा में वाकई एक पंक्ति के ट्रांसक्रिप्ट हैं जो फ़ाइल नाम जैसे दिखते हैं, तो यह अनुमान बंद कर दीजिए:

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

कॉन्फ़िगरेशन

प्रदर्शन: audio_dialogue

ऑडियो संवाद प्रदर्शन टर्न को ऑडियो के साथ समकालिक वक्ता बुलबुलों के रूप में दिखाता है, हर टर्न पर एक प्ले बटन के साथ।

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
विकल्पडिफ़ॉल्टक्या करता है
audio_keyaudioफ़ील्ड मान की वह उपकुंजी जिसमें ऑडियो का URL या पथ है।
turns_keyturnsवह उपकुंजी जिसमें टर्न सूची है। segments भी स्वीकार्य है।
speaker_key / text_keyspeaker / textप्रति-टर्न कुंजियाँ।
speakers[]{id, name, color, side} की सूची। सूची में न होने वाले वक्ताओं को नियत रंग और बारी-बारी से पक्ष मिलता है।
allow_speaker_assignmentautoजब बिना डायराइज़ेशन वाले टर्न हों या सुधारने के लिए सूची हो तो auto क्लिक-से-असाइन चालू कर देता है। true इसे बाध्य करता है, false बंद।
transcript_is_pathautoफ़ील्ड मान को साइडकार पथ की तरह पढ़ना है या नहीं।
show_timestampstrueहर टर्न पर mm:ss–mm:ss दिखाता है।
scroll_height480pxस्क्रॉल होने वाले ट्रांसक्रिप्ट पटल की ऊँचाई।
playback_rates[1, 1.25, 1.5, 2]गति चयनकर्ता के विकल्प।

स्कीमा

2.7.1 से speech_transcript, voice_interaction और tiered_annotation सभी ट्रांसक्रिप्ट को सीधे इंस्टेंस रिकॉर्ड से पढ़ते हैं और इस पृष्ठ के हर प्रारूप को स्वीकार करते हैं। इससे पहले केवल 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

स्तरीय एनोटेशन ट्रांसक्रिप्ट से किसी स्तर को पहले से भर सकता है, ताकि एनोटेटर हाथ से भाषण को दोबारा विभाजित करने के बजाय मौजूदा संरेखण को सुधारें:

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"

पहले से भरे गए एनोटेशन तब तक नहीं लिखे जाते जब तक एनोटेटर सचमुच कोई बदलाव न करे, इसलिए जिसने केवल इंस्टेंस खोला उसके नाम कुछ दर्ज नहीं होता।

potato transcripts से डेटा फ़ाइल बनाना

कन्वर्टर को ASR आउटपुट के फ़ोल्डर पर लगाइए और वह एनोटेशन के लिए तैयार डेटा फ़ाइल लिख देगा:

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 कुछ लिखे बिना बताता है कि उसे क्या मिला, और ग़लत Whisper आउटपुट फ़ाइल वाले फ़ोल्डर को पकड़ने का यही सबसे तेज़ तरीक़ा है:

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.
विकल्पउद्देश्य
-o, --outputकहाँ लिखना है। --dry-run के अलावा अनिवार्य।
--formatjson (डिफ़ॉल्ट) या jsonl
--media-dirवह मीडिया फ़ोल्डर जिसे मूल नाम से मिलाना है।
--media-url-prefixस्थानीय फ़ाइलों के बजाय मीडिया का आधार URL।
--fieldआइटम का वह फ़ील्ड जिसमें ट्रांसक्रिप्ट जाएगा। डिफ़ॉल्ट conversation
--id-prefixहर बनी हुई आईडी से पहले जोड़ी जाने वाली स्ट्रिंग।
--speaker-keyस्रोत की वह कुंजी जिसमें वक्ता लेबल है।
-r, --recursiveउपफ़ोल्डरों में भी जाता है।
--dry-runप्रति फ़ाइल पहचाना गया प्रारूप और टर्न संख्या बताता है।
--emit-configसाथ में मिलती-जुलती config.yaml का अंश भी छापता है।
-q, --quietप्रति-फ़ाइल रिपोर्ट दबा देता है।

आइटम आईडी फ़ाइल नाम से आती हैं और अंत में लगा मीडिया एक्सटेंशन हटा दिया जाता है, इसलिए Whisper की interview_01.mp3.json से interview_01 बनता है, interview_01.mp3 नहीं।

वापस निर्यात करना

स्तरीय एनोटेशन ELAN EAF और Praat TextGrid में निर्यात होते हैं, इसलिए एक ट्रांसक्रिप्ट पूरा चक्कर लगा सकता है: उसे पढ़िए, Potato में एनोटेट कीजिए, निर्यात कीजिए, ELAN या Praat में सुधारिए और परिणाम वापस पढ़ लीजिए।

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

दोनों निर्यातक tiered_annotation के आउटपुट से काम करते हैं। बाकी स्कीमा मानक प्रारूपों के ज़रिए निर्यात होते हैं।

समस्या निवारण

लक्षणक्या हुआ
सब कुछ एक ही बड़े बुलबुले जैसा दिखता हैप्रारूप पहचाना नहीं गया और सादे अनुच्छेद वाले विकल्प पर चला गया। potato transcripts <file> --dry-run चलाइए; अगर वह plain text बताता है तो समय कभी पढ़े ही नहीं गए। आम तौर पर फ़ाइल .json या .srt के बजाय Whisper की .txt होती है, जिसमें कोई समय नहीं होता।
कोई वक्ता नहीं, सब Unassignedस्रोत में वक्ता लेबल नहीं हैं। अकेला Whisper डायराइज़ नहीं करता, और YouTube के स्वतः कैप्शन भी नहीं। पहले डायराइज़ेशन चलाइए या एनोटेटर्स को इंटरफ़ेस में वक्ता चुनने दीजिए।
समय 1000 गुना ग़लत हैंपहले कहीं सेकंड और मिलीसेकंड मिल गए। whisper.cpp के offsets, AssemblyAI और Whisper का TSV सभी मिलीसेकंड में हैं।
ट्रांसक्रिप्ट का पथ ही पाठ की तरह दिखता हैसाइडकार फ़ाइल पढ़ी नहीं जा सकी, इसलिए पथ को सामग्री की तरह दिखाया गया। जाँचिए कि वह task_dir के भीतर हल होता है। सर्वर लॉग में सटीक कारण दर्ज होता है।
एक पंक्ति का ट्रांसक्रिप्ट फ़ाइल नाम की तरह पढ़ा जा रहा हैप्रदर्शन फ़ील्ड पर transcript_is_path: false लगाइए।

उदाहरण परियोजना

Potato रिपॉज़िटरी में examples/audio/transcript-formats/ छह प्रारूपों को साथ-साथ दिखाता है, हर एक साइडकार फ़ाइल से लोड होकर: SubRip, WebVTT, Whisper JSON, YouTube json3, Praat TextGrid और Deepgram। छहों एक जैसे वक्ता बुलबुले बनाते हैं।

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

यही कार्य डाउनलोड करने योग्य शोकेस डिज़ाइन के रूप में भी उपलब्ध है: Transcript Format Ingestion

कार्यान्वयन के विवरण के लिए स्रोत दस्तावेज़ देखिए।

आगे पढ़ें