Phát hiện wake word: thiết bị thông minh luôn ở sẵn sàng nghe
Góc nhìn thực tế về wake word cục bộ trên ESP32-S3: chia frame âm thanh, microWakeWord, chỉnh ngưỡng, kích hoạt nhầm, công tắc micro và quyền riêng tư.
Chia sẻ

“Luôn lắng nghe” nghe đáng ngại hơn so với cách phần cứng wake word thực sự cần phải hoạt động. Microphone đúng là luôn bật, nhưng thiết bị có thể xử lý từng frame âm thanh ngắn ngay tại chỗ, không lưu bản ghi và bỏ chúng đi nếu mô hình nhỏ không nghe thấy câu đánh thức.
Ranh giới này rất quan trọng. Wake-word detector không phải là speech-to-text và không nên hành xử như một chiếc microphone luôn mở về phía server. Mình xem nó như một cánh cổng tiết kiệm tài nguyên: chỉ trả lời câu hỏi hẹp “âm thanh này có giống wake word không?” trước khi cho phép pipeline giọng nói nặng hơn chạy.
Trong bài này, mình sử dụng framework Apache-2.0 dùng để train model TensorFlow Lite Micro cho thiết bị hạn chế tài nguyên. ESPHome đã triển khai runtime chạy trực tiếp trên thiết bị, nên đây là điểm tham khảo khá thực tế cho một bản ESP32-S3.
Phần nào thực sự “lắng nghe”?
Vòng lặp bình thường diễn ra như sau:
- Microphone I2S tạo luồng PCM liên tục.
- Firmware chia luồng thành các frame ngắn có chồng lấn, rồi trích xuất đặc trưng phổ gọn hơn.
- Voice Activity Detection (VAD) có thể bỏ những frame không giống giọng nói.
- Mô hình wake word trả về xác suất cho mỗi cửa sổ mới.
- Firmware làm mượt vài kết quả liên tiếp rồi so với ngưỡng.
- Dưới ngưỡng thì audio bị ghi đè; vượt ngưỡng thì thiết bị bật đèn báo và bắt đầu thu câu lệnh.
Nhánh đầu tiên không tạo transcript. Với thiết bị ưu tiên riêng tư, cả frame thô lẫn đặc trưng âm thanh đều không rời khỏi vỏ máy trước khi phát hiện wake word.
Luồng luôn chạy nằm hoàn toàn trên thiết bị. Chỉ khi xác nhận wake word, nhánh thu câu lệnh mới được mở.
Cấu hình ESP32-S3 đủ dùng để bắt đầu
Mình sẽ bắt đầu bằng board ESP32-S3 có PSRAM, microphone MEMS I2S, amplifier nhỏ cùng loa nếu thiết bị cần trả lời và một công tắc vật lý cắt nguồn microphone. Công tắc không nên chỉ đổi một biến trong phần mềm; khi nhìn vào thiết bị, bạn phải biết microphone thật sự không thể hoạt động.
Phần wake word trong ESPHome khá ngắn:
micro_wake_word:
microphone:
microphone: i2s_mic
channels: 0
gain_factor: 4
vad:
models:
- model: okay_nabu
id: wake_model
probability_cutoff: 97%
sliding_window_size: 5
on_wake_word_detected:
then:
- voice_assistant.start:
wake_word: !lambda return wake_word;
Chân microphone và audio output vẫn phụ thuộc vào từng board. Mình sẽ kiểm tra luồng mono 16 kHz sạch trước, sau đó mới thêm model rồi cuối cùng mới nối voice assistant. Debug I2S, inference, mạng và playback cùng lúc rất dễ khiến lỗi nào cũng trở nên bí hiểm.

