Спасибо за статью! Интересно было почитать и повспоминать, как сам такое делал.
AEC можно сделать програмно, если в железе оно не предусмотрено. VAD крадёт некоторое время, ожидая окончания фразы - уменьшить можно семантическим и просодическим эндпоинтонгом и небольшой моделью вероятности продолжения/окончания фразы. Для более быстрой реакции робота можно параллелить vad/vosk/sst.
Какое у вас в итоге получается время между окончанием команды и началом звукового ответа/действия?
Про AEC — да, «не будет» я написал слишком категорично. Софтовый AEC вроде WebRTC AEC3 как раз и рассчитан на разные несинхронные устройства. Изначальный блокер у нас был в другом: микрофон сидел на закрытой вендорской плате со своим beamforming и шумодавом, сырого сигнала мы просто не видели. С внешней петличкой сырой поток уже наш, так что путь открыт — просто пока не дошли, обошлись окном по времени.
Про эндпоинтинг — тут вы попали в самое больное место. Мы сейчас просто ждём тишины: 250 мс, чтобы закрыть фразу, и ещё 400 мс на случай, если человек продолжит. Эти 400 мс мы добавили ради одного сценария — диктовки списка «первое… второе…», а платят за них все команды подряд. Итого 0,65 с потерь на каждой фразе. Модель, которая по звуку скажет «фраза закончена» (например, smart-turn v3 — 8M параметров, русский есть), сняла бы обе константы разом. А для команд семантический эндпоинт почти бесплатный: если Vosk с закрытой грамматикой уже уверенно собрал «стой», ждать ещё 650 мс тишины незачем.
Про параллелить — тоже да, сейчас после закрытия фразы всё последовательно: Vosk → whisper → роутер. Vosk можно кормить потоково во время речи, whisper запускать спекулятивно на первой паузе. Это в планах.
Цифры от момента, когда человек замолчал: «секундочку» звучит через ~0,7 с (почти всё это — hangover VAD). Команда через Vosk уходит в мотор-стек примерно через секунду. В диалоге whisper на GPU 0,5–0,9 с, первое предложение от LLM ещё 0,3–2 с, TTS 0,1 с — голосовой ответ начинается через 2,5–5 с. А у вас какие цифры получались?
Я использую gigaam, поэтому время на sst сразу урезается раз в десять по сравнению с whisper. Но мне не нужна мультиязычность. Глянул последние логи: от окончания моего запроса до ответа - около 150мс на простых tool, ещё около 150-300мс если small talk с llm. Это с учетом wakeword, двух гейтов (кто сказал и действительно ли произнесено именно wake). Когда более-менее настроил, то был убеждён, что неправильно меряю время :) Проверил записью команд-ответов со стороны и анализом получившегося аудио - всё сошлось.
dabrahost
Спасибо за статью! Интересно было почитать и повспоминать, как сам такое делал.
AEC можно сделать програмно, если в железе оно не предусмотрено. VAD крадёт некоторое время, ожидая окончания фразы - уменьшить можно семантическим и просодическим эндпоинтонгом и небольшой моделью вероятности продолжения/окончания фразы. Для более быстрой реакции робота можно параллелить vad/vosk/sst.
Какое у вас в итоге получается время между окончанием команды и началом звукового ответа/действия?
anton_yakimov Автор
Спасибо, всё три пункта по делу.
Про AEC — да, «не будет» я написал слишком категорично. Софтовый AEC вроде WebRTC AEC3 как раз и рассчитан на разные несинхронные устройства. Изначальный блокер у нас был в другом: микрофон сидел на закрытой вендорской плате со своим beamforming и шумодавом, сырого сигнала мы просто не видели. С внешней петличкой сырой поток уже наш, так что путь открыт — просто пока не дошли, обошлись окном по времени.
Про эндпоинтинг — тут вы попали в самое больное место. Мы сейчас просто ждём тишины: 250 мс, чтобы закрыть фразу, и ещё 400 мс на случай, если человек продолжит. Эти 400 мс мы добавили ради одного сценария — диктовки списка «первое… второе…», а платят за них все команды подряд. Итого 0,65 с потерь на каждой фразе. Модель, которая по звуку скажет «фраза закончена» (например, smart-turn v3 — 8M параметров, русский есть), сняла бы обе константы разом. А для команд семантический эндпоинт почти бесплатный: если Vosk с закрытой грамматикой уже уверенно собрал «стой», ждать ещё 650 мс тишины незачем.
Про параллелить — тоже да, сейчас после закрытия фразы всё последовательно: Vosk → whisper → роутер. Vosk можно кормить потоково во время речи, whisper запускать спекулятивно на первой паузе. Это в планах.
Цифры от момента, когда человек замолчал: «секундочку» звучит через ~0,7 с (почти всё это — hangover VAD). Команда через Vosk уходит в мотор-стек примерно через секунду. В диалоге whisper на GPU 0,5–0,9 с, первое предложение от LLM ещё 0,3–2 с, TTS 0,1 с — голосовой ответ начинается через 2,5–5 с. А у вас какие цифры получались?
dabrahost
Я использую gigaam, поэтому время на sst сразу урезается раз в десять по сравнению с whisper. Но мне не нужна мультиязычность. Глянул последние логи: от окончания моего запроса до ответа - около 150мс на простых tool, ещё около 150-300мс если small talk с llm. Это с учетом wakeword, двух гейтов (кто сказал и действительно ли произнесено именно wake). Когда более-менее настроил, то был убеждён, что неправильно меряю время :) Проверил записью команд-ответов со стороны и анализом получившегося аудио - всё сошлось.