当前位置: 首页 > news >正文

在 RK3588S 上搭建离线视觉语音助手:从 C310 推流到 Qwen3-VL 与 TTS

本文记录 EdgeSight Assistant 截至 2026-08-14 的架构、目标板测试和近期修改。文章中的地址、密钥、模型路径和日志文件均已省略。

一、项目背景

这个项目的目标是在一块 8GB 内存的 Firefly ROC-RK3588S-PC 上,搭建一个可以持续推送视频、通过语音唤醒、理解当前画面并播报答案的离线多模态助手。

当前硬件组成如下:

  • Firefly ROC-RK3588S-PC;
  • Logitech C310 USB 摄像头,提供视频和麦克风;
  • 板载 ES8323 音频输出,连接 3.5mm 设备;
  • 外部 SRS 服务器;
  • Win11 主机上的 RambosPlayer。

Win11 主机只负责从 SRS 拉流播放视频。目标板负责摄像头采集、视频编码推流、语音唤醒、语音识别、视觉推理和语音播放。这样划分以后,视频播放端和边缘计算端相互独立,目标板无需连接显示屏,也无需在板端重复实现播放器。

github:https://github.com/johnjiamzhong-project/EdgeSightAssistant

二、总体架构

系统由四条主要链路组成:视频推流链路、音频激活链路、视觉问答链路和 TTS 播放链路。

                           ┌──────────────────────────────┐│ Win11 RambosPlayer            ││ 从 SRS 拉流播放               │└──────────────▲───────────────┘│
C310 摄像头 ─> V4L2 MJPEG ─> FFmpeg 解码 ─> NV12│┌────────────────┴───────────────┐│                                │h264_rkmpp 硬编                  latest-frame 缓冲│                                │FLV / RTMP                      视觉 worker│                                │▼                                ▼SRS                    RKNN 图像编码器│▼RKLLM Qwen3-VL-2B│▼
C310 麦克风 ─> ALSA ─> KWS ─> 状态机 ─> VAD ─> SenseVoice ─> asr_final│▼Unix datagram│▼edgesight_tts│VITS + ALSA 播放

1. 视频推流模块

视频模块的核心数据流是:

C310 MJPEG 1280x720@30-> V4L2-> FFmpeg MJPEG decoder-> reusable NV12 frame-> h264_rkmpp-> FLV muxer-> RTMP/SRS

项目强制使用 h264_rkmpp,硬编码器不可用时直接报告错误,不回退到 CPU 软件编码。C310 启动时会关闭动态曝光降帧控制,避免摄像头在暗光场景下从 30 FPS 降到约 15 FPS。

推流器同时按固定间隔生成一张较小的 RGB 最新帧,放入容量为 1 的 latest-frame 缓冲。视觉请求到来时只取最近的一帧,不建立历史图片队列,也不让视觉推理阻塞视频发布循环。

2. 音频激活模块

音频模块使用 C310 的 USB 麦克风,默认参数为 16 kHz、单声道、S16_LE。流程为:

ALSA PCM-> sherpa-onnx Zipformer KWS-> ActivationController-> 能量 VAD-> SenseVoiceSmall int8-> 结构化 asr_final 事件

固定唤醒词为“你好小视”。命中后,程序通过 TTS 播放“我在”,并等待用户开始说命令:

  • 5 秒只限制“开始说话”的时间;
  • 一旦检测到语音,命令可以继续超过 5 秒;
  • 尾部静音达到 1 秒后结束命令;
  • 5 秒内没有开始说话时产生 activation_timeout
  • 唤醒后会先等待一个安静音频块,降低唤醒词和“我在”的回声误触发。

所有关键状态都写成结构化事件,例如:

wake_detected
asr_started
command_ended
asr_final
activation_timeout
wake_rejected

3. 视觉问答模块

在 8GB 目标板上,首轮固定使用 Qwen3-VL-2B。视觉模型由两个部分组成:

  1. RKNN 图像编码器,把 RGB 图片转换成视觉 embedding;
  2. RKLLM 语言模型,把 embedding 和用户问题组合成回答。

