RealtimeVAD: phát hiện kết thúc câu nói sớm hơn Silero 100ms
Dự án mã nguồn mở RealtimeVAD kết hợp Silero VAD với bộ dò năng lượng 10ms để phát hiện thời điểm người dùng ngừng nói sớm hơn khoảng 100ms so với Silero, đổi lại số lần báo nhầm tăng khoảng 10 lần. Trên 3.279 lượt hội thoại thực tế, tín hiệu kết thúc câu đến sớm hơn ở 82% lượt, giúp giảm độ trễ cho trợ lý giọng nói.

Một lập trình viên vừa công bố RealtimeVAD, thư viện mã nguồn mở giúp phát hiện thời điểm người dùng ngừng nói sớm hơn khoảng 100 ms so với Silero VAD — công cụ phổ biến hiện nay để nhận diện hoạt động giọng nói (VAD — voice activity detection, tức xác định đoạn âm thanh nào là lời nói).
Với trợ lý giọng nói, mọi bước phía sau — nhận dạng giọng nói (ASR), gọi mô hình ngôn ngữ lớn (LLM), phát giọng trả lời — đều phải chờ quyết định "người dùng đã nói xong chưa". Rút ngắn được khoảng chờ này đồng nghĩa trợ lý phản hồi nhanh hơn.
Cách hoạt động
RealtimeVAD vẫn giữ Silero để quyết định đâu là lời nói, nhưng thêm một lớp kiểm tra thứ hai nhanh hơn: cứ mỗi 10 ms nó so sánh mức âm lượng hiện tại với tiếng ồn nền của phòng và với chính mức âm lượng của người nói. Ngay khi âm thanh lắng xuống, sự kiện được phát ra, sớm hơn nhiều so với lúc xác suất của Silero giảm.
Thư viện nhận đầu vào âm thanh mono 16 kHz, chia theo khối kích thước tùy ý (float32, int16 hoặc int16 dạng byte), và trả về ba loại sự kiện:
- start: lời nói đã bắt đầu, sau khoảng 64 ms lời nói đủ chắc chắn để không bị kích hoạt bởi tiếng tách.
- pause: người nói có thể đã dừng, phát ra trong khoảng 10 ms kể từ lúc âm thanh lắng xuống.
- end: đoạn hội thoại kết thúc thật, sau 0,24 giây tính từ lúc lắng xuống, trừ khi lời nói tiếp tục. Không bao giờ muộn hơn Silero chạy riêng.
Ngoài ra còn có sự kiện onset (tắt mặc định), báo hiệu lời nói có thể đã bắt đầu trước khi được xác nhận. Hàm vad.audio() trả về đoạn âm thanh đang chạy bất kỳ lúc nào, bắt đầu từ khoảng 0,3 giây trước khi có lời nói.
Khi trợ lý phát âm thanh trong lúc micro vẫn mở, cần gọi vad.feed(chunk, playback=True) để tiếng của chính nó được xử lý như tiếng vọng. Thư viện chỉ cần numpy và onnxruntime, mô hình Silero được đóng gói sẵn, không cần PyTorch, và chạy trên một luồng CPU với tốc độ nhanh hơn nhiều so với thời gian thực.
Kết quả đo trên 3.279 lượt hội thoại
Tác giả đo trên dữ liệu từ một trợ lý giọng nói đang chạy thực tế, so sánh Silero và RealtimeVAD trên cùng một khung âm thanh (cùng xác suất, cùng đầu vào):
| So với | Sớm hơn (trung vị) | Khoảng p25–p75 | p90 | Sớm hơn ở |
|---|---|---|---|---|
| Silero, xác suất dưới 0,5 | 100 ms | 80–150 ms | 214 ms | 98% |
| Silero, xác suất dưới 0,35 | 110 ms | 90–176 ms | 230 ms | 98% |
| Silero VADIterator end, mặc định 100 ms im lặng | 206 ms | 186–272 ms | 336 ms | 99% |
Cái giá phải trả là dương tính giả: tín hiệu pause cũng phát ra trong những khoảng ngắn giữa các từ, với tần suất khoảng 1,5 lần mỗi giây lời nói — gấp khoảng 10 lần Silero. Có tới 86% lượt không có pause nào với Silero, trong khi con số này với RealtimeVAD là 17%.
pause phát ra sớm và thường sai là có chủ đích. Nó kích hoạt ở mỗi hơi thở, mỗi khoảng ngắn giữa các từ và mỗi phụ âm tắc.
Tác giả khuyến nghị chỉ dùng pause để khởi động những việc có thể hủy: chốt bản ghi nhận dạng, gọi LLM, chuẩn bị giọng trả lời — rồi hủy nếu người dùng nói tiếp. Chỉ sự kiện end mới thực sự đóng một đoạn hội thoại.
Bản 0.0.5: sửa lỗi với người nói nhỏ
Phiên bản 0.0.5 (trạng thái alpha) khắc phục hai vấn đề của các bản trước:
- Ngưỡng im lặng thích ứng theo người nói: trước đây "im lặng" có mức sàn cố định khoảng −54 dBFS, khiến người nói nhỏ (như qua điện thoại) bị cắt giữa lúc đang nói. Giờ mức sàn là giá trị thấp hơn giữa −54 dBFS và mức của người nói trừ 20 dB.
- Đếm lại thời gian im lặng sau tiếng tách: một khối âm thanh lớn 10 ms (tiếng tách, chép miệng, hơi thở) từng làm dừng hẳn bộ đếm im lặng. Lỗi này xảy ra ở một phần ba của 680 lượt lấy mẫu.
Nhờ vậy tín hiệu end đến sớm hơn Silero ở 82% lượt, trung vị 70 ms (trước khi sửa là 51% và 18 ms).
Giới hạn
Tác giả nêu rõ các số liệu trên đến từ một người nói, một chuỗi thu âm — ghi từ trình duyệt có khử ồn và khử vọng, chủ yếu trong phòng yên tĩnh. Lợi thế về độ trễ cần âm thanh thực sự lắng xuống sau mỗi từ, và khử ồn giúp ích cho việc này. Khi tiếng ồn nền chỉ thấp hơn giọng nói khoảng 20 dB thì không còn lợi thế nào — RealtimeVAD kết thúc đúng chỗ Silero kết thúc.
Ngoài ra, thư viện không nhận ra tiếng thì thầm (Silero chấm dưới 0,5) nhưng thường nhận ra tiếng cười, ho, hắt hơi. Đầu vào có độ lệch DC cũng sẽ che mất khoảng lặng. Thư viện chỉ hỗ trợ 16 kHz mono.
Với người đã dùng Silero, việc chuyển sang rất đơn giản: chỉ cần đổi lệnh import của VADIterator, giữ nguyên cách khởi tạo và kết quả trả về. Còn với LiveKit Agents, đã có plugin riêng: so với mặc định của plugin Silero, tín hiệu end đến sớm hơn khoảng 380 ms, nhưng phần lớn là nhờ thời gian im lặng ngắn hơn (0,25 giây thay vì 0,55 giây); ở cùng thiết lập, con số này là 65–110 ms.
Toàn bộ mã nguồn theo giấy phép MIT, có sẵn kịch bản benchmark để chạy trên dữ liệu của riêng bạn.
Góc nhìn
Với các kỹ sư đang xây trợ lý giọng nói hoặc ứng dụng hội thoại thời gian thực, RealtimeVAD đáng chú ý ở chỗ nó không thay thế Silero mà bổ sung một tầng quyết định nhanh hơn lên trên. Ý tưởng cốt lõi — chấp nhận dương tính giả để khởi động sớm công việc có thể hủy — là một mô hình thiết kế đáng học: độ trễ cảm nhận được giảm đáng kể, còn chi phí khi đoán sai gần như bằng không nếu pipeline được xây dựng đúng cách.
Tuy nhiên, một điểm cần lưu ý là các số đo đều đến từ một người nói và một chuỗi thu âm trong phòng tương đối yên tĩnh. Trước khi đưa vào sản phẩm, các nhóm nên chạy kịch bản benchmark có sẵn trên chính dữ liệu và môi trường âm thanh thực tế của mình, đặc biệt nếu người dùng thường gọi từ đường điện thoại hoặc nơi ồn ào — những trường hợp mà theo chính tác giả, lợi thế về độ trễ có thể biến mất hoàn toàn. Việc thiết kế pipeline có thể hủy nhanh (như hủy gọi LLM khi người dùng nói tiếp) cũng là điều kiện tiên quyết để cách tiếp cận này có lợi thay vì phản tác dụng.
Nguồn: github.com · Quy trình biên tập