Bản thử đầu tiên chỉ cần ESP32-S3, một microphone I2S, loa và công tắc cắt nguồn microphone thật sự.
Chỉnh ngưỡng là đổi kiểu khó chịu
Có hai loại lỗi cần theo dõi:
- False reject: bạn nói wake word nhưng thiết bị không phản ứng.
- False accept: TV, cuộc trò chuyện hoặc tiếng ồn làm thiết bị tự kích hoạt.
Tăng probability_cutoff thường giảm false accept nhưng tăng false reject. sliding_window_size lớn hơn đòi hỏi tín hiệu ổn định lâu hơn, đổi lại có thể tăng độ trễ. VAD giúp bỏ tiếng ồn không phải giọng nói, nhưng không thể ngăn TV nói rõ một cụm gần giống wake word.
Không có con số tốt nhất cho mọi thiết bị. Vị trí microphone, lỗ trên vỏ, tiếng vang trong phòng, âm lượng loa, giọng vùng miền và khoảng cách nói đều làm kết quả thay đổi. Hãy tune trên chiếc vỏ hoàn chỉnh, không phải board trần đặt cách miệng mười centimet.
Hãy test cả căn phòng, đừng chỉ test một file sạch
Bảng test của mình sẽ gồm:
| Bài test | Thông tin cần ghi |
|---|---|
| Nói wake word ở 0,5 m, 2 m và 4 m | Số lần nhận / tổng số lần và thời gian phản hồi |
| Nói nhỏ, nói bình thường, gọi từ phòng bên | False reject theo từng điều kiện |
| Nhiều giờ TV, podcast, nhạc, tiếng bếp và tiếng quạt | False accept mỗi giờ |
| Nhiều người và giọng vùng miền trong nhà | Có ai thường xuyên bị bỏ sót hay không |
| Thiết bị tự phát câu trả lời | Echo có kích hoạt lại detector hay không |
Hãy chạy các bài này với gain, loa, vỏ và vị trí lắp thật. Nếu có thể, log thời điểm sự kiện, điểm model và nhãn bài test thôi. Giữ lại mọi đoạn audio kích hoạt nhầm sẽ tự tạo ra một vấn đề riêng tư mới.

Độ chính xác phụ thuộc căn phòng, nên hãy thử khoảng cách, tiếng TV, nhạc, tiếng ồn và giọng của người dùng thật.
Wake word riêng khó hơn bản demo khá nhiều
Một câu đánh thức tốt cần khác biệt, dễ lặp lại và không xuất hiện thường xuyên trên TV hay trong hội thoại. Với tiếng Việt, mình sẽ thử nhiều cách phát âm vùng miền thay vì cho rằng một giọng tổng hợp đại diện cho tất cả mọi người.
Repo microWakeWord có notebook train cơ bản và công cụ sinh mẫu tổng hợp, nhưng chính tài liệu dự án cũng cảnh báo output của notebook chỉ là điểm bắt đầu. Model dùng được cần positive sample đa dạng, negative dataset lớn, augmentation cho tiếng ồn và vang phòng, cùng bài test trên những giọng không có trong tập train.
Nếu detector chạy trên Linux hoặc Raspberry Pi thay vì vi điều khiển, openWakeWord là một hướng open source khác với model ONNX/TFLite và runtime Python. Mình không cố nhét stack lớn hơn vào ESP32 khi microWakeWord đã được thiết kế đúng cho giới hạn đó.
Lời hứa riêng tư phải nhìn thấy được
Với sản phẩm luôn lắng nghe, mình sẽ đưa các hành vi sau vào specification:
- Trước khi phát hiện, inference chạy tại chỗ và audio không được lưu hay stream.
- LED bật ngay khi bắt đầu thu câu lệnh, không phải đợi đến lúc thiết bị trả lời.
- Nút vật lý cắt nguồn microphone.
- Thiết bị không có endpoint “nghe trực tiếp” bị giấu đi.
- Event log là tùy chọn và mặc định không chứa audio thô.
- Khi timeout, hủy hoặc xử lý xong câu lệnh, phần thu dừng lại và thiết bị quay về detector cục bộ nhỏ.
Model wake word chỉ là một thành phần. Sản phẩm chỉ tạo được niềm tin khi mạch điện, firmware, đèn báo, log và tài liệu cùng kể một câu chuyện giống nhau.
Nguồn tham khảo và nguồn ảnh
- GitHub - microWakeWord
- ESPHome - Micro Wake Word
- GitHub - ESPHome micro wake word models
- GitHub - openWakeWord
- Ảnh cover: the blowup trên Unsplash, đã custom cho bài viết.
- Ảnh phần cứng: Harrison Broadbent trên Unsplash, đã custom cho bài viết.
- Ảnh bàn test: Kit trên Unsplash, đã custom cho bài viết.
Chia sẻ
Tiếp tục khám phá
Đọc tiếp
Bài viết liên quan
TinyML trên ESP32: Chạy AI ngay tại thiết bị
Cách mình chạy một model nhận diện người ngay trên ESP32 bằng TensorFlow Lite Micro và ESP-NN, từ giới hạn bộ nhớ đến cách thử ví dụ person_detection.
Thiết kế audio hai chiều trên ESP32-S3: Microphone I2S và loa I2S
Giải thích các tín hiệu BCLK, WS, DIN, DOUT, full-duplex, sample rate và buffer khi thiết kế audio hai chiều trên ESP32-S3.
Tối ưu thời lượng pin cho robot ESP32 có màn hình
Phân tích thời lượng pin cho robot ESP32 có màn hình: backlight, Wi-Fi, audio, ngoại vi, sleep mode, wake-up và runtime.