视觉 worker 在后台加载一次模型。收到 asr_final 后,从 latest-frame 缓冲取一张当前画面,再执行图像编码和语言推理。视觉模块只在用户提出问题时运行,当前没有让 VLM 按 30 FPS 持续分析视频。

模型文件、RKNN/RKLLM 运行库和转换工具均放在目标板外部目录,仓库只保存构建代码和配置模板。当前使用的 RKLLM runtime 与 Qwen3-VL-2B 模型保持匹配,4B 模型暂不进入这块 8GB 板的主路径。

4. TTS 模块

TTS 运行在独立的 edgesight_tts 进程中:

VisionWorker-> Unix datagram-> edgesight_tts-> sherpa-onnx Offline VITS-> 持久 ALSA 会话-> 3.5mm 输出

当前使用 VITS Melo 中英文模型。一个回答会按中文或英文句末标点拆分,最多缓存两个待合成片段。第一段合成完成后即可开始播放,后续片段继续合成和播放。

TTS 对外保留两种协议:普通完整文本请求,以及 stream_beginstream_segmentstream_end 组成的句子流。请求级仍然采用单请求 busy 拒绝策略,避免无界音频队列把延迟越积越长。

三、启动和进程边界

完整链路通过脚本启动:

scripts/start_all.sh config/config.yaml

启动顺序为:

  1. 初始化板载音频输出;
  2. 启动 edgesight_tts
  3. 启动启用视觉旁路的 edgesight_streamer
  4. 启动 edgesight_audio

停止时按相反顺序清理:

scripts/stop_all.sh

当前项目采用前台 CLI 和脚本控制,暂不配置 systemd、桌面启动项、常驻 WebSocket/HTTP 控制服务或 GUI。错误主要通过 logs/ 中的结构化事件和统计信息定位。

四、已经完成的目标板验证

视频链路

  • C310 实际枚举为 MJPEG 1280×720、30 FPS;
  • h264_rkmpp 硬编码路径可用;
  • SRS RTMP 推流完成 600 秒连续运行;
  • VLC/RambosPlayer 人工观看画面正常;
  • 最终验证约 29.9 FPS,发布器错误数为 0。

音频和唤醒链路

  • C310 实时麦克风可以命中“你好小视”;
  • 唤醒后“我在”可以通过 3.5mm 输出播放;
  • wake_detected → asr_started → command_ended → asr_final 已通过真人测试;
  • activation_timeout、活动中重复唤醒拒绝和冷却窗口已完成回归;
  • 真人唤醒正例使用实时 C310 麦克风,保存 WAV 只用于确定性回归。

视觉和 TTS 并发链路

  • Qwen3-VL-2B 单图和 latest-frame 旁路已在目标板运行;
  • 视觉回答可以经 Unix datagram 交给 TTS;
  • TTS 真实 3.5mm 播放成功;
  • 视频、音频、视觉和 TTS 同时运行时,视频仍保持约 30 FPS;
  • start_all.shstop_all.sh 烟测通过,结束后没有残留 EdgeSight 进程和 Unix socket。

开发机无硬件回归也已固定下来:

