Step 1 builds the WebSocket foundation for a low-latency voice conversation system.
/user_data/audio_voice_demo/.venv/bin/python -m uvicorn app.main:app --host 0.0.0.0 --port 8010
Open:
http://localhost:8010/
All runtime audio/control traffic uses one WebSocket endpoint:
ws://localhost:8010/ws/audio
Client to server:
{ "type": "client.ready", "inputSampleRate": 16000 }{ "type": "stop" }Server to client:
server.readyaudio.statsasr.ready, asr.final, asr.ignoredllm.ready, llm.start, llm.delta, llm.say, llm.endtts.ready, tts.start, tts.endImplemented:
/ws/audioImplemented:
input_audiosilero_vad and torch are installedasr_eventsOptional VAD dependencies:
python3 -m pip install -r requirements-vad.txt
For a CUDA GPU environment, install the matching PyTorch build first, then install requirements-vad.txt.
VAD endpoint tuning:
export VAD_END_SILENCE_SECONDS=0.9
export MIN_UTTERANCE_SECONDS=0.45
export ASR_MIN_RMS=0.006
export ASR_MIN_VOICED_RATIO=0.08
Increase VAD_END_SILENCE_SECONDS if normal pauses split one sentence too early.
Increase ASR_MIN_RMS or ASR_MIN_VOICED_RATIO if silence/noise still reaches ASR and causes hallucinated text.
Implemented:
AsrEvent items from VADInstall ASR runtime dependencies:
python3 -m pip install -r requirements-asr.txt
Breeze ASR 25 must be converted to CTranslate2 format outside this app, then exposed at runtime:
export BREEZE_CTRANSLATE2_MODEL=/path/to/breeze-asr-25-ctranslate2
export ASR_DEVICE=cuda
export ASR_COMPUTE_TYPE=float16
export ASR_LANGUAGE=zh
python3 -m uvicorn app.main:app --host 0.0.0.0 --port 8010
Local demo install status:
.venvmodels/breeze-asr-25-ct2models/voxcpm2Not implemented yet:
Implemented:
.venvopenbmb/VoxCPM2 weights downloaded to models/voxcpm2VoxCPM2 and BlueMagpie TTStts_textgenerate_streaming with inference_timesteps=6demo.tts WebSocket control and front-end Test TTS buttonCurrent CUDA smoke test:
tts.ready reports voxcpm2demo.tts receives tts.startdemo.tts first audio chunk arrives in about 0.48sFor the intended low-latency demo, run with:
export ASR_DEVICE=cuda
export ASR_COMPUTE_TYPE=float16
export TTS_DEVICE=cuda
export TTS_INFERENCE_TIMESTEPS=6
export TTS_SEED=20260612
/user_data/audio_voice_demo/.venv/bin/python -m uvicorn app.main:app --host 0.0.0.0 --port 8010
To keep VoxCPM2 voice identity more stable, the backend fixes the TTS random seed by default. For a stronger fixed voice, provide a reference clip:
export TTS_REFERENCE_WAV=/path/to/reference.wav
Optional BlueMagpie install:
python3 -m pip install -r requirements-bluemagpie.txt
export BLUEMAGPIE_MODEL=/user_data/audio_voice_demo/models/bluemagpie-tts
export BLUEMAGPIE_ALLOW_DOWNLOAD=1
export BLUEMAGPIE_VOICE_MODE=centroid
export BLUEMAGPIE_REFERENCE_WAV=/user_data/audio_voice_demo/models/bluemagpie-ref-8s.wav
export BLUEMAGPIE_INFERENCE_TIMESTEPS=10
export BLUEMAGPIE_CFG_VALUE=2.8
export BLUEMAGPIE_MAX_AUDIO_SECONDS=8.0
Use TTS_PROFILE=bluemagpie to make BlueMagpie the startup default, or switch it from the /agent status panel.
The default BLUEMAGPIE_VOICE_MODE=centroid uses the bundled hung_yi_lee speaker centroid because it matches the upstream usage guide more closely than reference-audio cloning.
Or use continuation-style prompting:
export TTS_PROMPT_WAV=/path/to/prompt.wav
export TTS_PROMPT_TEXT="The exact text spoken in the prompt audio."
Not implemented yet:
Implemented:
/v1/chat/completions SSE parser<SAY>...</SAY> and <TOOL_CALL>...</TOOL_CALL><SAY> content into the TTS queue<TOOL_RESULT> events for local testingllm.delta event logging to verify real token streamingDefault local LLM endpoint:
http://127.0.0.1:8011/v1/chat/completions
Recommended Gemma 4 test target:
llama-server \
-m /user_data/audio_voice_demo/models/llm/gemma-4-e4b-it-Q6_K.gguf \
--host 127.0.0.1 \
--port 8011 \
-ngl 99 \
-c 4096 \
--flash-attn
FastAPI reads these environment variables:
export LOCAL_LLM_BASE_URL=http://127.0.0.1:8011/v1
export LOCAL_LLM_MODEL=gemma-4-e4b-it
export LOCAL_LLM_TEMPERATURE=0.45
export LOCAL_LLM_MAX_TOKENS=384
If llama.cpp is not running, the backend emits a short spoken fallback so the rest of the ASR-to-TTS pipeline remains testable.
1 commits
Python
61.9%
JavaScript
21.5%
CSS
7.9%
HTML
5.6%
Shell
3.1%
Step 1 builds the WebSocket foundation for a low-latency voice conversation system.
/user_data/audio_voice_demo/.venv/bin/python -m uvicorn app.main:app --host 0.0.0.0 --port 8010
Open:
http://localhost:8010/
All runtime audio/control traffic uses one WebSocket endpoint:
ws://localhost:8010/ws/audio
Client to server:
{ "type": "client.ready", "inputSampleRate": 16000 }{ "type": "stop" }Server to client:
server.readyaudio.statsasr.ready, asr.final, asr.ignoredllm.ready, llm.start, llm.delta, llm.say, llm.endtts.ready, tts.start, tts.endImplemented:
/ws/audioImplemented:
input_audiosilero_vad and torch are installedasr_eventsOptional VAD dependencies:
python3 -m pip install -r requirements-vad.txt
For a CUDA GPU environment, install the matching PyTorch build first, then install requirements-vad.txt.
VAD endpoint tuning:
export VAD_END_SILENCE_SECONDS=0.9
export MIN_UTTERANCE_SECONDS=0.45
export ASR_MIN_RMS=0.006
export ASR_MIN_VOICED_RATIO=0.08
Increase VAD_END_SILENCE_SECONDS if normal pauses split one sentence too early.
Increase ASR_MIN_RMS or ASR_MIN_VOICED_RATIO if silence/noise still reaches ASR and causes hallucinated text.
Implemented:
AsrEvent items from VADInstall ASR runtime dependencies:
python3 -m pip install -r requirements-asr.txt
Breeze ASR 25 must be converted to CTranslate2 format outside this app, then exposed at runtime:
export BREEZE_CTRANSLATE2_MODEL=/path/to/breeze-asr-25-ctranslate2
export ASR_DEVICE=cuda
export ASR_COMPUTE_TYPE=float16
export ASR_LANGUAGE=zh
python3 -m uvicorn app.main:app --host 0.0.0.0 --port 8010
Local demo install status:
.venvmodels/breeze-asr-25-ct2models/voxcpm2Not implemented yet:
Implemented:
.venvopenbmb/VoxCPM2 weights downloaded to models/voxcpm2VoxCPM2 and BlueMagpie TTStts_textgenerate_streaming with inference_timesteps=6demo.tts WebSocket control and front-end Test TTS buttonCurrent CUDA smoke test:
tts.ready reports voxcpm2demo.tts receives tts.startdemo.tts first audio chunk arrives in about 0.48sFor the intended low-latency demo, run with:
export ASR_DEVICE=cuda
export ASR_COMPUTE_TYPE=float16
export TTS_DEVICE=cuda
export TTS_INFERENCE_TIMESTEPS=6
export TTS_SEED=20260612
/user_data/audio_voice_demo/.venv/bin/python -m uvicorn app.main:app --host 0.0.0.0 --port 8010
To keep VoxCPM2 voice identity more stable, the backend fixes the TTS random seed by default. For a stronger fixed voice, provide a reference clip:
export TTS_REFERENCE_WAV=/path/to/reference.wav
Optional BlueMagpie install:
python3 -m pip install -r requirements-bluemagpie.txt
export BLUEMAGPIE_MODEL=/user_data/audio_voice_demo/models/bluemagpie-tts
export BLUEMAGPIE_ALLOW_DOWNLOAD=1
export BLUEMAGPIE_VOICE_MODE=centroid
export BLUEMAGPIE_REFERENCE_WAV=/user_data/audio_voice_demo/models/bluemagpie-ref-8s.wav
export BLUEMAGPIE_INFERENCE_TIMESTEPS=10
export BLUEMAGPIE_CFG_VALUE=2.8
export BLUEMAGPIE_MAX_AUDIO_SECONDS=8.0
Use TTS_PROFILE=bluemagpie to make BlueMagpie the startup default, or switch it from the /agent status panel.
The default BLUEMAGPIE_VOICE_MODE=centroid uses the bundled hung_yi_lee speaker centroid because it matches the upstream usage guide more closely than reference-audio cloning.
Or use continuation-style prompting:
export TTS_PROMPT_WAV=/path/to/prompt.wav
export TTS_PROMPT_TEXT="The exact text spoken in the prompt audio."
Not implemented yet:
Implemented:
/v1/chat/completions SSE parser<SAY>...</SAY> and <TOOL_CALL>...</TOOL_CALL><SAY> content into the TTS queue<TOOL_RESULT> events for local testingllm.delta event logging to verify real token streamingDefault local LLM endpoint:
http://127.0.0.1:8011/v1/chat/completions
Recommended Gemma 4 test target:
llama-server \
-m /user_data/audio_voice_demo/models/llm/gemma-4-e4b-it-Q6_K.gguf \
--host 127.0.0.1 \
--port 8011 \
-ngl 99 \
-c 4096 \
--flash-attn
FastAPI reads these environment variables:
export LOCAL_LLM_BASE_URL=http://127.0.0.1:8011/v1
export LOCAL_LLM_MODEL=gemma-4-e4b-it
export LOCAL_LLM_TEMPERATURE=0.45
export LOCAL_LLM_MAX_TOKENS=384
If llama.cpp is not running, the backend emits a short spoken fallback so the rest of the ASR-to-TTS pipeline remains testable.
1 commits
Python
61.9%
JavaScript
21.5%
CSS
7.9%
HTML
5.6%
Shell
3.1%