מפתחים

API להמרת דיבור לטקסט

תמלול קובצי שמע שהושלמו באמצעות משימות בתור, הערכות ללא עלות, שליחה אידמפוטנטית ומעקב אחר השימוש בשני שרתי ה-API.

בעמוד זה
  1. נקודות קצה
  2. הכנת קובץ שמע
  3. שליחת משימת תמלול
  4. מפתח אידמפוטנטיות
  5. הערכה ללא יצירת משימה
  6. קריאת התמלול
  7. שימוש ב-api.multitel.net

API זה מתמלל קובצי שמע שהושלמו כמשימות בתור. שלחו קובץ, שמרו את מזהה המשימה שהוחזר ואחזרו את המשימה עד לסיום העיבוד. שלחו כל בקשה ב-HTTPS עם פרטי האימות של חשבונכם, באמצעות פרטי HTTP Basic כפי שמוצג בדוגמאות או אסימון API, כמתואר בסעיף אימות. שמרו את פרטי האימות בשרת שלכם.

נקודות קצה

שני שרתי API, https://api.multi.tel ושרת התאימות https://api.multitel.net, חולקים אותן משימות ברמת החשבון, מפתחות אידמפוטנטיות, מגבלות וחיוב. הם נבדלים בקידוד ההעלאה ובמבנה מעטפת התגובה, לכן השתמשו בעקביות בשרת אחד עם מנתח תגובות תואם.

פעולהשיטה ונתיב
מידע על השירותGET /v3/speech_to_text
שליחת משימהPOST /v3/speech_to_text
הערכה ללא יצירת משימהPOST /v3/speech_to_text/estimate
קריאת משימהGET /v3/speech_to_text/JOB_ID
הסדרת תשלום למשימה הממתינה לתשלוםPOST /v3/speech_to_text/JOB_ID/settle
שימושGET /v3/speech_to_text/usage

בשרת api.multi.tel, כל נתיב זמין גם עם הקידומת /v1/speech-to-text במקום /v3/speech_to_text, לדוגמה POST /v1/speech-to-text/estimate. בשרת api.multitel.net, השתמשו בנתיבי /v3/speech_to_text.

תגובת המידע על השירות מדווחת על mode (batch), realtime (false), paidEnabled (האם מתקבלות כעת משימות חדשות בתשלום), pricePerMinuteUsd (0.005), billingUnit (audio_second), maxAudioSeconds (7200) וכן maxUploadBytes (26214400), יחד עם תיאור קצר בשדה description. קריאת המידע היא ללא עלות ופועלת גם כשהגשת משימות בתשלום מושבתת; היא מחזירה 503 transcription_unavailable רק כשהשירות כולו אינו זמין.

הכנת קובץ שמע

השתמשו בקובץ שמע שהושלם, בגודל של עד 25 MiB (26,214,400 בתים) ובאורך של עד 2 שעות (7,200 שניות). בעת השליחה, הקובץ חייב להיות מזוהה כמדיה בפורמט MP3, WAV, Ogg, FLAC, MOV או Matroska המכילה זרם שמע, עם משך במטא-נתונים הגדול מאפס ואינו עולה על 7,200 שניות. קובץ מזוהה שאינו עומד בבדיקות אלה נדחה עם 422 unsupported_audio. קובץ שלא ניתן לקרוא באף אחד מהפורמטים האלה עשוי כרגע להידחות במקום זאת עם שגיאת שרת (500); אל תשלחו שוב קובץ כזה ללא שינוי. סיומת קובץ לבדה אינה מעידה על תאימות.

מעבר הבדיקות אינו מבטיח שניתן לפענח את השמע. השמע מעובד כערוץ אחד או שניים. קובץ עם יותר משני ערוצי שמע, קובץ שהשמע המפוענח שלו ארוך מ-2 שעות, או כל קובץ אחר שפענוחו נכשל במהלך העיבוד, מסתיים כמשימה במצב failed, בדרך כלל עם decode_failed, ואינו מחויב. המירו שמע מרובה ערוצים למונו או לסטריאו לפני השליחה.

