Skip to content

كيفية شرح نصوص Whisper التفريغية

كيف تحوّل مخرجات Whisper أو WhisperX إلى مشروع شرح جاهز للعمل: أي ملف تحتفظ به، ومتى تحتاج إلى فصل المتحدثين، وكيف تُسنِد المتحدثين، وكيف تُصدّر مع الحفاظ على المحاذاة الزمنية.

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

Whisper هو نموذج التعرّف على الكلام مفتوح المصدر من OpenAI، وقد صار الخطوة الأولى الافتراضية لكل من لديه كمية كبيرة من التسجيلات الصوتية. ما ينتجه هو مجموعة مقاطع موقّتة، وهذا معظم ما يحتاجه مشروع الشرح. الناقص هو كل ما يقع بين «لديّ نصوص تفريغية» و«المشاركون في الشرح يضعون التسميات».

Note: Potato لا يقوم بالتفريغ. التعرّف على الكلام يجري قبله، وPotato يستقبل مخرجاته. يشرح هذا الدليل أي اختيارات سابقة لها أثر، لكن التفريغ نفسه يحدث قبل أن يرى Potato أي شيء.

أي ملف من مخرجات Whisper ينبغي أن أحتفظ به؟

يكتب Whisper عدة ملفات، والاختيار بينها أهم مما يبدو:

bash
whisper interview_01.mp3 --model medium --output_format json --word_timestamps True
الملفالمحتوىهل يصلح؟
.jsonمقاطع بأوقات بداية ونهاية، واختياريًا توقيتات لكل كلمةنعم، هذا هو
.srt / .vttمقاطع موقّتة، بلا بيانات وصفيةنعم، يعمل جيدًا
.tsvالبداية والنهاية بالميلي ثانية مع النصنعم
.txtنص فقط، بلا أي توقيتاتلا، لا يوجد ما يُزامَن مع الصوت

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

هل يضع Whisper تسميات للمتحدثين؟

لا، وهذا ما يفاجئ الناس باستمرار. يقوم Whisper بالتفريغ فقط؛ ولا يخبرك من المتحدث. تصل كل الأدوار غير مُسنَدة، وهذا مقبول لشرح المحتوى ومزعج لأي عمل يتعلق بالمتحدثين.

فصل المتحدثين خطوة منفصلة. وهناك ثلاث طرق للتعامل معها:

شغّل WhisperX، وهو يغلّف Whisper بفصل المتحدثين من pyannote:

bash
whisperx interview_01.mp3 --model medium --diarize --output_format json

تحمل مخرجاته حقل speaker لكل مقطع (SPEAKER_00 وSPEAKER_01 وهكذا)، وPotato يقرأه مباشرة.

استخدم واجهة برمجية سحابية مع تفعيل فصل المتحدثين. Deepgram مع diarize=true، وAssemblyAI مع speaker_labels، وAWS Transcribe، وRev.ai، جميعها تنتج تسميات للمتحدثين، وPotato يقرأ الأربعة بشكل أصيل.

ثلاثة أدوار من نص تفريغي بخلفية رمادية مخطّطة، كل منها موسوم بـ Unassigned مع سهم قائمة منسدلة.تظهر الأدوار غير المفصولة على أنها Unassigned مع أداة اختيار المتحدث

اترك الأمر للمشاركين في الشرح. عندما تصل الأدوار دون فصل، تظهر كل فقاعة على أنها Unassigned مع أداة اختيار. مع الصوت الرديء أو الكلام المتداخل أو ضجيج الخلفية، يكون حكم إنسان يستمع أدقّ من الفصل الآلي في كثير من الأحيان. وبالنسبة لمدوّنة صغيرة، هذه مقايضة معقولة لا حلٌّ اضطراري.

كيف أبني ملف البيانات؟

وجّه أداة التحويل إلى مجلد مخرجات Whisper:

bash
potato transcripts ./whisper_out --media-dir ./audio -o data/interviews.json

تُزاوَج النصوص التفريغية مع الصوت عبر الاسم الأساسي، فيجد interview_01.json ملف interview_01.mp3. تُشتق معرّفات العناصر من اسم الملف، وتُعالَج لاحقة Whisper المزدوجة interview_01.mp3.json دون أن تنتج معرّفًا مثل interview_01.mp3.

