HFD_DuplexOmni_ROMA_Aero
统一交付仓库:
- HFD-1024 编译数据(新版 hesitation 165 条替换旧 hesitation)——所有模型共用;
- ROMA 流式 + 原生 talker 代码;
- Aero 严格在线 + Qwen3-TTS streaming 代码。
模型权重不在仓库,需自行下载(见下)。数据与模型解耦:MiniCPM-o、Venus、Gander、ROMA、Aero、DuplexOmni 等所有 HFD 模型都直接引用本仓库
data/。
0. 师兄需要做什么
本仓库分两类:
- ROMA / Aero:代码现成,准备环境和权重后可直接跑;
- DuplexOmni:代码需要自己配,本仓库只给数据和要求。
0.1 共同步骤
- 下载本仓库
data/:manifest.jsonl、videos/、adapters/;- 已编译 1024 条,165 条新版 hesitation 已替换;
- 3 秒 padding 已编译,运行时不要补静音。
- 不要用旧 1024 的 hesitation,也不要拿原始 manifest 直接跑;
- 每条结果必须保存:
- 文本;
- 原生语音 wav(不是 TTS、不是纯文本);
- 语音/文字相对媒体开始的时间戳。
- 先跑 1–2 条检查,再跑 1024。
0.2 ROMA(代码现成)
- 准备 ROMA 源码仓库和 Python 环境:
src/llamafactory+ vendored transformers 4.50.0.dev0;- torch 2.9/2.10。
- 下载权重:
EurekaTian/ROMA; - 显卡 ≥40 GB,建议 A100 80G;
- 跑:
python code/run_streaming_pilot.py --model-path /path/ROMA --manifest data/manifest.jsonl --output-root results_roma --two-stage - 必须保持:流式、不裁剪上下文、原生 talker;不能只用离线 generate。
0.3 Aero(代码现成)
- 准备 Aero vLLM/omni 环境;
- 下载权重:
kcz358/aero-realtime-4B;Qwen/Qwen3-TTS-12Hz-0.6B-CustomVoice;
- 建 TTS 环境(见第 4 节),启动:
- GPU1:
tts_server.py --emit-every-frames 1; - GPU0:
aero_server.py;
- GPU1:
- 跑:
python code/aero/run_aero_online_batch.py --manifest data/manifest.jsonl --output-root results_aero --url ws://127.0.0.1:8090/v1/aero/realtime --tts-url ws://127.0.0.1:8091/v1/tts/stream - 必须保持:严格在线,text delta 立即送 TTS;不能后置 TTS、不能只输出文字。
0.4 DuplexOmni(代码需自己配)
- 本仓库没有 DuplexOmni 推理代码;
- 基于官方
MuyeHuang/DuplexOmni仓库自己配 duplex/streaming; - 仍然使用本仓库
data/; - 按第 6 节要求:
- 不补静音、不改 3 秒;
- 原生 duplex + 原生 talker;
- 不裁剪上下文、不量化、不用 TTS;
- 官方建议 8×H20;
- 跑通 1–2 条后,再跑 1024。
0.5 交付给我们的结果
每个模型一套:
results_<model>/
├── <sample_id>/result.json # text, 时间戳, 音频路径
└── <sample_id>/assistant_audio.wav # 原生语音
不要只交文本;不要用外部 TTS 冒充原生语音。
1. 数据
data/
├── manifest.jsonl # 1024 条
├── videos/ # 1024 条已编译视频(5 fps)
└── adapters/ # 1024 个 adapter
- 新版 hesitation 165 条已替换旧 hesitation;
- 其他 859 条任务不变;
- 新版 hesitation 音轨已按
duplex.inputs事件拼好:- 第一问只放
spoken_text的未说完前缀; - 第二问放完整改口问题;
event.start - timing.video_offset映射到视频内时间;
- 第一问只放
- 所有视频尾部已编译 3 秒 padding(最后一帧冻结 + 音轨静音);
- 运行时不要再补静音 chunk,客户端直接流完整个文件再
input.done。
manifest 里 videos/...、adapters/... 都是相对仓库根目录的路径。
2. 目录
code/
├── run_streaming_pilot.py # ROMA 两阶段流式 runner
├── compile_hes1030.py # 新版 hesitation 编译参考
├── make_padded.py # 3s padding 模板
├── HESITATION_RERUN.md # hesitation 重跑方法
└── aero/
├── aero_server.py # 官方 online server 副本
├── run_aero_online_batch.py # 严格在线批量客户端
├── tts_server.py # Qwen3-TTS streaming server
├── qwen3_tts_bridge.py # bridge(sdpa/eager 兼容)
└── qwen_tts_fork/ # streaming fork 的 qwen_tts
3. ROMA
规则
- 必须流式
streaming_mix,不能离线generate; - 不裁剪上下文、不量化;
- 原生 talker + token2wav 音频;不接受纯文本/外部 TTS;
- 3 秒 padded 已编译进
data/; - 32 GB 会 OOM,建议 ≥40 GB / A100 80G。
环境
- 模型:
EurekaTian/ROMAHF snapshot; - ROMA 源码仓库(
src/llamafactory+ vendored transformers 4.50.0.dev0); - torch 2.9/2.10,soundfile、numpy;
- 不是独立 pip 包。
运行
python code/run_streaming_pilot.py \
--model-path /path/to/ROMA/snapshot \
--manifest data/manifest.jsonl \
--output-root results_roma \
--two-stage
输出:result.json(text、first_token_s、end_s)+ assistant_audio.wav。
4. Aero(严格在线 + Qwen3-TTS streaming)
规则
- 每个
response.text.delta立即转发 TTS; - TTS
--emit-every-frames 1,partial text → partial audio; - 不做后置 TTS、不接受纯文本;
- 数据用本仓库
data/,3 秒已编译,客户端不补静音。
模型
- Aero:
kcz358/aero-realtime-4B; - TTS:
Qwen/Qwen3-TTS-12Hz-0.6B-CustomVoice。
Aero 环境
按官方 Aero 仓库安装 vLLM/omni;code/aero/aero_server.py 是官方 examples/online/server.py 副本。
TTS 环境
python -m venv .venv-tts
.venv-tts/bin/pip install torch torchaudio --index-url https://download.pytorch.org/whl/cu130
.venv-tts/bin/pip install transformers==4.57.3 accelerate==1.12.0 sox
.venv-tts/bin/pip install qwen-tts==0.1.1 --no-deps
cp -a code/aero/qwen_tts_fork/* .venv-tts/lib/python3.12/site-packages/qwen_tts/
qwen3_tts_bridge.py 已处理:CUDA sdpa、CPU eager、compile/CUDA graph 兼容;需要系统 sox。
启动(建议两张卡)
# GPU1 TTS
.venv-tts/bin/python code/aero/tts_server.py --model /path/Qwen3-TTS-12Hz-0.6B-CustomVoice --device cuda:1 --port 8091 --emit-every-frames 1
# GPU0 Aero
python code/aero/aero_server.py --model /path/aero-realtime-4B --deploy-config /path/vllm-omni/vllm_omni/deploy/aero_realtime.yaml --gpu-memory-utilization 0.9 --max-model-len 262144 --port 8090
批量
python code/aero/run_aero_online_batch.py --manifest data/manifest.jsonl --output-root results_aero --url ws://127.0.0.1:8090/v1/aero/realtime --tts-url ws://127.0.0.1:8091/v1/tts/stream
输出:assistant_stream.wav + result.json(text、audio_arrivals、qend)。
5. 新版 hesitation 编译方法
数据已编译,无需重编;复现见 code/HESITATION_RERUN.md:
video_time = event.start - timing.video_offset;- 按
source_start/source_end裁事件音频; - 第一问只用
spoken_text前缀; - 3 秒
tpad/apad; - adapter 的
events.start/end必须是视频内时间。
6. DuplexOmni 配置要求(师兄)
DuplexOmni 需要单独配置推理代码;以下是完整要求,不要直接套 ROMA/Aero 的 runner。
6.1 数据
- 只用本仓库
data/(1024 条,已编译替换 hesitation); - 每条视频已包含:
- 新版 hesitation 的“未说完前缀 + 改口问题”音轨;
- 尾部 3 秒 padding(最后一帧冻结 + 静音);
- 运行时不补任何静音 chunk,也不要把完整第一问再播一遍;
- manifest 的
video/adapter是相对路径,直接按仓库根目录解析; - 每条
duration_seconds已含 3 秒,不要再 +3。
6.2 输入流
- 视频 5 fps,音频 16 kHz mono;
- 按媒体时间轴顺序推 chunk,不要跳帧/跳音频;
- 媒体流完后直接
done,不要额外喂 3 秒; - 如果框架要求固定 chunk(如 80ms/1s),按原时长切分,最后一块补零到 chunk 长度即可,不要再加整段静音。
6.3 模型与推理
- 权重:
MuyeHuang/DuplexOmni; - 必须用官方 duplex/streaming 推理路径,不能改成离线整段
generate; - 保持原生 thinker + talker,不能只输出文字,也不能接外部 TTS;
- 不裁剪上下文、不量化、不蒸馏;
- 官方建议至少 8×H20;显存不足时不要靠裁剪上下文硬跑,结果不可比。
6.4 输出与时间戳
- 保存每条:
- 文本输出;
- 原生语音 wav;
- 语音/文字相对媒体开始的时间戳;
- 语音起点用模型实际开始输出的位置,不要事后按固定延迟摆放;
- 视频比语音短时,冻结最后一帧到语音结束,不要截断语音。
6.5 常见错误
- 用旧 1024 的 hesitation 视频;
- 只给原视频加静音,没有拼事件音轨;
- 运行时又补 3 秒,导致 6 秒;
- 把新版 hesitation 的
start/end当视频时间,没减video_offset(数据已编译,运行时不需要再减,但不要拿原始 manifest 直接跑); - 只保存文字,没有原生语音。
7. 硬件与许可
- ROMA:≥40 GB,建议 80 GB;
- Aero:GPU0 Aero,GPU1 TTS;同卡 32 GB 峰值会 OOM;
- 数据 CC-BY-NC-SA-4.0;模型权重按各自许可。
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support