רמז השפה האופציונלי הוא קוד בן שתיים או שלוש אותיות קטנות המציין את השפה המדוברת, כגון en. כדי לא לספק רמז, השמיטו את השדה; api.multi.tel דוחה מחרוזת ריקה. הרמז מנחה את העיבוד אך אינו נבדק מול רשימת שפות נתמכות, לכן השתמשו בקוד תקין של השפה המדוברת.

שליחת משימת תמלול

שלחו JSON עם Content-Type: application/json אל POST https://api.multi.tel/v3/speech_to_text. גוף הבקשה יכול להיות בגודל של עד 35 MiB, כדי להכיל קובץ בגודל המרבי לאחר קידוד base64; גוף גדול יותר נדחה עם 413.

שדהמשמעות
audioBase64נדרש. הקובץ המלא ב-base64 תקני (A–Z, a–z, 0–9, +, /) עם תווי מילוי = לפי הצורך. אל תוסיפו קידומת data-URL, מעברי שורה או רווחים, ואל תשתמשו באלפבית המותאם לכתובות URL. הערך חייב להתפענח לקובץ בגודל שבין 1 בית ל-25 MiB ולהתקודד מחדש לאותו טקסט בדיוק.
languageרמז שפה אופציונלי, כמתואר לעיל.

כל מאפיין JSON אחר, כולל idempotency_key, נדחה עם 400 invalid_transcription_request. שלחו את המפתח ככותרת.

מפתח אידמפוטנטיות

כל שליחה דורשת כותרת Idempotency-Key באורך של 1 עד 190 תווים. השתמשו באותיות ASCII, בספרות, ב--, _, . וב-:, ללא רווחים בתחילת הערך או בסופו: שרת התאימות מסיר רווחים מסביב ומודד את המפתח בבתים, לכן תווים אחרים עשויים להיספר אחרת בכל שרת. מפתח חסר, או מפתח באורך 191 תווים ומעלה, נדחה עם 400.

המפתחות משויכים לחשבונכם ולשירות המרת דיבור לטקסט, בשני השרתים ובכל פרטי האימות של החשבון. שליחה חוזרת של אותו מפתח עם אותו קובץ ושפה מחזירה את המשימה הקיימת עם HTTP 200 ו-duplicate: true, ללא קשר למצבה וגם אם העיבוד עודכן מאז יצירתה, ללא חיוב נוסף. שימוש חוזר במפתח עם קובץ או שפה שונים מחזיר 409 idempotency_conflict. מפתח חדש יוצר משימה חדשה גם עבור קובץ זהה, עם חיוב נפרד אם העיבוד מסתיים בהצלחה.

API_USER="your-api-username"
API_PASSWORD="your-api-password"

node -e 'process.stdout.write(JSON.stringify({audioBase64:require("node:fs").readFileSync("completed-call.mp3").toString("base64"),language:"en"}))' > completed-call.json

curl --fail-with-body --silent --show-error --user "$API_USER:$API_PASSWORD" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: speech-call-001" \
  --data-binary @completed-call.json \
  -o speech-job.json \
  https://api.multi.tel/v3/speech_to_text

node -p 'JSON.parse(require("node:fs").readFileSync("speech-job.json","utf8")).data.id'

משימה חדשה מחזירה HTTP 202 עם השדות המוצגים להלן, ושליחה חוזרת מחזירה HTTP 200 עם אובייקט המשימה המלא המתואר בסעיף קריאת התמלול. קראו את מזהה המשימה, שהוא UUID, מתוך data.id. תגובה למשימה חדשה נראית כך (המזהה והערכים הם דוגמאות):

{
  "status": "success",
  "data": {
    "id": "3f6c1b2e-8a4d-4e7f-9c21-5b0d7e4a9f13",
    "status": "queued",
    "mode": "batch",
    "realtime": false,
    "source": "api",
    "durationSeconds": 90.5,
    "billedSeconds": 91,
    "costUsd": "0.007583334",
    "pricePerMinuteUsd": "0.005"
  }
}

כל עוד משימה נמצאת בתור או פועלת, durationSeconds, billedSeconds ו-costUsd הם אומדנים מהמטא-נתונים של הקובץ. החיוב הסופי מבוסס על משך השמע המפוענח.

