अपलोडले ट्रान्सक्रिप्ट होइन, कार्य (job) फर्काउँछ। हरेक सिर्जना अनुरोधमा Idempotency-Key राख्नुहोस्, ताकि पुनः प्रयासले दोस्रो ट्रान्सक्रिप्सन बनाउन वा बिल गर्न नसकोस्; त्यसपछि कार्य पूरा नहुन्जेल जाँच गर्नुहोस्, र उही id बाट वाक्य, शब्द वा निर्यात पढ्नुहोस्।
फाइल ट्रान्सक्रिप्सन VocalStack API ले गर्ने सबैभन्दा सरल कार्य हो, र यसको संरचना जुनसुकै असिङ्क्रोनस कार्यजस्तै हो: अपलोड गर्नुहोस्, पर्खनुहोस्, पढ्नुहोस्। अपलोडले तुरुन्तै एउटा ट्रान्सक्रिप्सन र त्यसको कार्य फर्काउँछ, तर अहिलेसम्म कुनै शब्द हुँदैन। तपाईंको प्रोग्रामले कार्यलाई जाँच गरिरहँदा, सर्भरले फाइललाई अडियो चल्ने गतिभन्दा धेरै गुणा छिटो ट्रान्सक्रिप्ट गर्छ। स्थिति done भएपछि, तपाईंले ट्रान्सक्रिप्ट वक्ता र समयसहित वाक्यका रूपमा पढ्न सक्नुहुन्छ, वा बोलिएको भाषामा वा अनुवाद गरिएको रूपमा, चार ढाँचामध्ये कुनै एकमा फाइल निर्यात गर्न सक्नुहुन्छ।
जुनसुकै ब्याच API मा यो संरचना लागू हुन्छ: id फर्काउने सिर्जना, तपाईंले जाँच गर्ने स्थिति, र पछि लिने नतिजा। फिल्डका नाम मात्र VocalStack का लागि विशेष हुन्, र यस ट्युटोरियलमा TypeScript र Python SDK का साथै आवश्यक ठाउँमा HTTP कलहरू पनि देखाइएका छन्।
ड्यासबोर्डमा Developers → API keys खोल्नुहोस् र Read र Write अनुमतिसहित कुञ्जी बनाउनुहोस्। कुञ्जी एक पटक मात्र देखिन्छ; त्यसलाई वातावरण चरमा (environment variable) कपी गर्नुहोस्:
export VOCALSTACK_API_KEY="<your API key>"
कुञ्जी सर्भर र स्क्रिप्टका लागि हो। ब्राउजरमा पठाइने कुनै पनि कुरासँगै कुञ्जी पनि पठाइन्छ, त्यसैले यसलाई पेज कोड र URL बाहिर राख्नुहोस्, किनभने URL हरू लगमा पुग्छन्। ब्राउजरबाट स्ट्रिम गर्न, तपाईंको सर्भरले त्यसका लागि realtime सत्र बनाउँछ; त्यो अर्को ट्युटोरियल हो।
हरेक कलले कुञ्जीलाई 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 सन्दर्भको quickstart को 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 mono मा काम गर्छ र सबै कुरा आइपुग्दा त्यसमै रूपान्तरण हुन्छ। एक जना मानिसको कुराकानी भएको 48 kHz stereo WAV ले आफ्ना अधिकांश बाइट मौनताको उच्च गुणस्तरको वर्णनमा खर्च गर्छ। त्यही कुराको 64 kbps mono MP3 वा Opus फाइलजत्तिकै राम्रोसँग ट्रान्सक्रिप्ट हुन्छ, तर त्यो लगभग बीस गुणा ठूलो हुन्छ, र अपलोड पनि बीस गुणा लामो लाग्छ। अपलोड अघि रूपान्तरण गर्नुहुन्छ भने, mono र मध्यम बिटरेट मात्र बदल्न लायक दुई सेटिङ हुन्।
हरेक अपलोडसँग Idempotency-Key पठाउनुहोस्, र किन भन्ने बुझ्नुहोस्। नेटवर्क टाइमआउटले सर्भरले के गर्यो भन्ने कुरा बताउँदैन: सर्भरले अनुरोध कहिल्यै नदेखेको हुन सक्छ, वा फाइल भण्डारण गरेर कार्य लाइनमा राखिसकेको हुन सक्छ, र जवाब हराएको हुन सक्छ। अन्धाधुन्ध पुनः प्रयासले दोस्रो ट्रान्सक्रिप्सन र दोस्रो शुल्कको जोखिम बोक्छ। कुञ्जीले त्यो रोक्छ। एउटै कुञ्जी र एउटै बडीसहित 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 हो, जसको अर्थ कार्य कुन रेकर्डिङको कुन भाग ट्रान्सक्रिप्ट गर्ने भनेर कसैले छान्नुपर्ने अवस्थामा रोकिएको हो, जस्तै ड्यासबोर्डको ट्रिम चरणमा हुन्छ। सामान्य अपलोड कहिल्यै यो अवस्थामा जाँदैन, यद्यपि jobs.wait ले यहाँ पुग्दा पनि फर्कन्छ। स्थिति done वा failed नहुन्जेल GET /v1/recordings/{id}/job पढ्नुहोस्।
वेबहुक छैनन्, र त्यो जानीजानी गरिएको व्यापार हो। वेबहुकलाई तपाईंको तर्फ सार्वजनिक HTTPS अन्त्यबिन्दु, अरूले त्यसलाई कल गर्न नसकून् भनी हस्ताक्षर जाँच, र तपाईंको अन्त्यबिन्दु बन्द हुँदा प्रयास गर्ने नियम चाहिन्छ। एक मिनेट लाग्ने कार्यका लागि त्यो धेरै झन्झट हो। पोलिङलाई त्यो कुनै चाहिँदैन। तपाईंको स्क्रिप्टले हरेक दुई सेकेन्डमा "भयो?" भनेर सोध्छ, जस्तै पछाडिको सिटमा बसेको बच्चा; तर बच्चाको विपरीत, यसले प्रतिशत पनि पाउँछ।
पहिले नै खुला रहेको वेब पृष्ठले ट्रान्सक्रिप्सनको events सकेट (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 मा त्रुटि फाल्दैन; कार्य फर्काउँछ र जाँच तपाईंले गर्नुपर्छ, भन्ने कुरा ध्यान दिनुहोस्। भाषण (talk) का लागि दुई सेकेन्ड ठीक छ। तीन घण्टाको रेकर्डिङ वा सयौँको ब्याचका लागि, अन्तराल (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 लाई चिन्नु उपयोगी छ, किनभने लगभग हरेक प्लेयरले यो सबटाइटल ढाँचा स्वीकार गर्छ, र यो सादा पाठ हो। फाइल खाली पंक्तिले छुट्याइएका क्युहरूको सूची हो, र प्रत्येक क्युमा गणक, समय दायरा र पाठ हुन्छन्। समयमा मिलिसेकेन्ड अगाडि अल्पविराम प्रयोग हुन्छ, जुन फ्रान्सेली बानी हो र यो ढाँचाले कहिल्यै छोडेन:
1
00:00:01,000 --> 00:00:04,200
Welcome, everyone. Let's get started.
एक क्युमा एक वाक्य सबैभन्दा राम्रो आकार हो: प्रत्येक क्यु स्क्रिनमा हुँदा पढ्न सकिन्छ, र कुनै पनि विचारको बीचमा काटिँदैन। रेकर्डिङमा वक्ता लेबल भएको थियो भने, हरेक क्युको पाठ वक्ताको नाम र कोलनबाट सुरु हुन्छ।
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 हो, तर बहु-भाग अपलोडको सट्टा JSON बडी { "url": "..." } सहित, र 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 ले एक वाक्यमा कारण बताउँछ। प्रोब वैकल्पिक हो, र प्रति मिनेट 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}%`);
},
});
API सन्दर्भको Transcribe a link गाइडमा दुवै भाषा र HTTP मा पूरा प्रोग्राम छ। लिङ्क तान्दा थप असफलताका तरिका थपिन्छन्, त्यसैले यहाँ तपाईंले वास्तवमा देख्ने त्रुटिहरू छन्।
हरेक असफल कलले एउटा JSON लिफाफा फर्काउँछ। code शाखा लिन प्रयोग हुने स्ट्रिङ हो, र status HTTP स्थिति हो; 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 भएको सिर्जना। कुञ्जी बिनाको सिर्जना तपाईंको जिम्मामा छोडिन्छ, किनभने 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…"
}
सबै कोडको पूरा तालिका Errors, retries and limits मा छ। त्यो 402 मात्र पैसासँग जोडिएको त्रुटि हो, त्यसैले फाइलको लागत यहाँ छ।
फाइलहरू $0.20 प्रति घण्टा अडियोमा बिल हुन्छन्, प्रति सेकेन्ड ($0.0033 प्रति मिनेट) गणना गरिएर, न्यूनतम 5 मिनेटसहित: 30 मिनेटको फाइलको लागत $0.10 हो। त्यो दस सेन्ट हो, प्रगति पट्टी भरिँदा तपाईंले पिउने चियाभन्दा पनि कम। दर हरेक योजनामा उही हो, र API मार्फत पनि ड्यासबोर्डमा जस्तै हो। नयाँ खाता एकपटक $5 साइनअप क्रेडिटबाट सुरु हुन्छ, र कार्ड चाहिँदैन।
यस ट्युटोरियलमा तीनवटा योजना सीमा छन्।
GET /v1/realtime/capabilities ले limits.maxUploadBytes को रूपमा रिपोर्ट गर्छ। दुईमध्ये सानो लागू हुन्छ, र त्यो भन्दा ठूलो फाइल कुनै पनि ट्रान्सक्रिप्सन अघि 413 सहित अस्वीकार गरिन्छ। लामो रेकर्डिङका लागि, WAV भन्दा कम्प्रेस गरिएको mono फाइल अपलोड गर्नुको अर्को कारण यही हो।GET /v1/billing ले जुनसुकै बेला तपाईंको योजना, ब्यालेन्स र सीमाहरू देखाउँछ; पूरा तालिका मूल्य पृष्ठ मा छ।
यसपछिको चरण भनेको फाइल पूरा नहुँदै अडियो वास्तविक समयमा स्ट्रिम गर्ने हो, वा AI एजेन्ट जोड्ने काम हो, जसले त्यही खातालाई MCP सर्भर मार्फत जोड्छ, ताकि माथिको कोड नलेखिकन पनि त्यसले तपाईंका लागि ट्रान्सक्रिप्ट र खोज गरिदिन्छ।