Skip to content

صيغ النصوص التفريغية

كل صيغ النصوص التفريغية والترجمات التي يقرأها Potato: Whisper وWhisperX وDeepgram وAssemblyAI وAWS Transcribe وSRT وWebVTT وTTML وترجمات YouTube وCTM وPraat TextGrid وELAN EAF، إضافة إلى الملفات المرافقة ونموذج الأدوار الموحّد.

يقرأ Potato 21 نوعًا من مدخلات النصوص التفريغية والترجمات، ويحوّلها جميعًا إلى نموذج الأدوار نفسه قبل عرض أي شيء. مهما كان ما أنتجه مسار التعرّف على الكلام لديك أو أداة الترجمة، يمكنك توجيه Potato إليه دون كتابة برنامج تحويل. هذه الصفحة مرجع لما يعمل، ولكيفية استنتاج كل صيغة، ولما تقدّمه كل واحدة منها. وللشرح خطوة بخطوة انظر كيفية شرح نصوص Whisper التفريغية وكيفية شرح ترجمات YouTube.

نص تفريغي معروض كفقاعات متحدثين ملوّنة، لكل منها زر تشغيل وطوابع زمنية وسؤال تسمية على مستوى الدور.ملف SRT مرافق معروض كفقاعات متحدثين، مع سؤال مرفق بكل دور

Potato لا يقوم بالتفريغ

يجري التعرّف على الكلام وفصل المتحدثين قبل أن يرى Potato أي شيء. شغّل أولًا Whisper أو WhisperX أو pyannote أو واجهة برمجية سحابية؛ وPotato يستقبل النتيجة. لا شيء في هذه الصفحة يشغّل أي نموذج.

Note: يشغّل وضع Think-Aloud بالفعل نموذج Whisper محليًا، لكن لغرض مختلف: فهو يسجّل المشاركين في الشرح وهم يفكّرون بصوت عالٍ أثناء العمل. تلك ميزة تسجيل، لا استقبالًا لنصوص تفريغية.

الاستنتاج يتم من المحتوى لا من الامتداد

ينظر Potato فيما بداخل الملف بدل الاعتماد على اسمه. فملف WebVTT اسمه captions.txt يظل يُحلَّل كـ WebVTT. والنتيجة العملية أن النص التفريغي نفسه يعمل سواء كان مضمّنًا في ملف بياناتك أو مقروءًا من ملف مرافق على القرص، دون تغيير في الإعدادات.

الصيغ المدعومة

مخرجات التعرّف على الكلام

الصيغةيُستنتج منالمتحدثونتوقيتات الكلمات
Whisper JSONمصفوفة segmentsلانعم، مع --word_timestamps
WhisperX / JSON مفصول المتحدثينsegments تحتوي speakerنعمنعم
whisper.cpp JSONمصفوفة transcriptionلالا
Whisper TSVترويسة start/end/textلالا
AWS Transcriberesults.items أو results.audio_segmentsنعمنعم
Deepgramresults.channels أو results.utterancesنعم، مع diarize=trueنعم
AssemblyAItext مع words/utterancesنعم، مع speaker_labelsنعم
Rev.aiمصفوفة monologuesنعمنعم
SPoRCصفوف turn_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/srv3XML على شكل <transcript><text>من بادئة Name:
YouTube json3مصفوفة eventsلا شيء؛ الترجمات التلقائية بلا متحدثين

يغطي SubRip وWebVTT معظم ما ستصادفه. ويظهر TTML في أرشيفات البث وفي الملفات المصدَّرة من أدوات الترجمة الاحترافية.

المحاذاة والشرح اللغوي

الصيغةيُستنتج منالمتحدثون
NIST CTMأعمدة مفصولة بمسافات، بداية ومدة رقميتانمن حقل القناة
Praat TextGridFile type = "ooTextFile"طبقة لكل متحدث
ELAN EAFالجذر ANNOTATION_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 وverbose_json من واجهة Whisper داخل أغلفة غير معتادة
  • ملفات فصل المتحدثين 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 عند الحدّ كي يكون كل ما بعده بالثواني. وإن خلطت معالجتك السابقة بينهما، خرجت التوقيتات خاطئة بمقدار ألف ضعف.

الملفات المرافقة

قيمة الحقل التي تكون مسارًا قصيرًا في سطر واحد وينتهي بامتداد نص تفريغي معروف تُقرأ من القرص بدل أن تُعامَل كنص. وبذلك يعمل التنظيم الذي أنتجته أداة التعرّف على الكلام أصلًا، بوجود ملفات الوسائط إلى جانب ملف .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المفتاح الفرعي داخل قيمة الحقل الذي يحمل رابط الصوت أو مساره.
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

وجّه أداة التحويل إلى مجلد فيه مخرجات تعرّف على الكلام، فتكتب ملف بيانات جاهزًا للشرح:

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رابط أساسي للوسائط بدل الملفات المحلية.
--fieldحقل العنصر الذي يوضع فيه النص التفريغي. الافتراضي conversation.
--id-prefixنص يُضاف قبل كل معرّف مُولَّد.
--speaker-keyمفتاح المصدر الذي يحمل تسمية المتحدث.
-r، --recursiveيشمل المجلدات الفرعية.
--dry-runيُبلغ عن الصيغة المستنتَجة وعدد الأدوار لكل ملف.
--emit-configيطبع أيضًا مقتطف config.yaml مطابقًا.
-q، --quietيكتم التقرير الخاص بكل ملف.

تُشتق معرّفات العناصر من اسم الملف بعد إزالة امتداد وسائط في نهايته، فيصبح ملف interview_01.mp3.json من Whisper هو 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 فالتوقيتات لم تُقرأ أصلًا. وغالبًا يكون الملف .txt من Whisper، وهو بلا أي توقيتات، بدل .json أو .srt.
لا متحدثين، والكل Unassignedالمصدر لا يحمل تسميات متحدثين. Whisper وحده لا يفصل المتحدثين، وكذلك ترجمات YouTube التلقائية. شغّل فصل المتحدثين قبل ذلك أو دع المشاركين يُسنِدون المتحدثين في الواجهة.
التوقيتات خاطئة بمقدار ألف ضعفخُلطت الثواني والميلي ثواني في مرحلة سابقة. فإزاحات whisper.cpp وAssemblyAI وملف TSV من Whisper كلها بالميلي ثانية.
مسار النص التفريغي يظهر بوصفه النص نفسهتعذّرت قراءة الملف المرافق، فعُرض المسار كمحتوى. تحقق من أنه يُحلّ داخل task_dir. وتسجّل سجلات الخادم السبب المحدّد.
نص تفريغي من سطر واحد يُقرأ كاسم ملفاضبط transcript_is_path: false على حقل العرض.

مشروع مثال

يعرض examples/audio/transcript-formats/ في مستودع Potato ست صيغ جنبًا إلى جنب، كل منها محمّلة من ملف مرافق: 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.

لتفاصيل التنفيذ، انظر الوثائق المصدرية.

قراءات إضافية