பதிவேற்றம் ஒரு டிரான்ஸ்கிரிப்டைத் தராது, ஒரு பணியையே (job) தரும். ஒவ்வொரு உருவாக்க அழைப்பிலும் Idempotency-Key வைத்திருங்கள், அப்போது மறுமுயற்சி ஒருபோதும் இரண்டாவது டிரான்ஸ்கிரிப்ஷனை உருவாக்காது அல்லது கட்டணம் வசூலிக்காது; பிறகு பணி முடியும் வரை நிலையைக் கேட்டுக்கொண்டிருங்கள், அதே id-யிலிருந்து வாக்கியங்கள், சொற்கள் அல்லது ஏற்றுமதிக் கோப்பைப் படியுங்கள்.
கோப்பு டிரான்ஸ்கிரிப்ஷன் என்பது VocalStack API செய்யும் எளிமையான செயல், அது எந்த ஒத்திசைவற்ற பணியின் (asynchronous job) வடிவத்தையும் கொண்டது: பதிவேற்று, காத்திரு, படி. பதிவேற்றம் உடனே பதிலளிக்கும், அதற்கு ஒரு டிரான்ஸ்கிரிப்ஷனும் அதன் பணியும் கிடைக்கும், ஆனால் இன்னும் சொற்கள் இருக்காது. உங்கள் நிரல் பணியை வாக்களிக்கும்போது, சேவையகம் கோப்பை ஆடியோ இயங்கும் வேகத்தைவிடப் பல மடங்கு வேகமாக டிரான்ஸ்கிரிப்ட் செய்கிறது. நிலை done ஆகும்போது, பேச்சாளர்களும் நேரக்குறிப்புகளும் உள்ள வாக்கியங்களாக டிரான்ஸ்கிரிப்ட்டைப் படிக்கலாம், அல்லது நான்கு வடிவங்களில் ஒன்றில் கோப்பாக ஏற்றுமதி செய்யலாம்; பேசப்பட்ட மொழியிலோ மொழிபெயர்க்கப்பட்ட மொழியிலோ.
இந்த வடிவம் எந்த தொகுப்பு (batch) API-க்கும் பொருந்தும்: id தரும் ஒரு உருவாக்கம், நீங்கள் வாக்களிக்கும் ஒரு நிலை, பின்னர் பெறும் ஒரு முடிவு. புலப் பெயர்கள் மட்டுமே VocalStack-க்கு உரியவை; இந்த டுடோரியல் அவற்றை TypeScript மற்றும் Python SDK-களுடனும், தேவையான இடங்களில் HTTP அழைப்புகளுடனும் விளக்குகிறது.
டாஷ்போர்டில் Developers → API keys திறந்து Read மற்றும் Write அனுமதிகளுடன் ஒரு விசையை உருவாக்குங்கள். விசை ஒரே ஒரு முறைதான் காட்டப்படும்; அதை ஒரு சூழல் மாறிக்குள் நகலெடுங்கள்:
export VOCALSTACK_API_KEY="<your API key>"
விசை சேவையகங்களுக்கும் ஸ்கிரிப்ட்டுகளுக்கும்தான். உலாவிக்கு அனுப்பப்படும் எதுவும் விசையையும் கூடவே அனுப்புகிறது, எனவே அதைப் பக்கக் குறியீட்டிலிருந்தும் URL-களிலிருந்தும் விலக்கி வையுங்கள், ஏனெனில் URL-கள் பதிவுகளில் சேரும். உலாவியிலிருந்து ஸ்ட்ரீம் செய்ய, உங்கள் சேவையகம் அதற்கு ஒரு நேரடி அமர்வை (realtime session) உருவாக்கும்; அது வேறொரு டுடோரியல்.
ஒவ்வொரு அழைப்பும் விசையை bearer டோக்கனாகக் கொண்டு அங்கீகரிக்கிறது:
Authorization: Bearer vs_key_...
விசை சூழலில் இருப்பதால், அடுத்த படி அதை அனுப்பும் ஒரு கிளையண்ட்.
இரண்டு SDK-கள் உள்ளன. ஒவ்வொன்றிலும் VocalStack என்ற ஒரே கிளையண்ட் உண்டு; அதன் முறைகள் வளங்களின்படி தொகுக்கப்பட்டுள்ளன: vs.transcriptions, vs.jobs, vs.recordings, vs.realtime மற்றும் வேறு சிலவும். TypeScript SDK Node 20 அல்லது புதியதிலும் உலாவிகளிலும் இயங்கும்; Python SDK asyncio-வின் மேல் கட்டப்பட்டது, Python 3.10 அல்லது புதியது தேவை.
SDK-கள் npm அல்லது PyPI-யில் இல்லை. API அனைத்துக் கணக்குகளுக்கும் உருவாக்கங்களை வழங்குகிறது. உங்கள் சூழலுக்கேற்ற நிறுவல் கட்டளைகள் API குறிப்பேட்டின் விரைவுத் தொடக்கத்தில் உள்ள Install பகுதியில் உள்ளன; அவை உங்கள் விசையை API ஹோஸ்டுக்கு மட்டுமே அனுப்பும். எதையும் நிறுவ விரும்பவில்லையென்றால், கீழே உள்ள HTTP அழைப்புகளுக்கு curl மற்றும் jq மட்டுமே போதும்.
நீங்கள் எதைத் தேர்ந்தெடுத்தாலும், முதல் அழைப்பு பதிவேற்றம்தான்.
POST /v1/transcriptions கோப்பை multipart/form-data ஆக ஏற்கிறது: ஒரு file பகுதியும், JSON-ஐக் கொண்ட விருப்பத்தேர்வு options பகுதியும். அது 201 உடன் டிரான்ஸ்கிரிப்ஷனைத் திருப்பும். அதன் job.recordingId கோப்பிலிருந்து உருவான பதிவின் id; அதன் பின் வரும் ஒவ்வொரு அழைப்பும் அந்த id-யைக் கொண்டே குறிக்கப்படும்.
முதல் ஓட்டத்துக்கு இரண்டு அமைப்புகள் முக்கியம், இரண்டும் options.settings-க்குள்:
spokenLanguage: en போன்ற ஒரு குறியீடு. விட்டுவிட்டால் மொழி கண்டறியப்படும். அதைக் குறிப்பிடுவது இரைச்சல் மிகுந்த பதிவுகளிலும் கனமான உச்சரிப்புகளிலும் துல்லியத்தை மேம்படுத்தும்.speakerLabels: auto, on அல்லது off. on என்றால் ஒவ்வொரு வாக்கியத்திலும் ஒரு பேச்சாளர் எண் இருக்கும்; auto என்றால் இரண்டாவது பேச்சாளர் கேட்கப்பட்ட பிறகுதான் லேபிள்கள் தோன்றும்.mp3, wav, flac, ogg, m4a, mp4 உட்பட பெரும்பாலான ஆடியோ மற்றும் வீடியோ கோப்புகள் ஏற்கப்படும். வீடியோ அதன் ஆடியோவை மட்டுமே வைத்துக்கொள்ளும். வடிவம் துல்லியத்தைப் பெரிதாக மாற்றாது, ஏனெனில் பேச்சு அறிதல் 16 kHz மோனோவில் வேலை செய்கிறது, வந்தவுடன் அனைத்தும் அதற்கு மறுமாதிரியாக்கப்படும் (resample). ஒருவர் பேசும் 48 kHz ஸ்டீரியோ WAV, அதன் பெரும்பாலான பைட்டுகளை உயர் தரத்தில் அமைதியை விவரிப்பதில் செலவிடுகிறது. அதே பேச்சின் 64 kbps மோனோ MP3 அல்லது Opus கோப்பைப் போலவே அது சரியாக டிரான்ஸ்கிரிப்ட் ஆகும், ஆனால் சுமார் இருபது மடங்கு பெரியதாக இருக்கும், எனவே பதிவேற்றவும் இருபது மடங்கு நேரம் எடுக்கும். பதிவேற்றுவதற்கு முன் மாற்றினால், மோனோவும் மிதமான bitrate-உம் மாற்றத்தக்க இரண்டு அமைப்புகள்.
ஒவ்வொரு பதிவேற்றத்துடனும் Idempotency-Key அனுப்புங்கள்; ஏன் என்றும் புரிந்துகொள்ளுங்கள். பிணைய நேரமுடிவு (timeout) சேவையகம் என்ன செய்தது என்று உங்களுக்குச் சொல்லாது: அது கோரிக்கையைப் பார்க்காமலும் இருந்திருக்கலாம், அல்லது பதில் தொலைவதற்கு முன் கோப்பைச் சேமித்து வேலையை வரிசையில் வைத்திருக்கலாம். குருட்டுத்தனமான மறுமுயற்சி ஒரு இரண்டாவது டிரான்ஸ்கிரிப்ஷனையும் இரண்டாவது கட்டணத்தையும் ஆபத்தில் ஆழ்த்தும். இந்தச் சாவி அதைத் தடுக்கிறது. ஒரே சாவி, ஒரே உடலுடன் 24 மணி நேரத்துக்குள் கோரிக்கை மீண்டும் வந்தால், சேவையகம் எதையும் உருவாக்காமல் முதல் பதிலைத் திருப்பும்; இதனால் "குறைந்தது ஒரு முறை" என்பது "நடைமுறையில் ஒரு முறை" ஆகிறது. எனவே விதி: ஒரு தர்க்கரீதியான பதிவேற்றத்துக்கு ஒரு சாவி, முதல் முயற்சிக்கு முன் உருவாக்கி, ஒவ்வொரு மறுமுயற்சியிலும் மீண்டும் பயன்படுத்துவது. ஒவ்வொரு முயற்சிக்கும் புதிய சாவி கொடுத்தால், ஒவ்வொரு மறுமுயற்சியும் புதிய பதிவேற்றமாகிவிடும், அந்தத் தலைப்பு எதையும் பாதுகாக்காது.
import { VocalStack } from '@vocalstack/sdk';
const vs = new VocalStack({ baseUrl: '{{api}}', apiKey: process.env.VOCALSTACK_API_KEY });
const uploadKey = crypto.randomUUID(); // one key for this upload, however many attempts it takes
const tx = await vs.transcriptions.create(
{ file: './talk.mp3', name: 'Talk', settings: { spokenLanguage: 'en', speakerLabels: 'on' } },
{ idempotencyKey: uploadKey },
);
const recordingId = tx.job!.recordingId;
import asyncio
import os
import uuid
from vocalstack import VocalStack
async def main() -> None:
upload_key = str(uuid.uuid4()) # one key for this upload, however many attempts it takes
async with VocalStack("{{api}}", api_key=os.environ["VOCALSTACK_API_KEY"]) as vs:
tx = await vs.transcriptions.create(
file="./talk.mp3",
name="Talk",
settings={"spokenLanguage": "en", "speakerLabels": "on"},
idempotency_key=upload_key,
)
assert tx.job is not None
recording_id = tx.job.recording_id
curl மூலம் அதே அழைப்பு:
API={{api}}
AUTH="Authorization: Bearer $VOCALSTACK_API_KEY"
UPLOAD_KEY=$(uuidgen)
REC=$(curl -sSf "$API/v1/transcriptions" -H "$AUTH" -H "Idempotency-Key: $UPLOAD_KEY" \
-F file=@talk.mp3 \
-F 'options={"name":"Talk","settings":{"spokenLanguage":"en","speakerLabels":"on"}}' \
| jq -r .job.recordingId)
201 பதில் ஒரு சொல்லும் டிரான்ஸ்கிரைப் ஆவதற்கு முன்பே வருகிறது; உங்கள் கையில் இருப்பது ஒரு பணி id, எனவே அடுத்த படி அதற்காகக் காத்திருப்பது.
ஒரு பணி queued → transcribing → done என நகரும், அல்லது failed நிலையில் முடியும்; அதில் error செய்தியும், காரணம் இயந்திரம் படிக்கக்கூடியதாக இருந்தால் errorCode-உம் இருக்கும். நான்காவது நிலை cropping: எந்தப் பகுதியை டிரான்ஸ்கிரிப்ட் செய்வது என்று யாராவது தேர்ந்தெடுக்கும் வரை பணி நிறுத்தி வைக்கப்படும்; டாஷ்போர்டின் trim படியில் நடப்பது போல. சாதாரண பதிவேற்றம் ஒருபோதும் அந்த நிலைக்குச் செல்லாது, இருந்தாலும் jobs.wait அந்த நிலையை அடையும்போதும் திரும்பும். நிலை done அல்லது failed ஆகும் வரை GET /v1/recordings/{id}/job-ஐப் படியுங்கள்.
வெப்ஹூக்குகள் இல்லை; அது ஒரு வேண்டுமென்றே எடுத்த வர்த்தகம். வெப்ஹூக்குக்கு உங்கள் பக்கத்தில் ஒரு பொது HTTPS முனையம், வேறு யாரும் அழைக்காமல் இருக்க ஒரு கையொப்ப சரிபார்ப்பு, உங்கள் முனையம் கீழே இருக்கும்போதுக்கான மறுமுயற்சிக் கொள்கை ஆகியவை வேண்டும்; ஒரு நிமிடம் எடுக்கும் பணிக்கு இது நிறைய இணைப்பு வேலை. வாக்களிப்புக்கு இவை எதுவும் தேவையில்லை. உங்கள் ஸ்கிரிப்ட் ஒவ்வொரு இரண்டு வினாடிக்கும் "முடிந்ததா?" எனக் கேட்கும், பின்சீட்டில் அமர்ந்திருக்கும் குழந்தை போல; ஆனால் அந்தக் குழந்தையைப் போலன்றி, அதற்கு சதவீதமும் கிடைக்கும்.
ஏற்கனவே திறந்திருக்கும் ஒரு வலைப்பக்கம் அதற்குப் பதிலாக டிரான்ஸ்கிரிப்ஷனின் நிகழ்வுச் சாக்கெட்டைப் (WS /v1/transcriptions/{id}/events, பணி முன்னேறும்போது ஒரு job.progress சட்டம்) பின்தொடரலாம். ஒரு ஸ்கிரிப்ட்டுக்கு, வாக்களிப்புதான் சரியான கருவி.
SDK-கள் வாக்களிப்பைச் செய்கின்றன: vs.jobs.wait ஒவ்வொரு 2 வினாடிக்கும் பணியைப் படித்து, ஒவ்வொரு வாசிப்பையும் onProgress-க்கு (Python-இல் on_progress) அனுப்புகிறது. பணியின் progress-இல் pct (0 முதல் 100 வரை) மற்றும் processedS உள்ளன, அதாவது இதுவரை டிரான்ஸ்கிரைப் செய்யப்பட்ட மீடியா வினாடிகள். கீழே உள்ள நிரல்கள் நிலையோ சதவீதமோ மாறும்போது மட்டும் ஒரு வரி அச்சிடுகின்றன.
let last = '';
const job = await vs.jobs.wait(recordingId, {
onProgress: (j) => {
const line = `${j.state} ${j.progress.pct}%`;
if (line !== last) console.log((last = line));
},
});
if (job.state !== 'done') throw new Error(`transcription ${job.state}: ${job.error ?? ''}`);
last = ""
def on_progress(j) -> None:
nonlocal last
line = f"{j.state} {j.progress.pct}%"
if line != last:
last = line
print(line)
job = await vs.jobs.wait(recording_id, on_progress=on_progress)
if job.state != "done":
raise RuntimeError(f"transcription {job.state}: {job.error}")
wait failed நிலையில் பிழை எறிவதில்லை என்பதைக் கவனியுங்கள்; அது பணியைத் திருப்பி, சரிபார்ப்பை உங்களிடம் விட்டுவிடுகிறது. ஒரு பேச்சுக்கு இரண்டு வினாடிகள் போதும். மூன்று மணி நேரப் பதிவுக்கோ நூற்றுக்கணக்கான தொகுப்புக்கோ இடைவெளியை அகலமாக்குங்கள் (intervalMs, interval_s), அல்லது பணி நடக்கும்போது பின்னிழுக்கவும்: முதல் வாசிப்புகள்தான் அதிகம் சொல்லும், பின்னர் வருபவை சேவையகம் இன்னும் பிஸியாக இருப்பதை பெரும்பாலும் உறுதிப்படுத்தும். SDK இல்லாமல், அதே சுழற்சியை நீங்களே கையால் எழுதுவீர்கள்:
while :; do
JOB=$(curl -sSf "$API/v1/recordings/$REC/job" -H "$AUTH")
STATE=$(jq -r .state <<<"$JOB")
echo "$STATE $(jq -r .progress.pct <<<"$JOB")%"
case $STATE in
done) break ;;
failed) jq -r .error <<<"$JOB" >&2; exit 1 ;;
esac
sleep 2
done
நிலை done என்று காட்டும்போது, டிரான்ஸ்கிரிப்ட் தயார்.
GET /v1/recordings/{id}/transcript முழு டிரான்ஸ்கிரிப்டையும் ஒரே ஆவணமாகத் திருப்பும்:
sentences: மக்களுக்குக் காட்ட வேண்டியவை. ஒவ்வொன்றிலும் text, speaker, மற்றும் வினாடிகளில் start மற்றும் end உள்ளன.segments: இயந்திரத்தின் வரிகள், ஒவ்வொன்றிலும் words-இல் சொல் வாரியான நேரங்கள் (ஒவ்வொரு சொல்லுக்கும் text, start மற்றும் end).speakers: ஒவ்வொரு பேச்சாளர் எண்ணுக்கும் ஒரு உள்ளீடு, அதன் name-உடன்.பேச்சாளர்கள் 0-இலிருந்து எண்ணப்படுவார்கள். speaker -1 என்றால் அந்தப் பதிவுக்குப் பேச்சாளர் லேபிள்கள் முடக்கப்பட்டிருந்தன என்று பொருள். மொழிபெயர்க்கப்பட்ட ஸ்பானிஷ் டிரான்ஸ்கிரிப்டைப் படிக்க ?lang=es சேர்க்கவும்; வாக்கியங்கள் அந்த மொழியில் திரும்பும்.
const { sentences } = await vs.recordings.transcript(recordingId);
for (const s of sentences) console.log(s.speaker >= 0 ? `[speaker ${s.speaker}] ${s.text}` : s.text);
snapshot = await vs.recordings.transcript(recording_id)
for s in snapshot.sentences:
print(f"[speaker {s.speaker}] {s.text}" if s.speaker >= 0 else s.text)
curl -sSf "$API/v1/recordings/$REC/transcript" -H "$AUTH" \
| jq -r '.sentences[] | if .speaker >= 0 then "[speaker \(.speaker)] \(.text)" else .text end'
இரண்டு நேர அளவுகள் இரண்டு வேலைகளுக்குச் சேவை செய்கின்றன. வாக்கியங்கள் வாசிப்பின் அலகு, எனவே வசனம் அல்லது டிரான்ஸ்கிரிப்ட் பக்கம் காட்டுவது அவைதான். சொற்கள் சுட்டிக்காட்டும் அலகு, எனவே கராஓகே பாணி முன்னிலைப்படுத்தல், தேடல் முடிவு அல்லது கிளிப் வெட்டு segments[].words-ஐப் பின்தொடரும். ஏற்றுமதி வடிவங்கள் வாக்கியங்களிலிருந்தே கட்டப்படுகின்றன.
GET /v1/recordings/{id}/export ஒரு உண்மையான கோப்பைத் திருப்பும். format srt, json, xlsx அல்லது pdf ஆக இருக்கலாம்; கோப்பில் இருக்கும் எந்தத் திருத்தங்களும் சேர்க்கப்படும். மொழிபெயர்க்கப்பட்ட கோப்புக்கு lang= சேர்க்கவும்: அப்போது ஏற்றுமதி அந்த மொழியில் படிக்கும், ஒரு வாக்கியத்துக்கு ஒரு வரியாக, மொழிபெயர்க்கப்படாத எந்த வாக்கியமும் முதலில் மொழிபெயர்க்கப்படும்.
SRT-ஐ அதன் தோற்றத்தால் தெரிந்துகொள்வது பயனுள்ளது, ஏனெனில் அதுதான் கிட்டத்தட்ட எல்லாப் பிளேயர்களும் ஏற்கும் வசன வடிவம், மேலும் அது வெறும் உரை. ஒரு கோப்பு வெற்று வரிகளால் பிரிக்கப்பட்ட cue-களின் பட்டியல்; ஒவ்வொரு cue-உம் ஓர் எண், ஒரு நேர வரம்பு, உரை. நேரக்குறிகள் மில்லி வினாடிக்கு முன் காற்புள்ளியைப் பயன்படுத்துகின்றன, இது வடிவம் ஒருபோதும் கைவிடாத ஒரு பிரெஞ்சுப் பழக்கம்:
1
00:00:01,000 --> 00:00:04,200
Welcome, everyone. Let's get started.
ஒரு cue-க்கு ஒரு வாக்கியம்தான் சரியான அளவு: ஒவ்வொரு cue-உம் திரையில் இருக்கும் நேரத்திலேயே படிக்கப்படலாம், எதுவும் நடுவில் துண்டிக்கப்படாது. பதிவில் பேச்சாளர் லேபிள்கள் இருந்தால், ஒவ்வொரு cue-இன் உரையும் பேச்சாளரின் பெயருடனும் ஒரு காற்புள்ளியுடனும் (colon) தொடங்கும்.
TypeScript SDK-இல் vs.recordings.export ஒரு Response திருப்புகிறது; அதன் பைட்டுகளை arrayBuffer() மூலம் படியுங்கள். Python-இல் அது bytes திருப்புகிறது.
import { writeFile } from 'node:fs/promises';
const srt = await vs.recordings.export(recordingId, 'srt');
await writeFile('talk.srt', Buffer.from(await srt.arrayBuffer()));
const pdf = await vs.recordings.export(recordingId, 'pdf', { lang: 'es' });
await writeFile('talk.es.pdf', Buffer.from(await pdf.arrayBuffer()));
srt = await vs.recordings.export(recording_id, "srt")
with open("talk.srt", "wb") as f:
f.write(srt)
pdf = await vs.recordings.export(recording_id, "pdf", lang="es")
with open("talk.es.pdf", "wb") as f:
f.write(pdf)
asyncio.run(main())
curl -sSf "$API/v1/recordings/$REC/export?format=srt" -H "$AUTH" -o talk.srt
curl -sSf "$API/v1/recordings/$REC/export?format=pdf&lang=es" -H "$AUTH" -o talk.es.pdf
டிரான்ஸ்கிரிப்ஷன் சேமிக்கப்படுவதால், அது டாஷ்போர்டில் Transcriptions-இன் கீழ் தோன்றும், இணைப்பால் பகிரலாம், எப்போது வேண்டுமானாலும் மீண்டும் படிக்கலாம். அதுதான் அடிப்படைச் சுழற்சி: உருவாக்கு, காத்திரு, படி, ஏற்றுமதி செய். இந்த டுடோரியலின் மீதமுள்ள பகுதி மாற்று வழிகளை உள்ளடக்குகிறது: ஏற்கனவே இணையத்தில் உள்ள மீடியா, நீங்கள் சந்திக்கும் பிழைகள், மற்றும் ஒரு கோப்புக்கான செலவு.
மீடியா ஏற்கனவே இணையத்தில் இருந்தால், இணைப்பை API-க்குக் கொடுங்கள்; அதுவே கோப்பைப் பெற்றுக்கொள்ளும்: பொது http(s) முகவரி (ஒரு mp3, ஒரு வீடியோ, ஒரு பாட்காஸ்ட் அத்தியாயம்) அல்லது ஒரு YouTube வீடியோ. அழைப்பு அதே POST /v1/transcriptionsதான், பல்பகுதிப் பதிவேற்றத்துக்குப் பதிலாக { "url": "..." } JSON உடலுடன், name மற்றும் settings முன்புபோலவே. SDK-களில் vs.transcriptions.createFromUrl(url) (TypeScript) மற்றும் vs.transcriptions.create(url=...) (Python) அதே கோரிக்கையைச் செய்கின்றன.
எதையும் உருவாக்குவதற்கு முன், GET /v1/transcriptions/probe?url= ஓர் இணைப்பு எது என்று சொல்லும். அதன் kind மூன்றில் ஒன்று:
file: ஒரு முடிவுள்ள பதிவு; இங்கேயே டிரான்ஸ்கிரிப்ட் செய்யுங்கள்.live: ஒரு YouTube நேரலை, முடிவற்ற வானொலி ஸ்ட்ரீம் அல்லது முடிவில்லாத HLS பிளேலிஸ்ட். நேரடி இணைப்பு ஒருபோதும் முடிவதில்லை, எனவே அதைக் கோப்பாக டிரான்ஸ்கிரிப்ட் செய்ய முடியாது; அதற்குப் பதிலாக நேரலை டிரான்ஸ்கிரிப்ஷனின் மூலமாகப் பயன்படுத்துங்கள்.unknown: சேவையகத்தால் சொல்ல முடியவில்லை.இணைப்பு மீடியாவாகவே திறக்கப்படாவிட்டால் (உதாரணமாக ஒரு வலைப்பக்கம்), ok false ஆகும், problem ஒரு வாக்கியத்தில் ஏன் என்று விளக்கும். probe விருப்பத்தேர்வு; நிமிடத்துக்கு 60 அழைப்புகள் என வரம்பு.
நேரடி இணைப்பின் பணி transcribing மற்றும் done-க்கு முன் fetching-இல் தொடங்குகிறது. அது பெற்றுக்கொள்ளும்போது, progress.phase சேவையகம் என்ன செய்கிறது என்று சொல்கிறது: பைட்டுகள் வரும்போது fetching (மறுமுனை எத்தனை என்று சொன்னால் fetchedBytes மற்றும் fetchTotalBytes உடன்), அல்லது வீடியோவிலிருந்து ஆடியோ எடுக்கப்படும்போது extracting. progress.phasePct அந்தக் கட்டத்தில் பணி எவ்வளவு தூரம் சென்றுள்ளது என்று சொல்கிறது. நீண்ட வீடியோக்களுக்கு நேரம் ஆகும்; எனவே சில வினாடிகளுக்கு ஒருமுறை வாக்களியுங்கள். இதற்கு vs.jobs.wait intervalMs (Python-இல் interval_s) எடுக்கும்.
const probe = await vs.transcriptions.probe(url);
if (!probe.ok) throw new Error(`that link did not open: ${probe.problem}`);
if (probe.kind === 'live') throw new Error('a live link: record it with a live transcription instead');
const linkKey = crypto.randomUUID();
const tx = await vs.transcriptions.createFromUrl(url, { name: 'From a link' }, { idempotencyKey: linkKey });
const job = await vs.jobs.wait(tx.job!.recordingId, {
intervalMs: 3000,
onProgress: (j) => {
const p = j.progress;
if (j.state === 'fetching') console.log(`${p.phase ?? 'fetching'} ${p.phasePct ?? 0}%`);
else console.log(`${j.state} ${p.pct}%`);
},
});
குறிப்பேட்டின் இணைப்பை டிரான்ஸ்கிரிப்ட் செய்தல் வழிகாட்டியில் இரண்டு மொழிகளிலும், HTTP-யிலும் முழு நிரல் உள்ளது. இணைப்புகளிலிருந்து பெறுவது கூடுதல் தோல்விக்கான வழிகளைச் சேர்க்கிறது, எனவே நீங்கள் உண்மையில் சந்திக்கும் பிழைகள் இங்கே.
ஒவ்வொரு தோல்வியுற்ற அழைப்பும் ஒரே JSON உறையுடன் (envelope) பதிலளிக்கும். கிளை பிரிக்க வேண்டிய சரமாக code இருக்கும், HTTP நிலை status. message மனிதர்களுக்கானது, requestId ஆதரவுக்கு. data-இன் கீழ் retryable அதே கோரிக்கையை மீண்டும் அனுப்புவது உதவுமா என்று சொல்லும், details குறியீட்டுக்குத் தேவையானவற்றைக் கொண்டிருக்கும். SDK-கள் VocalStackError என்ற ஒரே பிழை வகையை எறியும், அதே புலங்களுடன்.
முதல் நாளிலிருந்தே கையாள வேண்டிய மூன்று குறியீடுகள் உள்ளன.
402 insufficient_credit: கணக்கின் கிரெடிட் தீர்ந்துவிட்டது, எதுவும் வசூலிக்கப்படவில்லை. details.balance டாலரில் இருப்பு, details.topUpUrl கிரெடிட் சேர்க்க வேண்டிய இடம். செலவு முன்கூட்டியே தெரிந்திருக்கும்போது, உதாரணமாக கால அளவு தெரிந்த ஒரு கோப்புக்கு, details.required அது எவ்வளவு ஆகியிருக்கும் என்று சொல்லும்.429 rate_limited: Retry-After வினாடிகள் காத்திருங்கள். details.metric creates_per_hour ஆக இருந்தால், நீங்கள் திட்டத்தின் உருவாக்க விகிதத்தை (ஒரு மணி நேரத்துக்குப் புதிய டிரான்ஸ்கிரிப்ஷன்கள்) எட்டியுள்ளீர்கள், திடீர் அதிகரிப்பு வரம்பை அல்ல; limit மற்றும் resetsAt வரம்பு என்ன, அது எப்போது விடுபடும் என்று சொல்லும்.503 unavailable: சேவை சிறிது நேரம் கிடைக்கவில்லை. Retry-After-க்குப் பிறகு கோரிக்கையை மீண்டும் அனுப்புங்கள்.SDK-கள் 429 மற்றும் 503-ஐ Retry-After-க்குப் பிறகு, இயல்பாக இரண்டு முறை மீண்டும் முயல்கின்றன (கிளையண்டில் maxRetries / max_retries). ஆனால் 503 பாதுகாப்பாக இரண்டு முறை அனுப்பக்கூடிய அழைப்பில் மட்டுமே மீண்டும் முயலப்படுகிறது: ஒரு GET, அல்லது Idempotency-Key-உடன் ஒரு create. சாவி இல்லாத create உங்களுக்கே விடப்படுகிறது, ஏனெனில் முதல் முயற்சி வெற்றி பெற்றதா என்று SDK-க்குத் தெரியாது. ஒவ்வொரு பதிவேற்றத்திலும் ஒரு சாவி வைப்பதற்கான நடைமுறைக் காரணம் இதுதான்.
ஒவ்வொரு பதிலும் RateLimit-Limit, RateLimit-Remaining மற்றும் RateLimit-Reset தலைப்புகளையும் கொண்டுள்ளது; எனவே பரபரப்பான பைப்லைன் 429-க்கு முன்பே வேகத்தைக் குறைக்கலாம்.
{
"code": "insufficient_credit",
"status": 402,
"message": "this account has no credit left; add credit to continue",
"data": {
"retryable": false,
"details": { "balance": -0.42, "required": 0.075, "currency": "usd", "plan": "payg", "topUpUrl": "https://…" }
},
"requestId": "01J…"
}
முழுக் குறியீட்டு அட்டவணை பிழைகள், மறுமுயற்சிகள் மற்றும் வரம்புகள் பக்கத்தில் உள்ளது. அந்த 402தான் பணத்துடன் தொடர்புடைய ஒரே பிழை; எனவே ஒரு கோப்புக்கு எவ்வளவு ஆகும் என்று பார்ப்போம்.
கோப்புகளுக்கு ஒரு மணி நேர ஆடியோவுக்கு $0.20, வினாடி வாரியாகக் கணக்கிடப்படும் ($0.0033 ஒரு நிமிடத்துக்கு), குறைந்தபட்சம் 5 நிமிடங்கள்: 30 நிமிட கோப்புக்கு $0.10 ஆகும். அது பத்து சென்ட்; முன்னேற்றப் பட்டி நிரம்பும்போது நீங்கள் குடிக்கும் காபியை விட மலிவானது. விகிதம் எல்லாத் திட்டங்களுக்கும் ஒன்றுதான், டாஷ்போர்டில் உள்ளதைப் போலவே API மூலமும் அதே. புதிய கணக்கு ஒரு முறை $5 பதிவு கிரெடிட்டுடன் தொடங்கும், அட்டை தேவையில்லை.
இந்த டுடோரியலைப் பாதிக்கும் மூன்று திட்ட வரம்புகள்.
GET /v1/realtime/capabilities limits.maxUploadBytes ஆகக் காட்டும். இரண்டில் சிறியது பொருந்தும்; அதைவிடப் பெரிய கோப்பு எதுவும் டிரான்ஸ்கிரைப் ஆகும் முன்பே 413 உடன் மறுக்கப்படும். நீண்ட பதிவுக்கு, WAV-ஐ விட ஒரு சுருக்கப்பட்ட மோனோ கோப்பைப் பதிவேற்றுவதற்கு இதுவும் ஒரு காரணம்.GET /v1/billing உங்கள் திட்டம், இருப்பு மற்றும் வரம்புகளை எப்போதும் காட்டும்; முழு அட்டவணை விலைப் பக்கத்தில் உள்ளது.
இனி அடுத்த படிகள்: நீங்கள் ஒரு கோப்பு முடியக் காத்திருக்க முடியாதபோது ஆடியோவை நேரடியாக ஸ்ட்ரீம் செய்தல், அல்லது AI முகவரை இணைத்தல் அதே கணக்குடன் MCP சேவையகம் வழியாக; அப்போது அது மேலே உள்ள எந்தக் குறியீடும் இல்லாமலேயே டிரான்ஸ்கிரைப் செய்து தேடும்.