نسخ تسجيل مع تسميات المتحدثين
عالج تسجيلًا طويلًا ومكتملًا باستعلام محدود، وتوفيق المتحدثين، وخرج التسميات التوضيحية.
تأخذ هذه الوصفة تسجيلًا مكتملًا واحدًا عبر سير عمل Batch يشبه الإنتاج: الإرسال، والاستعلام حتى حالة نهائية، وتوفيق مقاطع المتحدثين، وكتابة التسميات، والتنظيف في كل مسار.
متى تستخدم هذه الوصفة
استخدم BatchTranscribeClient عندما يكون التسجيل كله موجودًا، خاصة للمواد
الطويلة أو الكبيرة مثل الاجتماعات والبودكاست والمكالمات والأرشيف. تحدّ إعداداتُ
Batch الافتراضية كل طلب بـ 512 ميبيبايت من بايتات الطلب و4 ساعات من الصوت
المفكوك؛ وللنسخ السريع حدود رفع منفصلة خاصة به. يُقبل الطلب المساوي تمامًا لحدٍّ
مُعَدّ ولا يُرفض إلا الطلب الذي يتجاوزه، لكن الحدود المنشورة قد تكون أدنى من هذه
القيم الافتراضية، لذا اختبر مواد تمثل استخدامك. لا يحدد API الدفعي مدة احتفاظ
بالنتيجة، لذا اجلب النتائج بسرعة ولا تصمم اعتمادًا على نافذة احتفاظ غير موثقة.
| حالة الصوت | اختر | السبب |
|---|---|---|
| تسجيل طويل ومكتمل | النسخ الدفعي | ارفع مرة واحدة واستعلم عن دورة حياة العمل |
| وحدة مكتملة وقصيرة وحساسة لزمن الوصول، مثل دور في محادثة وكيل | النسخ السريع | أرسل الحمولة المكتملة عبر Socket.IO لزمن وصول أقل |
| ما زال الصوت يصل | النسخ الفوري | أرسل مقاطع PCM وتعامل مع النتائج المؤقتة والنهائية |
النسخ السريع ليس مسار المواد الطويلة. استخدم Batch لسير عمل الاجتماع أو البودكاست أو الأرشيف هذا.
المتطلبات المسبقة
- تثبيت
@humain-voice/sdk@0.18.0أوhumain-voice==0.18.0. API_KEYالذي تحصل عليه عبر مسار الوصول في مؤسستك وAPI_URLالمعروض للبيئة. لا يستخدم Batch API_PATH؛ ويستخدم عملاء Socket.IO المسار/socket.ioافتراضيًا.- ملف صوت مكتمل ومدعوم. تستخدم البرامج المختبرة
meeting.wavافتراضيًا وتكتبmeeting.vtt. - بيئة JavaScript على الخادم أو Python 3.10 أو أحدث. يستخدم مثال الاستعلام
المباشر في Python حزمة
httpxأيضًا. - مجلد خرج قابل للكتابة ومهلة تطبيق تناسب التسجيل وبيئة العامل.
تختار البرامج المختبرة Language.ArEn مع
BatchTranscriptionModel.BayanArEn. غيّر اللغة والنموذج معًا إذا احتاج
تسجيلك تركيبة أخرى مدعومة.
1. شغّل مسار SDK المختبر
اختر برنامجًا واحفظه باسم الملف المعروض. يفعّل البرنامجان التمييز، ويستعلمان كل ثانيتين مع حد لحلقة الاستعلام قدره 300 ثانية، ويطبعان النص المعاد، ويكتبان WebVTT نهائية، ويغلقان العميل أثناء التنظيف. قد يمدد الإرسال أو طلب قيد التنفيذ المدة الفعلية.
import { readFile, writeFile } from 'node:fs/promises';
import {
BatchDiarization,
BatchTranscribeClient,
BatchTranscriptionModel,
Language,
Subtitles,
} from '@humain-voice/sdk';
function requiredEnv(name: 'API_KEY' | 'API_URL'): string {
const value = process.env[name];
if (!value) throw new Error(`${name} is required`);
return value;
}
async function main(): Promise<void> {
const inputPath = process.argv[2] ?? 'meeting.wav';
const outputPath = process.argv[3] ?? 'meeting.vtt';
const client = new BatchTranscribeClient({
api_url: requiredEnv('API_URL'),
api_key: requiredEnv('API_KEY'),
api_version: process.env.API_VERSION ?? 'v1',
});
try {
const result = await client.transcribe(
await readFile(inputPath),
Language.ArEn,
{
asr: BatchTranscriptionModel.BayanArEn,
diarization: BatchDiarization.On,
saveResult: true,
pollInterval: 2,
timeout: 300,
onProgress: ({ status }) => console.info('status:', status),
},
);
console.info(result.results?.transcript ?? '');
await writeFile(outputPath, Subtitles.fromResponse(result).toVtt(), 'utf8');
} finally {
await client.close();
}
}
void main().catch((error: unknown) => {
console.error(error);
process.exitCode = 1;
});
شغّل البرنامج الذي حفظته:
- JavaScript / TypeScript في بيئة التحقق Node.js 24 للوثائق:
node batch-transcription.ts meeting.wav meeting.vtt - Python:
python batch_transcription.py meeting.wav meeting.vtt
2. تحقق من الآثار المتوقعة
في العمل الناجح:
| الأثر | النتيجة المتوقعة |
|---|---|
| خرج الطرفية | تحديث واحد أو أكثر يبدأ بـstatus:، ثم النص المعاد |
| نتيجة Batch | الحالة النهائية done، مع إزاحات نص مطبعة عند التعرف على كلام |
meeting.vtt | ملف WebVTT نهائي مولد بواسطة Subtitles.fromResponse(result).toVtt() |
| بيانات التمييز | مقاطع المتحدثين المعادة مع شكل النتيجة القديم الذي يستخدمه SDK الصادر |
قد ينتج الصوت الذي لا يحتوي كلامًا متعرفًا عليه نصًا فارغًا. تعامل مع إنشاء
ملف التسميات ووصول العمل إلى done كنجاح معالجة؛ وتحقق من فائدة المحتوى
بشكل منفصل.
ينجح مساعد SDK عند done، ويرفع خطأ عند failed، ويصل إلى مهلته المضبوطة
إذا بقيت المهمة queued أوprocessing أوcleared. لا يعرض cleared فورًا.
استخدم الاستعلام المباشر عندما يجب أن يميز التطبيق هذه الحالة بمجرد ظهورها.
3. قيّد الاستعلام المباشر عبر API
بعد إرسال multipart/form-data إلى POST /v1/transcribe/{lang}، استعلم من
عملية نتيجة V2 الموصى بها: GET /v1/transcribe/{job_id}. تحتاج الحلقة إلى
مهلة لكل طلب ومهلة إجمالية معًا.
// `jobId` is the value returned by the submission request in step 2.
const jobId = process.env.JOB_ID!;
const deadline = Date.now() + 5 * 60_000;
let job;
while (Date.now() < deadline) {
const response = await fetch(`${process.env.API_URL}/v1/transcribe/${jobId}?save_result=true`, {
headers: {
"x-api-key": process.env.API_KEY!,
Origin: process.env.API_URL!,
},
signal: AbortSignal.timeout(10_000),
});
if (!response.ok) throw new Error(`poll failed: HTTP ${response.status}`);
({ data: job } = await response.json());
if (job.status === "done") break;
if (job.status === "failed") {
throw new Error("transcription failed");
}
if (job.status === "cleared") {
throw new Error("transcription result is unavailable (cleared)");
}
await new Promise((resolve) => setTimeout(resolve, 2_000));
}
if (!job || job.status !== "done") throw new Error("poll deadline exceeded");queued وprocessing حالتان غير نهائيتين؛ وdone وfailed وcleared
حالات نهائية. استخدم النتائج عند done فقط، واعرض إخفاق العمل عند failed،
واعتبر النتيجة غير متاحة عند cleared.
تضبط هذه الحلقات save_result=true قبل جلب الحالة النهائية كي يمكن جلب
استجابة done أو failed مجددًا بعد فقدها. قد تمسح القيمة الافتراضية false
الحقول المخزنة بعد بناء تلك الاستجابة. لا يضمن الخيار مدة احتفاظ.
فاصل الثانيتين، ومهلة الطلب البالغة عشر ثوانٍ، والمهلة الإجمالية البالغة خمس
دقائق أعلاه اختيارات للتطبيق وليست ضمانات خدمة. تعامل مع 429 باستخدام
السعة المبلغ عنها وتراجع محدود. لا تعد قراءة النتيجة إلا عندما يحفظها
save_result=true؛ ولا تكرر رفعًا انتهت مهلته بلا تمييز لأنه ربما أنشأ عملًا
بالفعل.
4. وفّق الكلمات والمتحدثين
تفصل استجابة V2 بين final_word_segments وdiarization_segments. تسند
سياسة التطبيق الصريحة التالية الكلمة إلى المقطع الذي يحتوي منتصفها. وعند
غياب تطابق، تحتفظ بـUNKNOWN_SPEAKER.
function speakerFor(word, segments) {
const midpoint = (word.start_time + word.end_time) / 2;
return segments.find(
(segment) =>
segment.start_time <= midpoint && midpoint < segment.end_time,
)?.speaker ?? "UNKNOWN_SPEAKER";
}
const attributed = job.final_word_segments.map((word) => ({
...word,
speaker: speakerFor(word, job.diarization_segments ?? []),
}));مطابقة منتصف النطاق الزمني قاعدة تطبيق وليست ضمان هوية. وثّق سياسة مختلفة لأقرب مقطع أو التداخل إذا اخترتها. تميز تسميات المتحدثين الأدوار؛ ولا تعرّف أشخاصًا حقيقيين.
يمكن لمسار V1 القديم إعادة speaker مباشرة على إزاحات الكلمات عند تفعيل
المحاذاة القسرية. افصل نوعي استجابة V1 وV2 بدل خلط أسماء حقولهما.
5. أنشئ التسميات التوضيحية
يكتب مسار SDK المختبر مسبقًا meeting.vtt من إزاحات الكلمات المطبعة. استخدم
toSrt() بدل toVtt() عندما يتطلب المستهلك SubRip. في عميل V2 مباشر، طبّع
أولًا توقيت الكلمات المعاد إلى شكل دخل عارض التسميات؛ ولا تمرر غلاف V2 إلى
مساعد يتوقع TranscriptionResponse القديمة في SDK الصادر.
نص التسميات والخط الزمني للمتحدثين أثران منفصلان. WebVTT وSRT صيغتا تسميات توضيحية؛ أما RTTM فهي صيغة تمييز.
6. تعامل مع الفشل والتنظيف
| الحالة | إجراء الإنتاج |
|---|---|
| مفتاح مفقود أو غير صالح | توقف وصحح إعداد الخادم؛ ولا تعرض المفتاح في شيفرة العميل أو السجلات |
429 | اقرأ معلومات السعة عند وجودها وطبّق تراجعًا محدودًا مع jitter |
failed | توقف عن الاستعلام واعرض خطأ العمل |
cleared | توقف عن الاستعلام وأبلغ أن النتيجة غير متاحة؛ ولا تستنتج مدة احتفاظ |
| المهلة الإجمالية | أوقف العامل وسجل معرّف المهمة حتى يمكن التحقق من النتيجة |
مهلة رفع بلا jobId | تعامل مع النتيجة كملتبسة؛ ولا ترفع المادة نفسها مجددًا بلا تمييز |
يغلق مثال JavaScript المتحقق منه عميله داخل finally؛ ويستخدم مثال Python
مدير سياق غير متزامن. يستخدم مستعلم Python المباشر مدير سياق متزامن لعميل
HTTP. حافظ على حدود التنظيف هذه عند إضافة التخزين أو الطوابير أو نشر
التسميات.
الخطوات التالية
إذا كان مسار SDK مناسبًا، فأعد تشغيله على تسجيلات تمثل استخدامك واختبر المهل وإعادة المحاولة والتنظيف. وإذا كان العامل يملك الإرسال والاستعلام بشكل منفصل، فتابع إلى عقد Batch REST قبل تنفيذ جانب الرفع.