שליחה יכולה גם להחזיר 402 insufficient_balance כאשר יתרה ששולמה מראש אינה מספיקה לכיסוי המשימה יחד עם המשימות האחרות שלכם שטרם הסתיימו, 429 transcription_queue_full כאשר לחשבונכם או לשירות יש יותר מדי משימות שטרם הסתיימו, 429 audio_validation_busy כאשר אין קיבולת פנויה לאימות קבצים, וכן 503 paid_transcription_not_enabled כאשר תמלול בתשלום מושבת. נסו שוב מאוחר יותר לאחר תגובות 429 ו-503, עם אותו מפתח.

הערכה ללא יצירת משימה

שלחו את אותו גוף JSON אל POST https://api.multi.tel/v3/speech_to_text/estimate. אין צורך במפתח אידמפוטנטיות. הערכה מאמתת ומודדת את הקובץ, אך אינה מתמללת אותו, יוצרת משימה, משריינת כספים, בודקת את יתרתכם או מחייבת את חשבונכם. רמז language מתקבל אך אינו משפיע על ההערכה.

הערכה מוצלחת מחזירה HTTP 200 עם estimate: true, charged: false, mode, realtime, durationSeconds, billedSeconds, pricePerMinuteUsd ו-costUsd תחת data. היא משתמשת במשך שבמטא-נתונים של הקובץ, בעוד שמשימה שהושלמה מחויבת לפי משך השמע המפוענח, שעשוי להיות שונה. הערכות מחילות את אותן בדיקות קובץ כמו שליחות. הן זמינות רק כאשר תמלול בתשלום מופעל (אחרת מתקבל 503 paid_transcription_not_enabled). הן עשויות להחזיר 429 audio_validation_busy כאשר אין קיבולת פנויה לאימות קבצים; נסו שוב לאחר המתנה קצרה.

קריאת התמלול

בצעו תשאול מחזורי של GET /v3/speech_to_text/JOB_ID כמתואר במדריך זרימת העבודה של משימות. אובייקט המשימה מכיל את השדות הבאים:

שדהמשמעות
idה-UUID של המשימה.
statusqueued, running, completed, failed או awaiting_payment.
progressאחוז בין 0 ל-99 בזמן הפעולה, אם זמין; 100 לאחר השלמה; אחרת null.
durationSeconds, billedSecondsמשך השמע והשניות השלמות לחיוב. אלה אומדנים מהמטא-נתונים כשהמשימה בתור או פועלת, והם מבוססים על משך השמע המפוענח לאחר השלמתה או כשהיא ממתינה לתשלום.
costUsd, costIsEstimateהעלות בדולרים אמריקאיים כמחרוזת עשרונית עם תשע ספרות אחרי הנקודה. costIsEstimate הוא true כל עוד המשימה בתור או פועלת. משימה שנכשלה אינה מחויבת, אף שהשדה costUsd שלה עדיין מציג את האומדן.
pricePerMinuteUsd0.005 עבור משימות API, ו-0.000 עבור משימות חינמיות של הקלטות Hosted PBX.
failureCodeלמשימה שנכשלה: decode_failed (לא ניתן היה לפענח את השמע, למשל משום שיש בו יותר משני ערוצים או שאורכו לאחר הפענוח עולה על 2 שעות), inference_timeout (העיבוד ארך זמן רב מדי), service_error, או worker_lease_lost (העיבוד הופסק). גם הקודים unsupported_audio ו-quality_check_failed מוגדרים. משימה הממתינה לתשלום מציגה insufficient_balance, שעשוי להישאר גם לאחר הסדרת התשלום למשימה.
source, modelVersion, createdAtsource הוא api עבור שליחות API, או hpbx עבור משימת הקלטה של Hosted PBX בחשבונכם. modelVersion הוא מחרוזת אטומה של גרסת העיבוד. createdAt הוא זמן השליחה.
duplicatetrue בתגובות המחזירות משימה קיימת.
resultמופיע רק כאשר status הוא completed.
שדה בתוצאהמשמעות
textהתמלול המלא: הטקסטים של כל המקטעים מחוברים במעברי שורה, לפי סדר המקטעים.
segmentsמערך מקטעים המסודרים לפי זמן ההתחלה. כל מקטע מכסה חלק מהשמע באורך של עד כ-29 שניות. השדות start ו-end (בשניות מתחילת השמע) מסמנים את החלק הזה, ולא מילים או משפטים בודדים, וחלקים עוקבים יכולים לחפוף עד 1 שנייה. לכל מקטע יש גם text ו-language (קוד שפה, שיכול להיות ריק), וכן channel עבור תוצאות עם שני ערוצים.
channelCount1 או 2. מופיע בתוצאות הנוכחיות; תוצאות ישנות עשויות לא לכלול אותו.
audioDurationMsמשך השמע המפוענח במילישניות. החיוב מעגל אותו כלפי מעלה לשניות שלמות.
qualityFlagsריק, או review_recommended יחד עם repetition_detected (ביטוי חוזר בתדירות חריגה בתוך חלק מהשמע), no_speech (לא תומלל דיבור), או שניהם.
pipelineVersionעשוי להופיע. מזהה עיבוד אטום.