تحقق مما فهمته الأداة قبل أن تمضي:

bash
potato transcripts ./whisper_out --dry-run
text
Scanned 3 file(s):
  interview_01.json      Whisper JSON      42 turns    891.4s  undiarized
  interview_02.json      WhisperX JSON     51 turns   1120.8s  2 speaker(s): SPEAKER_00, SPEAKER_01
  interview_03.json      Whisper JSON      38 turns    754.2s  undiarized

3 item(s), 131 turn(s).

الملف الذي يُبلَّغ عنه بـ plain text أو بصفر أدوار هو ملفك المشكل. وهو في الغالب ملف .txt تسلّل بين مخرجات .json.

هل يمكنني تخطي خطوة التحويل؟

نعم. يمكن لملف البيانات أن يشير مباشرة إلى النصوص التفريغية على القرص:

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

يقرأ Potato الملف، ويستنتج الصيغة من محتواه، ويوحّدها عند عرض العنصر. تبقى نصوصك التفريغية ملفات يمكنك مقارنتها وإعادة تصديرها، بدل أن تُدفن داخل كتلة بيانات.

كيف تبدو الإعدادات؟

ملف البيانات المُولَّد بهذا الشكل:

json
{
  "id": "interview_01",
  "conversation": {
    "audio": "audio/interview_01.mp3",
    "turns": [
      {"turn_id": "t0", "speaker": "SPEAKER_00", "start": 0.0, "end": 6.5,
       "text": "Welcome back."}
    ]
  }
}

والإعدادات المقابلة، والتي يطبعها لك potato transcripts --emit-config:

yaml
annotation_task_name: "Interview Annotation"
task_dir: .
data_files:
  - data/interviews.json
 
item_properties:
  id_key: id
  text_key: conversation
 
instance_display:
  fields:
    - key: conversation
      type: audio_dialogue
      label: "Transcript"
      span_target: true
      display_options:
        show_timestamps: true
        allow_speaker_assignment: auto
 
annotation_schemes:
  - annotation_type: span
    name: topics
    description: "Highlight topic mentions"
    target_field: conversation
    labels:
      - name: policy
      - name: personal

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

يعرض audio_dialogue الأدوار كفقاعات متحدثين متزامنة مع الصوت، مع زر تشغيل على كل دور يشغّل ذلك الدور وحده. ويسمح span_target: true للمقاطع المحددة بتجاوز حدود الأدوار، مع بقاء الإزاحات مستقرة عند إعادة إسناد متحدث.

إن كنت تفضّل أن يراجع المشاركون النص التفريغي نفسه بدل تسمية محتواه، فإن speech_transcript يوفّر بطاقات مقاطع مع وسوم أخطاء وصندوق تصحيح. وللعمل على التداخل والمقاطعة، يوفّر voice_interaction خطًا زمنيًا بمسارين. وكلاهما يقرأ الملفات نفسها.

كيف يُسنِد المشاركون المتحدثين؟

عرّف قائمة كي تحصل الأسماء والألوان والجهات على ثبات:

yaml
display_options:
  allow_speaker_assignment: auto
  speakers:
    - id: interviewer
      name: "Interviewer"
      color: "#7c3aed"
      side: left
    - id: participant
      name: "Participant"
      color: "#059669"
      side: right

يفعّل auto أداة الاختيار عند وجود أدوار غير مفصولة تحتاج إلى تسمية. اضبطه على true للسماح بإعادة الإسناد حتى عندما يكون المصدر قد سمّى المتحدثين، وهو ما تريده إن كنت تصحّح أخطاء فصل بدل ملء فراغات.

تُحفظ الإسنادات مع الشروح، مرتبطة بمعرّف دور ثابت، فتبقى بعد إعادة التحميل.

كيف أستخرج الشروح؟

التصدير إلى JSON وJSONL وCSV يعمل كالمعتاد. وحين يجب أن تبقى المحاذاة الزمنية، صدّر الشروح الطبقية إلى ELAN EAF أو Praat TextGrid:

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

كلاهما يعمل في الاتجاهين. فPotato يقرأ EAF وTextGrid كمدخلات أيضًا، فيمكنك الشرح في Potato، والتنقيح في ELAN أو Praat، ثم إعادة قراءة النتيجة.

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