ألصق البثّ لا الصفحة. العنوان الحقيقي لصوت المحطة ينتهي بـ .mp3 أو .aac أو .m3u8، وبمجرد أن يأخذ التفريغ النصي المباشر ذلك الصوت، لا يحتاج أحد إلى الاستماع.
غرفة أخبار تتابع ثلاث محطات إذاعية وقناتين تلفزيونيتين وعددًا من بثوث YouTube المباشرة تواجه مشكلة في التوظيف قبل أن تواجه مشكلة في التفريغ النصي. يجب أن يستمع أحدهم، ويجب أن يضغط أحدهم زر التسجيل. يتولى التفريغ النصي المباشر بمصدر بثّ المهمتين معًا: أعطه عنوان البث، فيفتحه الخادم ويفكّ ترميزه ويفرّغه أثناء بثّه، فلا يحتاج أحد إلى الجلوس أمام مكتبه حين يبدأ مؤتمر صحفي مبكرًا. أما الجزء الصعب، كما يتبيّن، فهو العثور على العنوان.
يمكن للتفريغ النصي المباشر أن يأخذ صوته من بثّ يسحبه الخادم بنفسه: محطة راديو عبر الإنترنت، أو قائمة تشغيل HLS (.m3u8)، أو بيان DASH (.mpd)، أو بثّ YouTube مباشر. في لوحة التحكم، يكون ذلك عبر تفريغ نصي مباشر جديد من Transcriptions → New → Live يكون مصدره بثًّا لا الميكروفون. يُحدَّد العنوان عند إنشاء التفريغ ولا يتغير أبدًا، لذا يُعدّ المراقِب مرة واحدة، ويُشغَّل كلما استحقت المحطة التسجيل.
يجب أن يكون العنوان هو البث نفسه، لا صفحة الويب التي تشغّله. صفحة المحطة نص HTML، والصوت الذي تشغّله يأتي من مكان آخر، عادةً من خادم Icecast أو Shoutcast، ويجد مشغّل الصفحة ذلك العنوان بجافاسكربت بعد تحميلها. ابحث في الموقع عن رابط بعنوان «Listen» أو «Direct stream» أو «Other players»: ينتهي بـ .mp3 أو .aac أو .m3u أو .m3u8 أو .pls. وملفات .pls و.m3u ليست صوتًا أيضًا، بل ملف نصي قصير من بضعة أسطر، يحمل كل سطر منه عنوان بثّ، وهو موجود كي تستطيع مشغلات سطح المكتب أن تُعطى رابطًا واحدًا، ويُفرّغ VocalStack البثّ الذي تسمّيه. وإن ألصقتَ الصفحة بدلًا من ذلك، يطلب VocalStack الصفحة، ويرى أن ما يعود هو HTML، ويخبرك بذلك. تُخفي كل محطة بثّها بطريقة مختلفة قليلًا، وأغلبها يخفيه خلف زر مكتوب عليه «Listen»، وهذا هو الشيء الوحيد في الصفحة الذي لا يستحق النقر عليه.
يُرفض نوعان من الروابط دون تردد. الروابط إلى صفحات تشغّل الوسائط، مثل Spotify وSoundCloud وTwitch، تُردّ قبل أن يتصل شيء بها. كذلك لا تُدعم البثوث المحمية بحقوق النسخ: فقائمة التشغيل أو البيان الذي يحتاج إلى ترخيص DRM يفشل برسالة تقول ذلك. وبعض البثوث ترفض الطلبات من خارج بلد المحطة، فالعنوان الذي يعمل في المكتب قد لا يعمل من خادم في الخارج. وإذا كان البثّ يعمل في المتصفح ولا يعمل في VocalStack، فالمحطة تردّ المشغّلات الأخرى؛ اطلب منها عنوانًا تُسمح به التطبيقات الأخرى. أغلب المحطات تقدّم بثًّا بصيغة MP3 أو AAC أو HLS. وبعد أن تحصل على العنوان الصحيح، يبقى السؤال التالي: هل ينتهي البثّ أصلًا؟
البثّ المباشر لا ينتهي أبدًا، لذلك فهو ليس ملفًا. والفرق مهم خصوصًا مع YouTube. بثّ YouTube المباشر الذي يُبَث الآن ينتمي إلى تفريغ نصي مباشر، وتتبعه لوحة التحكم أثناء بثّه. أما بثّ مجدول لم يبدأ بعد فيظهر بعبارة Not live yet، ويمكن تسجيله بعد أن يبدأ بثّه. والفيديو المنتهي شيء مختلف: له مدة، لذا يُفرّغ كملف، فالصق الرابط في Transcriptions → New.
قائمة التشغيل نفسها تقول أيّ الحالتين هي، وبهذا تميّز أي مشغّل بينهما. قائمة HLS المنتهية تحمل الوسم #EXT-X-ENDLIST أو #EXT-X-PLAYLIST-TYPE:VOD؛ أما المباشرة فلا تحمل أيًّا منهما، وتستمر في النمو، لذلك يعيد المشغّل جلبها كل بضع ثوانٍ بحثًا عن مقاطع جديدة. ويعلن بيان DASH أنه type="dynamic" ما دام البثّ على الهواء، ثم type="static" حين يصبح تسجيلًا. أما بثّ MP3 أو AAC من خادم Icecast فليس له طول على الإطلاق؛ إنه ببساطة لا يتوقف أبدًا.
من الشيفرة، يحسم GET /v1/transcriptions/probe?url= هذا قبل تخزين أي شيء. تكون قيمة kind في الرد live لبثّ YouTube المباشر الذي يُبَث أو مجدول، أو لبثّ HTTP لا ينتهي، أو لقائمة HLS بلا نهاية، أو لبيان DASH ديناميكي. وتكون file لأي شيء له نهاية، وunknown حين لا يستطيع الفحص أن يحسم. وحين لا يُفتح الرابط كوسائط، تكون قيمة ok هي false، ويكون problem جملةً يمكن عرضها. ولا يحتفظ الفحص بشيء، ويُحدّ بـ60 استدعاءً في الدقيقة.
تعمل التفريغات النصية للملفات أسرع من تشغيل الصوت بمرات كثيرة، فساعة منتهية من التلفزيون لا تستغرق ساعة. أما البثّ المباشر فيُفرَّغ في الوقت الفعلي، لكن «الوقت الفعلي» يتأخر عن البثّ بمقدار، ومن المفيد أن تعرف كم. يصل بثّ Icecast إلى المشغّل بعد ثوانٍ قليلة من الميكروفون. أما HLS وDASH فمُقطّعان، ولا يبدأ المشغّل حتى يمتلك مقطعين أو ثلاثة، طول كل منها نحو ست ثوانٍ، لذلك يتأخر بثّ HLS عادةً بين 10 و30 ثانية عن البثّ الأصلي، قبل أن يضيف التفريغ تأخيره الخاص. والسطر الذي يبدو وصوله متأخرًا يكون عادةً تأخير المحطة، لا تأخير المُفرِّغ. كل بثّ يُنتج تسجيلًا واحدًا، والمكتب يشغّل عدة بثوث، وكلها تنتهي إلى المكان نفسه.
يصل كل تفريغ نصي مباشر إلى مكتبة التفريغات النصية، جنبًا إلى جنب مع كل ملف. يُحفظ كل تسجيل مع نصه المُفرَّغ، وحين تصبح الكلمات نهائية يُكتب له عنوان وملخص بكل اللغات. تُكتشف لغة الكلام تلقائيًا، ويجوز للمتحدثين تبديل اللغة في أي وقت. وحين تعرف اللغة، فإن تسميتها تحسّن جودة التفريغ.
المكتبة قابلة للبحث عبر اللغات: ابحث في كل نص مُفرَّغ، أيًّا كانت لغته، واحصل على النتائج بلغتك. يستطيع مراسل لا يقرأ إلا الإنجليزية أن يبحث في البرنامج الصباحي لمحطة رومانية عن اسم وزير، ويقرأ النتائج بالإنجليزية، ولكل نتيجة التفريغ الذي جاءت منه والوقت الذي قيل فيه. وسيُكتب اسم الوزير بثلاث طرق في ثلاث محطات؛ والبحث عنه بالإنجليزية يوفّر قراءة الطرق الثلاث.
يمكن ترجمة التفريغ الواحد إلى ما يصل إلى 10 لغات في وقت واحد، فيُقرأ التسجيل نفسه بكل لغة يعمل بها المكتب. ونتيجة البحث لا تفيد إلا إذا أمكن اقتباسها.
التفريغ ليس كتلةً نصيةً متصلة. تعيد GET /v1/recordings/{id}/transcript في الواجهة البرمجية sentences وsegments مع توقيتات الكلمات وspeakers، فيمكن وضع الاقتباس بدقة الثانية داخل التسجيل. وتعيد لوحة التحكم تشغيل التسجيل المباشر كما وصل تمامًا، مع صوته، فيمكن الاستماع إلى الجملة قبل اقتباسها.
قبل أن تثق بأي تفريغ لصوت إذاعي، من أي نظام كان، هناك أمران يستحقان المعرفة. يتعثر التعرّف على الكلام أكثر ما يكون في أسماء الأعلام والأماكن والأرقام، وهي بالضبط ما يبحث عنه المراسل. والاسم الذي لم يسمعه المُعرِّف من قبل يخرج على هيئة أقرب كلمة شائعة، ولن يجد البحث عن الكتابة الصحيحة له أثرًا. لذلك ابحث عن كلمة مميزة قيلت في النَّفَس نفسه، ثم اقرأ ما حولها. والإذاعة ليست كلها كلامًا: فالخلفيات الموسيقية والمقدمات الصوتية وفواصل الإعلانات تُنتج أسطرًا تبدو جملًا وليست كذلك. تحقّق من الصوت قبل أن تقتبس.
لتسميات المتحدثين ثلاثة إعدادات: إيقاف، أو تشغيل، أو When Needed، الذي يُظهر التسميات بعد أن يُسمع متحدث ثانٍ. ويمكنك تسمية متحدث في تسجيل (PUT /v1/recordings/{id}/speakers/{idx})، وبمجرد تسجيل صوت المتحدث، تتعرف التسجيلات اللاحقة عليه بالاسم. وبالنسبة لمحطة يعود مقدموها كل صباح، تتوقف التسميات عن كونها «Speaker 2» بعد الأسبوع الأول. وحين يُدقَّق الاقتباس، يجب أن يخرج من المبنى.
لكل صيغة في تبويب Export لتفريغ نصي دور في غرفة الأخبار. يذهب SRT إلى محرر الفيديو، فيحمل المقطع المأخوذ من البث ترجمات مكتوبة؛ وSRT المترجم يحملها بلغة أخرى. ويذهب Excel إلى الباحث، صفًّا لكل جملة مع وقتها، ليُصفّى ويُعلَّق عليه. ويذهب PDF إلى المحرر الذي يريد قراءة الساعة كاملة في القطار. ويذهب JSON إلى من يكتب أدوات المكتب الخاصة. عبر الواجهة البرمجية، يكون التصدير GET /v1/recordings/{id}/export?format=srt|json|xlsx|pdf، مع lang= للنسخة المترجمة. أما Download audio فيعطيك التسجيل بصيغة MP3 للحزمة الصحفية نفسها.
مراقبة بثّ لأغراض التغطية ممارسة عادية في غرف الأخبار. أما إعادة نشر مقطع منه فعمل مختلف. وهو يخضع للاستخدام العادل أو الاستعمال المقبول حيث أنت، ولشروط المحطة نفسها، فتنطبق على صوت المنافس قواعد المكتب المعتادة في الاقتباس من المنافسين. كل ما سبق بضع نقرات في لوحة التحكم؛ أما مكتب يتابع عشرين محطة فالأفضل أن يُؤتمت.
المسار كله موجود في الواجهة البرمجية، وهو مشمول في كل خطة ويُحاسَب بالسعر نفسه المعتمد في لوحة التحكم. يُنشأ التفريغ النصي المباشر ذو المصدر البثّي في حالة خمول، ويبدأ بأول تسجيل له، ويُتحكم فيه عبر HTTP. ولأن الخادم هو من يسحب الصوت، فبدء التسجيل لا يُرجع بثًّا تنشر إليه شيئًا: لا شيء من جهتك يرسل الصوت.
API=$VOCALSTACK_API_ORIGIN # the origin shown in the API reference
AUTH="Authorization: Bearer $VOCALSTACK_API_KEY"
# A live transcription whose source the server pulls itself.
TX=$(jq -n '{name: "Morning show", source: {kind: "stream", url: "https://example.org/live.mp3"},
settings: {speakerLabels: "auto"}}' \
| curl -sSf "$API/v1/transcriptions/live" -H "$AUTH" -H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" -d @- | jq -r .id)
# Start recording: the server opens the stream now.
REC=$(curl -sSf -X POST "$API/v1/transcriptions/$TX/recordings" -H "$AUTH" \
-H "Content-Type: application/json" -d '{}' | jq -r .recording.id)
# Later: pause, then stop (a live recording must be paused before it is stopped).
curl -sSf -X POST "$API/v1/recordings/$REC/pause" -H "$AUTH"
curl -sSf -X POST "$API/v1/recordings/$REC/stop" -H "$AUTH" -H "Content-Type: application/json" -d '{}'
# Search everything that was said, in English.
curl -sSfG "$API/v1/search" -H "$AUTH" --data-urlencode "q=budget" --data-urlencode "lang=en"
يجعل Idempotency-Key إعادة الإنشاء عند تكرار الطلب تُرجع التفريغ الأول بدلًا من إنشاء تفريغ ثانٍ. وتغلّف حزم SDK لـ TypeScript وPython الاستدعاءات نفسها، وتُنزَّل من منطقة المطورين؛ وفيه مرجع API كل مسار وإطاراته.
يستطيع وكيل ذكاء اصطناعي أن يعمل بالمكتبة دون أي شيفرة. يوفّر خادم MCP على /v1/mcp للوكيل مجموعةً من الأدوات، منها أربع تهمّنا هنا. يبحث search_transcriptions فيما قيل عبر تفريغات الحساب بأي لغة، ويُرجع الأسطر المطابقة، ولكل سطر التفريغ الذي هو فيه والوقت الذي قيل فيه. ويُرجع get_summary ملخص تسجيل. ويُفرّغ transcribe_url وwait_for_transcription فيديو منتهيًا أو رابط تسجيل، وينتظران النتيجة. أما إنشاء مراقب لبثّ مباشر فيبقى في لوحة التحكم أو في الواجهة البرمجية أعلاه. وإعداد Claude Code أو Cursor أو أي عميل Streamable HTTP موجود تحت Developers → Connect an AI agent، وتشرح مقالة MCP الخطوات. وتبقى تكلفة تشغيل النص السؤالَ الأخير.
التفريغ النصي المباشر بسعر $0.60 لكل ساعة من الصوت، يُحاسَب بالثانية ($0.01 في الدقيقة)، مع حدٍّ أدنى 5 دقائق لكل تفريغ. والبثّ المباشر أغلى من الملف لأنه يُفرَّغ أثناء وقوعه، طوال المدة التي يستمر فيها. أما الملفات فسعرها $0.20 لكل ساعة ($0.0033 في الدقيقة؛ ملف مدته 30 دقيقة يكلّف $0.10). والأسعار واحدة في كل خطة وعبر الواجهة البرمجية، والترجمات والملخصات وتسمية المتحدثين والبثّ والمشاركة لا تضيف شيئًا إلى الفاتورة.
مراقبة محطة ثماني ساعات يوميًا، خمسة أيام في الأسبوع، تعني 40 ساعة مباشرة: $24 في الأسبوع، بأي لغات يقرأ بها المكتب التفريغ.
الحدود التي تهم المراقبة تختلف باختلاف الخطة. وكل حد مذكور بالترتيب: الدفع حسب الاستخدام، ثم Premium، ثم Enterprise:
يحصل الحساب الجديد على رصيد تسجيل بقيمة $5 دون بطاقة، وهو أكثر من ثماني ساعات من المراقبة المباشرة لتجربته. الجدول الكامل موجود في صفحة الأسعار.