CTest: 5/5 passed
bash -n scripts/*.sh: passed

五、一次 TTS 竞态故障的定位和修复

多轮真人测试时,日志出现过以下异常顺序:

tts_request_accepted
没有 tts_started
后续请求全部 tts_rejected reason=busy

原因在于普通文本 worker 和流式 worker 共用了一个条件变量,但使用了不同的等待谓词。普通请求路径调用 notify_one() 时,可能唤醒了流式 worker。流式 worker 发现条件不满足后继续等待,普通 worker 没有收到通知,普通文本就一直留在 pending 状态。

修复方式是把普通请求路径的 notify_one() 改成 notify_all()。两个 worker 都被唤醒后,会分别检查自己的谓词,只有条件满足的 worker 才继续处理。

修复后进行了三步验证:

  1. 独立 socket 下发送一个流式请求;
  2. 连续发送两次普通“我在”请求;
  3. 确认三次都完成 accepted → started → finished

随后只重启 TTS 和音频监听进程,保持视频推流进程继续运行。C310 真人唤醒、确认语播放、ASR、视觉回答和最终 TTS 均成功,推流仍约 29.9 FPS。

这个问题的修复很小,但也说明了多 worker 程序中,条件变量、谓词和通知方式必须一起设计,不能只看消息队列本身。

六、端到端延迟统计

最初的测试只能得到一个模糊的“从唤醒到回答很慢”。后来给音频、视觉和 TTS 统一加入 Linux 单调时钟,并记录 tts_playback_startedsynthesis_msplayback_ms 等字段。

在 13 条修复后事件链中得到的 p50/p95 如下:

阶段 P50 P95 解释
唤醒到开始采集 859 ms 1000 ms 包含确认语回声保护的等待
命令采集 2376 ms 3752 ms 用户说话时间 + 1 秒尾部静音
命令结束到 ASR 结果 176 ms 246 ms ASR 解码收尾
图像编码 3092 ms 3096 ms 当前第一大固定瓶颈
VLM 语言推理 1988 ms 3016 ms 当前第二大固定瓶颈
视觉总耗时 5080 ms 6107 ms 从 ASR 完成到视觉结束
视觉结束到回答开始播放 3100 ms 5667 ms TTS 首声路径
唤醒到最终回答首声 11292 ms 13899 ms 用户感知的完整延迟

这组数据说明,ASR 解码只有约 0.18 秒,当前最值得优化的区域是图像编码、VLM 语言阶段和 TTS 首声。

在更早的一次单轮基线中,唤醒到首声曾达到 58.959 秒,播放结束达到 91.576 秒。后来增加简短回答约束、将 TTS 默认推理线程从 2 个调整到 4 个、完善分段播放后,一次真人样本降到首声 11.986 秒、播放结束 17.891 秒。两次测试的输入和运行状态并不完全相同,因此这组结果用于判断方向,不能替代严格的单变量基准。

七、当前的流式优化状态

视觉 worker 已经可以从 RKLLM 回调中接收文本片段,在句末组装出完整句后立即发送给 TTS。目标是让语言生成、TTS 合成和物理播放互相重叠。

两句文本探针已经观察到第二句在第一句合成期间到达,协议层面的重叠成立。当前真人回答经常只有一句话,首句与完整回答几乎同时产生,所以实际首声收益还没有形成稳定的 p50/p95 结论。另一个限制是当前 VITS 仍然属于 offline TTS,句子队列属于兼容现有模型的过渡方案。

八、现在还剩什么问题

当前项目已经完成“视频 + 音频 + 视觉 + TTS”目标板联调,但仍有几项工程工作需要继续:

1. 视觉编码约 3 秒

下一步先对同一暖机模型、同一输入帧测试 rknn_core_num=0/1/2/3,确认 NPU 核心调度、输入预处理和运行库配置是否真正生效。

2. latest-frame 预编码

如果核心 A/B 不能解决图像编码耗时,再评估让视觉 worker 在后台持续编码最新帧。实现时要同时观察 NPU 争用、画面时效、内存和视频 FPS,不能只看单次视觉耗时。

3. TTS 首声

继续记录 RKLLM 首 token、首分句、首完整句、TTS 接收和开始播放的时间;随后评估目标板兼容的真正流式 TTS。现有 VITS 需要继续保留为稳定回退。

4. 确认语回声

多轮日志中出现过“我在”“嗯”“3”等很短的 ASR 结果,它们可能继续触发视觉请求。后续需要加入短确认语过滤或 ACK 播放期间的输入门控,AEC 则单独评估。

5. 更快的任务路径

简单的“桌面有什么”“有没有人”等问题,可以评估 detector/OCR 等专用路径;复杂问题继续交给 VLM。如果板端完整 VLM 仍无法满足目标,再考虑把复杂视觉推理卸载到 Win11 主机。

九、当前状态与范围

当前系统按以下方式运行:

  • 完整链路由 start_all.shstop_all.sh 控制,开机自动启动留待后续处理;
  • 真实配置、RTMP key、模型和运行库保存在目标板外部环境,仓库只维护示例配置和程序代码;
  • 固定唤醒词的真人验收使用 C310 实时麦克风,保存 WAV 用于确定性回归;
  • 视频编码固定采用 h264_rkmpp,摄像头、推流、音频监听和视觉推理各自保持清晰的进程/线程职责;
  • 视觉推理运行在旁路中,持续视频推流和音频监听保持独立;
  • GUI、断流自动重连和长时间稳定性纳入后续阶段。

十、总结

这个项目经历了几个阶段:先确认 C310 能稳定推到 SRS,再接入唤醒词和 ASR,然后加入 latest-frame 视觉问答,最后把 TTS 和完整并发链路接起来。

最近一次工作重点从“把功能接上”转向“把耗时拆开”。通过统一计时和结构化事件日志,已经确认 ASR 并非主要瓶颈,图像编码、VLM 推理和 TTS 首声才是后续重点。TTS 竞态修复也验证了一个经验:边缘设备上的多进程系统,稳定性问题往往藏在进程间协议、队列边界和条件变量上。

目前系统已经具备可重复启动、可观测、可回归的基础。后续优化会严格遵循单变量 A/B,每完成一项都同时检查语音链路、实际播放和视频 30 FPS,避免只优化某个数字,却破坏整个系统。

http://www.jsqmd.com/news/1394635/

相关文章:

  • 思源宋体CN免费字体:5分钟快速配置完整中文排版方案
  • 无人机装调检修工培训基地推荐 - 湖南阳光技术
  • 加盟点喷需要哪些资质和培训?先看清行业门槛,再看艺猫怎么补齐 - 资讯报道
  • 赋能影视工业化升级,湖南梵映教育科技有限公司携手华智数媒打造产教融合** - 生活动态圈
  • 超市实体经营感悟:换位思考服务用户,方能实现长期成长
  • 2026成都旧房翻新售后保障装修公司选型指南:合规靠谱服务商盘点+签约避坑全维度FAQ - 商业大观
  • 家中藏书千册却无一纸目录?把PDF版权页导出Excel,图书信息一目了然打造专属电子书库
  • [NVSentinel] gpu-health-monitor模块调研
  • 全网最全✅okbiye核心功能大盘点!一篇看懂所有论文刚需能力
  • 2026成都整装套餐靠谱服务商甄选全攻略:含合规资质、性价比等多维度评估+签约避坑全流程FAQ及核心选型标准 - 行业观察网
  • 20260814 5.5+5 182.5
  • 第54届安妮奖增设国际动画单元,影视后期实训机构实测,赛事级作品集择校指南 - 生活动态圈
  • 中小企业选GEO代运营技巧,2026高性价比服务商严选
  • 联想工作站找谁买?售后SLA对比与保修避坑全指南
  • 2026园区物业公卫设备集采贴牌商家选型指南:正规合规供应商盘点+合作避坑全维度FAQ - U渠道
  • 2026西藏旅行社口碑发布:迎昭16年未出投诉,凭什么? - zhongxing1
  • miniRV CPU 设计实战:从数据通路到 FPGA 下板运行 CoreMark
  • 2026厦门经济犯罪律师选择指南:3家专业刑辩律所对比 帮信罪/合同诈骗委托避坑要点 - 商业大观
  • 经营驾驶舱:业务财务贯通让异常可逐级追溯
  • 0061基于 SpringBoot 的投稿与稿件处理系统设计与实现
  • 盘锦装修签合同前门窗选购要看哪些细节
  • 请假陪床3天,被扣光全勤[特殊字符][特殊字符]
  • 2026生成式引擎优化平台品牌代运营哪家口碑好?严选评析分享
  • 如何通过一张照片来获取 ip 地址?
  • 微修点喷和整车喷漆,哪种更赚钱?从成本、效率、复购看艺猫点喷的独有优势 - 资讯报道
  • 2026成都一站式高性价比家装公司选型指南:3家合规靠谱品牌盘点+签约避坑全维度FAQ - 行业观察网
  • 2026四大AI论文写作软件深度测评|从降重到润色,各有所长别盲选
  • 厦门合同诈骗辩护律所:3家商事犯罪律所对比与合作选择指南(2026版) - 行业观察网
  • NeteaseCloudMusicFlac 快速上手:一条命令批量下载网易云无损FLAC音乐
  • 《2026成都全屋整装公司推荐大全:正规合规、高性价比、口碑扎实、全场景适配的服务商盘点+选型标准与签约避坑全维度FAQ》 - 商业大观