הדביקו את הזרם, לא את הדף. השמע האמיתי של תחנה נמצא בכתובת שמסתיימת ב־.mp3, .aac או .m3u8, וברגע שתמלול בשידור חי מקבל אותה, אף אחד לא צריך להאזין.
חדר חדשות שמנטר שלוש תחנות רדיו, שני ערוצי טלוויזיה ומספר שידורי YouTube חיים צריך קודם כול לפתור בעיית כוח אדם, ורק אחר כך בעיית תמלול. מישהו צריך להאזין, ומישהו צריך ללחוץ על הקלטה. תמלול בשידור חי שהמקור שלו הוא זרם לוקח על עצמו את שתי המשימות: נותנים לו את הכתובת של הזרם, והשרת פותח אותו, מפענח אותו ומתמלל אותו תוך כדי השידור, כך שאף אחד לא חייב לשבת ליד המחשב כשמסיבת עיתונאים מתחילה מוקדם. הקושי האמיתי, מסתבר, הוא למצוא את הכתובת.
תמלול בשידור חי יכול לקחת את השמע שלו מזרם שהשרת שולף בעצמו: תחנת רדיו באינטרנט, רשימת השמעה מסוג HLS (.m3u8), מניפסט DASH (.mpd) או שידור YouTube חי. בלוח הבקרה זה תמלול בשידור חי חדש ב־Transcriptions → New → Live שהמקור שלו הוא זרם ולא המיקרופון. הכתובת נקבעת כשיוצרים את התמלול ולעולם לא משתנה, כך שמוניטור מוגדר פעם אחת ומופעל בכל פעם שהתחנה שווה הקלטה.
הכתובת חייבת להיות הזרם עצמו, לא הדף שמנגן אותו. דף של תחנה הוא HTML; השמע שהוא מנגן מגיע ממקום אחר, בדרך כלל משרת Icecast או Shoutcast, והנגן שבדף מוצא את הכתובת הזו עם JavaScript אחרי שהדף נטען. חפשו באתר קישור כמו "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 שפות בבת אחת, כך שאותה הקלטה נקראת בכל שפה שהחדר עובד בה. תוצאת חיפוש שימושית רק אם אפשר לצטט אותה.
תמליל אינו קיר של טקסט. ה־API, GET /v1/recordings/{id}/transcript, מחזיר sentences, segments עם תזמון מילים, ו־speakers, כך שאפשר למקם ציטוט לשנייה ביחס להקלטה. לוח הבקרה משמיע מחדש הקלטה חיה בדיוק כפי שהגיעה, עם השמע שלה, כך שאפשר לשמוע משפט לפני שמצטטים אותו.
לפני שסומכים על תמליל של שמע רדיו, מכל מערכת שהיא, שווה לדעת שני דברים. זיהוי דיבור נכשל יותר מכול בשמות פרטיים, במקומות ובנתונים מספריים, וזה בדיוק מה שכתבים מחפשים. שם שהמזהה מעולם לא ראה יוצא כמילה הדומה ביותר לו, וחיפוש של האיות הנכון מפספס אותו. לכן חפשו מילה מובהקת שנאמרה באותו משפט, ואז קראו סביב התוצאה. וגם רדיו אינו רק דיבור: רקעי מוזיקה, ג'ינגלים ופרסומות מייצרים שורות שנראות כמו משפטים ואינן כאלה. בדקו את השמע לפני שמצטטים.
לתוויות דוברים שלוש הגדרות: כבוי, פעיל, או When Needed, שמציג תוויות ברגע שנשמע דובר שני. אפשר לתת שם לדובר בהקלטה (PUT /v1/recordings/{id}/speakers/{idx}), וברגע שקולו של דובר נרשם, הקלטות עתידיות מזהות אותו בשמו. לתחנה שהמגישים שלה חוזרים כל בוקר, התוויות מפסיקות להיות „דובר 2” אחרי השבוע הראשון. ורק אחרי שהציטוט נבדק, הוא יכול לצאת מהבניין.
לכל פורמט בלשונית Export של תמלול יש תפקיד בחדר חדשות. SRT הולך לעורך הווידאו, כך שקטע מהזרם מגיע עם כתוביות; SRT מתורגם מגיע איתן בשפה אחרת. Excel הולך לחוקר, שורה לכל משפט עם חותמת הזמן שלו, כדי לסנן ולהוסיף הערות. PDF הולך לעורך שרוצה לקרוא שידור של שעה שלמה ברכבת. JSON הולך למי שכותב את הכלים של המערכת. דרך ה־API, הייצוא הוא GET /v1/recordings/{id}/export?format=srt|json|xlsx|pdf, עם lang= לגרסה מתורגמת. Download audio מוריד את ההקלטה כקובץ MP3 לחבילה עצמה.
ניטור של שידור לצורך דיווח הוא נוהל רגיל בחדר חדשות. פרסום מחדש של קטע ממנו הוא מעשה אחר. הוא כפוף לכללי השימוש ההוגן (fair dealing או fair use) במקום שבו אתם נמצאים, ולתנאים של התחנה עצמה, וכללי הציטוט הרגילים של החדר לגבי מתחרה חלים גם על השמע של המתחרה. כל מה שלמעלה הוא עניין של כמה קליקים בלוח הבקרה; לחדר עם עשרים תחנות, עדיף לכתוב סקריפט.
כל התהליך זמין ב־API, כלול בכל מסלול ומחויב באותו תעריף כמו בלוח הבקרה. תמלול בשידור חי עם מקור של זרם נוצר במצב המתנה, מתחיל בהקלטה הראשונה שלו, ונשלט דרך 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 מכיל כל נתיב והמסגרות שלו.
סוכן AI יכול לעבוד עם הספרייה בלי שום קוד. שרת ה־MCP ב־/v1/mcp נותן לסוכן קבוצה של כלים, ומתוכם ארבעה חשובים כאן. search_transcriptions מחפש במה שנאמר בכל התמלולים של החשבון, בכל שפה, ומחזיר את השורות שנמצאו, כל אחת עם התמלול שבו היא נמצאת והשעה שבה נאמרה. get_summary מחזיר את הסיכום של הקלטה. transcribe_url ו־wait_for_transcription מתמללים וידאו שהסתיים או קישור להקלטה, ומחכים לתוצאה. הפעלה של מוניטור לשידור חי נשארת בלוח הבקרה או ב־API שלמעלה. ההגדרה ל־Claude Code, ל־Cursor או לכל לקוח Streamable HTTP נמצאת תחת Developers → Connect an AI agent; מאמר ה־MCP עובר עליה שלב אחר שלב. מה עולה להריץ את הסקריפט הוא השאלה האחרונה.
תמלול בשידור חי עולה $0.60 לשעת שמע, מחויב לפי שנייה ($0.01 לדקה), עם מינימום של 5 דקות לתמלול. שידור חי עולה יותר מקובץ כי הוא מתומלל תוך כדי שהוא קורה, לכל משך ההפעלה. קבצים עולים $0.20 לשעה ($0.0033 לדקה; קובץ של 30 דקות עולה $0.10). התעריפים זהים בכל המסלולים ודרך ה־API, ותרגומים, סיכומים, שמות דוברים, שידור ושיתוף אינם מוסיפים לחיוב.
תחנה שמנוטרת שמונה שעות ביום, חמישה ימים בשבוע, הן 40 שעות של שידור חי: $24 בשבוע, בכל השפות שבהן החדר קורא אותה.
המגבלות שחשובות לניטור משתנות לפי מסלול. כל אחת מופיעה בסדר הבא: תשלום לפי שימוש, Premium, Enterprise:
לחשבון חדש יש קרדיט הרשמה של $5 ללא כרטיס, וזה יותר משמונה שעות של ניטור חי כדי לנסות. הטבלה המלאה נמצאת בדף התמחור.