התמלולים וחותמות הזמן, תוויות השפה ותוויות הערוצים שלהם נוצרים אוטומטית, ודיוקם אינו מובטח. התייחסו לכל דגל איכות כסיבה לבדוק את התוצאה, והשוו שמות, מספרים והתחייבויות חשובים לשמע המקורי. דילוג מתבצע על שתיקות ארוכות ועל קטעים חלשים מאוד, ולכן לא נוצרים עבורם מקטעים. התוצאות אינן מזהות דוברים בודדים. כאשר תוצאה מדווחת על channelCount בערך 2, לכל מקטע יש channel בערך A (הערוץ הראשון, או השמאלי) או B (הערוץ השני, או הימני). הדבר מפריד בין דוברים רק אם כל דובר הוקלט בערוץ נפרד. שמע בשני ערוצים מחויב פעם אחת לפי משכו, ולא לכל ערוץ. בתוצאות מונו אין תוויות ערוצים.

שימוש ב-api.multitel.net

נקודת הקצה לתאימות POST https://api.multitel.net/v3/speech_to_text מקבלת multipart/form-data עם חלק קובץ בשם audio ושדה אופציונלי בשם language, במקום JSON עם audioBase64. ערך ריק של language נחשב כהיעדר רמז. שלחו את אותה כותרת Idempotency-Key. אם הכותרת חסרה, שרת זה מקבל גם שדה טופס בשם idempotency_key. שדות בשם source, free, billing_source, realtime או stream נדחים עם 400 unsupported_transcription_option; שדות טופס אחרים אינם נלקחים בחשבון. שרת זה מחזיר גם את השגיאות הבאות:

  • 400 idempotency_key_required עבור מפתח חסר או ארוך מדי.
  • 400 audio_upload_required עבור העלאה חסרה או העלאה שלא התקבלה במלואה.
  • 400 invalid_language עבור שפה לא תקינה.
  • 413 invalid_audio_size עבור קובץ ריק או גדול מדי.
  • 400 invalid_job עבור מזהה משימה במבנה לא תקין.

תגובות משירות המרת הדיבור לטקסט של שרת זה משתמשות במעטפת {"status":{"code":HTTP_STATUS},"response":{...}}. שימו לב כי status הוא אובייקט, לא מחרוזת. במקרה הצלחה, response מכיל את אותו אובייקט כמו data בשרת הראשי, כך שמזהה המשימה הוא response.id. במקרה שגיאה, response.code מכיל את קוד השגיאה; לא נכללת הודעה או מזהה בקשה. כשלי אימות (401) מוחזרים מבדיקת ההתחברות הכללית של השרת ועשוי להיות להם גוף שונה, לכן בדקו את קוד מצב ה-HTTP לפני הניתוח. אל תחליפו את קידוד ההעלאה או את מנתח התגובות בין השרתים.

לקבלת הערכה בשרת זה, שלחו ב-POST את אותם שדות multipart אל /v3/speech_to_text/estimate. אין צורך במפתח אידמפוטנטיות, וההערכה נמצאת תחת response.

API_USER="your-api-username"
API_PASSWORD="your-api-password"

curl --fail-with-body --silent --show-error --user "$API_USER:$API_PASSWORD" \
  -H "Idempotency-Key: speech-call-001" \
  -F "audio=@completed-call.mp3" -F "language=en" \
  -o speech-job.json \
  https://api.multitel.net/v3/speech_to_text

node -p 'JSON.parse(require("node:fs").readFileSync("speech-job.json","utf8")).response.id'