چیتشیت
دستیارهای صوتی بیدرنگ (Real-Time)
Real-Time Voice Assistants
VAD، تشخیص نوبت مکالمه، ورود ناگهانی به کلام (barge-in)، سقف تاخیر و گفتار تمامدوطرفه برای ایجنت صوتی با پاسخدهی بهموقع.
فهرست مطالب
پایپلاین صوتی آبشاری
معماریاسکژولر پروژه نهایی، یک نوبت گفتوگو
گامبهگام- IDLEاولین فریم گفتار وضعیت را به LISTENING میبرد.
- LISTENINGهر فریم سکوت 20 ms به
silenceRunMsاضافه میکند. - LISTENINGدر 500 ms سکوت،
turnCompletionScoreآخرین متن ناقص را میخواند. - WAITINGامتیاز 0.6 یا بیشتر نوبت را commit میکند و
turnCompleteMsرا تنظیم میکند. - THINKINGفراخوانی ابزار اجرا میشود. در 300 ms ایجنت میگوید: «یک لحظه، بگذارید بررسی کنم».
- THINKINGابزار در 420 ms برمیگردد. اولین توکن LLM حدود 140 ms بعد میرسد.
- SPEAKINGاولین صوت خروجی 180 ms پس از اولین توکن LLM صادر میشود.
- Barge-inگفتار حین THINKING یا SPEAKING باعث لغو TTS و فعالسازی مجدد ASR میشود.
سقف تاخیر در هر نوبت گفتوگو
پیشفرضها| تنظیم | پیشفرض | نکته |
|---|---|---|
Mic to buffer | 20 ms | یک فریم |
VAD | 10 ms | اجرای Silero زیر 1 ms در هر فریم |
ASR (streaming) | 150 ms | رونویسیهای ناقص |
LLM (first token) | 100 ms | استریم توکنها |
TTS (first chunk) | 100 ms | شروع قبل از تکمیل کل پاسخ |
Render to speaker | 20 ms | یک فریم |
Total | ~400 ms | بالای 500 ms حس رباتیک ایجاد میکند |
First TTS audio, laptop CPU | 800 ms | هدف پروژه نهایی فاز 6 |
تنظیمات VAD و نوبت مکالمه
پیشفرضها| تنظیم | پیشفرض | نکته |
|---|---|---|
Silero threshold | 0.5 | مقدار 0.3 حساس است؛ برش خوردن کلمه اول کمتر میشود |
Minimum speech | 250 ms | حذف صدای سرفه و جابهجایی صندلی |
Silence hangover | 500-800 ms | مقدار خیلی کم کلام کاربر را قطع میکند |
Pre-roll buffer | 300-500 ms | کلمه اول را حفظ میکند |
Energy gate | -40 dBFS | با هر نویزی بالاتر از آن فعال میشود |
Frame size | 20 ms | 320 نمونه در 16 kHz |
Ring buffer | 32,000 samples | 2 s در 16 kHz |
Turn commit (capstone) | 0.6 | بهعلاوه 500ms سکوت VAD |
بخشهای Silero VAD
کدpython
from silero_vad import load_silero_vad, get_speech_timestamps
vad = load_silero_vad()
audio = torch.tensor(waveform_16k, dtype=torch.float32)
segments = get_speech_timestamps(
audio, vad, sampling_rate=16000,
threshold=0.5, # 0.3 حساس است
min_speech_duration_ms=250, # سرفهها را حذف میکند
min_silence_duration_ms=500, # مهلت سکوت
speech_pad_ms=300, # پد بافر پیش از کلام
)
for s in segments:
print(f"{s['start']/16000:.2f}s - {s['end']/16000:.2f}s")
ورود ناگهانی به کلام (barge-in) و ترفند تخلیه
کدpython
tts_task = asyncio.create_task(tts_loop())
while True:
chunk = await mic.get()
if vad(chunk): # کاربر حین پخش TTS صحبت میکند
tts_task.cancel() # توقف پاسخ
await speaker.stop()
await new_turn() # راهاندازی مجدد STT
break
def flush_on_end(stt_client, audio_buffer):
stt_client.send_audio(audio_buffer)
stt_client.send_flush() # اجبار به خروجی فوری
return stt_client.recv_transcript(timeout_ms=150)
اجرای درسها
دستورها| دستور | کارکرد |
|---|---|
python3 code/main.py | اجرای شبیهساز یک درس |
python main.py | اسکژولر پروژه نهایی، تماسهای عادی و barge-in |
pip install silero-vad | استفاده از VAD واقعی به جای استاب |
npm install | نصب کلاینت TypeScript |
npm start | دو نشست آفلاین و یک آزمون ارزیابی ws، خروج با 0 |
npm start -- --serve | روشن نگه داشتن سرور ws |
npm test | اجراکننده node --test از طریق tsx |
npm run typecheck | اجرای tsc --noEmit |
اصطلاحات کلیدی
مفهومها- Ring buffer
- بافر حلقوی ثابت؛ بدون تخصیص حافظه در مسیر اجرای سریع (hot path).
- Jitter buffer
- مرتبسازی مجدد بستههای دیرهنگام؛ خیلی کوچک باعث بریدگی صوتی و خیلی بزرگ باعث تاخیر میشود.
- Pre-roll
- بافر پیش از کلام برای نگهداری صوت قبل از فعالشدن VAD؛ مانع از بریدهشدن ابتدای کلمه اول میشود.
- Silence hangover
- مهلت سکوت؛ مدت انتظار پس از بازگشت VAD به 0، پیش از پایان نوبت.
- Semantic endpoint
- کلاسیفایری که علاوهبر سکوت، کلمات اداشده را نیز بررسی میکند.
- Flush trick
- ترفند تخلیه STT در پایان گفتار؛ 500 ms پیشنگری به حدود ~125 ms کاهش مییابد.
- Filler
- عبارت پرکننده کوتاه هنگام طول کشیدن ابزار بیش از 300ms.
- DOWNSTREAM
- فریمهای Pipecat از مبدا به مقصد؛ ورودی صدا و خروجی گفتار.
- UPSTREAM
- فریمهای کنترلی Pipecat؛ شامل لغو، معیارها و barge-in.
مدل تمامدوطرفه Moshi، یک گام 80 ms
گامبهگام- Mimiانکود صوت کاربر در 12.5 Hz با 8 کتاب کد.
- Temporal Transformerمدل 7B پارامتری؛ خواندن توکنهای کاربر و آخرین توکنهای خود مدل.
- Temporal Transformerتولید توکن متنی بعدی، همان تکگویی درونی.
- Depth Transformerدارای 2 لایه؛ پیشبینی متوالی 8 کتاب کد، یکی پس از دیگری.
- Clientتابع
decode_audio_mimiتوکنها را به صوت تبدیل و پخش میکند. - Budgetفریم 80 ms بهعلاوه 80 ms تاخیر آکوستیک برابر 160 ms است؛ 200 ms روی یک پردازنده L4 GPU.
عیبیابی
عیبیابیکلمه اول جا میافتد
- علت
- شروع VAD با کمی تاخیر
- راهحل
- آستانه 0.3 و بافر پیش از کلام (pre-roll)
ایجنت روی کلام کاربر صحبت میکند
- علت
- ادامه کار LLM بعد از وقفه
- راهحل
- اتصال مستقیم VAD به لغو اجرای LLM
شنیدن «Thanks for watching» روی سکوت
- علت
- اجرای Whisper روی فریمهای سکوت
- راهحل
- اعمال همیشگی گیت VAD
ASR صدای خود ربات را میشنود
- علت
- عدم حذف اکو
- راهحل
- WebRTC AEC3
ایجنت کلام کاربر را اواسط جمله قطع میکند
- علت
- مهلت سکوت (hangover) بسیار کوتاه است
- راهحل
- تنظیم روی 500-800 ms همراه تشخیصدهنده نوبت مکالمه
پاسخ اول کند است
- علت
- آمادهسازی اولیه (warm-up) مدل TTS در اولین درخواست
- راهحل
- پیشگرم کردن با یک اجرای تستی (dummy run)
دستسازههای صوتی ووکوودر شنیده میشود
- علت
- چانکهای TTS زیر 200 ms
- راهحل
- استفاده از چانکهای 320 ms
قطعی و بریدگی صدا زیر بار پردازشی
- علت
- انسداد ترد صدا توسط GIL
- راهحل
- کتابخانه صوتی مبتنی بر C-callback
واژهنامه
اصطلاحها- AEC
- حذف اکو؛ حذف صدای بلندگو از ورودی میکروفون.
- TPR @ 5% FPR
- معیار ارزیابی VAD؛ مدل Silero حدود 87.7% و WebRTC VAD حدود 50.0%.
- MultimodalAgent
- کلاس LiveKit؛ ورودی صوت، خروجی صوت، بدون متن در میانه مسیر.
- VoicePipelineAgent
- کلاس LiveKit؛ اجرای STT، LLM و TTS با کنترل در سطح متن.
پرسش و پاسخ
پرسش و پاسخ- سرعت تعویض نوبت در انسان چقدر است؟
- حدود 230 ms؛ بالاتر از 1500 ms حس خرابی میدهد.
- پایپلاین یا Moshi؟
- برای ابزارها از پایپلاین استفاده کنید؛ Moshi برای فراخوانی ابزار آموزش ندیده است.
- چرا در استریمینگ Whisper ترفند تخلیه کار نمیکند؟
- چون بلوکمحور است و همیشه منتظر چانکها میماند.
- تاخیر سرتاسری تراز اول چقدر است؟
- 450 تا 600 ms؛ بازه 800 تا 1200 ms رایج است.
- معیار قبولی پروژه نهایی چیست؟
- صدک p50 زمان رسیدن اولین صوت زیر 800ms، قطع نابهجا زیر 3%.
- قابلیت barge-in در Pipecat به چه چیزی نیاز دارد؟
- فریمهای لغو UPSTREAM به سمت TTS و LLM.