人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载导读本文以 TEN Framework 官方示例扩展包 ffmpeg_demuxer 为主线深入讲解如何在 TEN Framework 中构建一个基于 FFmpeg 的媒体解复用器demuxer扩展用于将音视频媒体流从容器中分离、解码并转换为 TEN 标准音视频帧。读完本文你将掌握该扩展的包结构、命令协议prepare_demuxer/start_demuxer、独立线程模型、FFmpeg 资源管理与帧格式转换的实现原理并能够将其按框架规范集成到自己的 TEN 应用中。一、扩展概述在 TEN Framework 中实现媒体流分离ffmpeg_demuxer是 TEN Framework 的一个 C 扩展包其官方定位为TEN Framework 中用于媒体流分离的 FFmpeg 解复用器扩展见 manifest.json 中的多语言描述。它解决的核心问题是如何把一段音视频输入本地文件或网络流拆解为独立的视频帧与音频帧并以 TEN 标准的消息帧形式送入后续扩展链例如转码、编码、推流或 AI 处理管线。从仓库结构看该扩展具备典型的 TEN 扩展包三要素文件作用manifest.json声明包类型extension、名称、版本、依赖与多语言 README 入口property.json扩展默认属性当前为空对象表示无预置属性BUILD.gnGN 构建脚本声明源码、资源与依赖src/main.cc扩展入口注册扩展类与命令处理src/demuxer_thread.cc解复用专用线程的启动、停止与结果回传src/demuxer.ccFFmpeg 核心逻辑打开输入、解码、格式转换、发送帧res/test.mp4内置测试用 MP4 资源构建上扩展通过 BUILD.gn 链接//third_party/ffmpeg:ffmpeg_for_ten_packages并在 manifest 中声明依赖系统包ffmpeg版本7.1.0与仓库内 third_party/ffmpeg 提供的能力保持一致。二、前置条件与包依赖根据 manifest.json包类型extension包名称ffmpeg_demuxer当前版本0.11.73系统依赖type: system、name: ffmpeg、version: 7.1.0—— 即要求构建环境中具备 FFmpeg 7.1.0 运行库API 声明api: {}即本扩展不对外暴露额外的 schema 接口完全依靠命令cmd进行交互标签cpp表明这是一个 C 扩展。安装遵循 TEN Framework 标准包安装流程使用tman安装扩展包安装后包目录通常位于ten_packages/extension/ffmpeg_demuxer这也是 main.cc 中默认输入路径ten_packages/extension/ffmpeg_demuxer/res/test.mp4的由来。三、命令协议如何驱动解复用器该扩展与外界交互完全通过命令完成核心命令有三个均定义在 main.cc 的demuxer_extension_t::on_cmd中。3.1prepare_demuxer准备输入流调用方通过命令属性input_stream指定媒体输入本地文件路径或网络流地址。若属性为空则回退到默认值ten_packages/extension/ffmpeg_demuxer/res/test.mp4auto input_stream_name cmd-get_property_string(input_stream); if (input_stream_name.empty()) { input_stream_name ten_packages/extension/ffmpeg_demuxer/res/test.mp4; }由于解复用与解码是 CPU 密集型操作扩展会创建一个独立的demuxer_thread_t线程并通过ten::ten_env_proxy_t::create(ten_env)创建线程代理供该线程与 TEN 主线程安全交互。prepare命令的应答在解复用线程中回传。3.2start_demuxer启动解复用循环start_demuxer命令通过demuxer_thread_-start_demuxing()置位事件唤醒被阻塞的解复用线程进入循环若尚未执行prepare_demuxer则返回错误结果You should prepare first.。3.3complete与 EOF 通知当输入流读尽EOF时解复用线程向后续扩展发送带eoftrue的音视频帧并发送名为complete的命令携带input_stream与success两个属性用于通知管线“该输入流已完整处理”。3.4prepare成功后的元数据回传解复用线程在准备成功后会通过cmd_result回传一批流元数据属性见 demuxer_thread.cc下游扩展可直接读取无需自行探测属性含义frame_rate_num/frame_rate_den/frame_rate_d视频帧率有理数与浮点两种表达video_time_base_num/video_time_base_den/video_time_base_d视频流时间基width/height视频宽度 / 高度已考虑旋转元数据bit_rate视频码率num_of_frames视频帧总数audio_sample_rate音频采样率audio_channel_layout_mask/audio_num_of_channels音频声道布局掩码 / 声道数audio_time_base_num/audio_time_base_den/audio_time_base_d音频流时间基四、线程模型解复用线程与 TEN 主线程的协作解复用器运行在独立线程中原因正如源码注释所言Since demuxing is a CPU-intensive operation, it is handled in a separate thread。整体生命周期如下on_cmd收到prepare_demuxer后创建ten_env_proxy与demuxer_thread_t并start()启动线程线程主函数demuxer_thread_main见 demuxer_thread.cc首先create_demuxer()打开输入流成功则回传prepare成功结果失败则回传错误并退出线程随后线程在wait_to_start_demuxing()处阻塞等待start_demuxer命令置位事件进入循环decode_next_packet()直到输入流 EOFDECODE_STATUS_EOF或发生错误DECODE_STATUS_ERROR循环结束后发送complete命令线程退出。线程的停止由扩展的on_stop驱动先stop()置位原子标志再wait_for_stop_completed()通过ten_thread_join回收线程。stop_标志也被open_input_with_retry用作“放弃重试”的退出条件保证在等待输入流期间能够被及时终止。五、输入流打开重试机制与 20 秒超时保护5.1 带重试的打开流程open_input_stream见 demuxer.cc调用open_input_with_retry当输入流尤其是网络流暂时不可用时会持续重试open_input直到成功或解复用线程被停止。这一机制对“等待推流端就绪”的场景非常关键。5.2 低延迟探测参数在open_input中扩展通过av_dict_set设置了 FFmpeg 选项av_dict_set(av_options, analyzeduration, 1000000, 0); // 1000 msec即限制avformat_open_input/avformat_find_stream_info的流分析时长为 1000 毫秒以换取更低的启动延迟。源码注释同时提醒如果输入格式定义明确且对延迟极度敏感可以考虑实现自定义格式解析器来替代自动分析。5.3 中断回调防止无限阻塞解复用器注册了interrupt_callback见 demuxer.cc每次读帧前刷新last_time若某次 FFmpeg 阻塞操作超过20 秒回调返回非零值立即中断当前操作从而规避网络故障或资源不可达导致的永久挂起。if (time(nullptr) - r-last_time 20) { return 1; // 超过 20 秒中断当前 FFmpeg 操作 }六、音视频流探测与解码器初始化输入打开成功后analyze_input()调用avformat_find_stream_info获取流信息随后分别通过av_find_best_stream定位视频流与音频流并完成解码器创建见 demuxer.ccav_find_best_stream(ctx, AVMEDIA_TYPE_VIDEO, ...)获取视频流索引与解码器avcodec_alloc_context3avcodec_parameters_to_contextavcodec_open2绑定解码器遍历流元数据读取rotate旋转标签并记录rotate_degree0/90/180/270后续video_width()/video_height()会根据旋转角度对宽高进行互换音频侧记录sample_rate、ch_layout与声道布局掩码对pcm_mulaw这类不提供声道布局的编码使用av_channel_layout_default按声道数生成默认布局。只有成功找到至少一种可解码的音/视频流video_decoder ! nullptr || audio_decoder ! nullptris_input_opened()才返回 true。七、包读取与逐包解码7.1 主循环decode_next_packetint ffmpeg_rc av_read_frame(input_format_context, packet);每次迭代先av_packet_unref丢弃上一包再读取下一包按packet-stream_index分发给视频或音频解码路径。AVERROR_EOF时依次执行flush_remaining_video_frames()与flush_remaining_audio_frames()把解码器中残留的帧全部冲刷出来然后返回DECODE_STATUS_EOF。7.2 视频解码与特殊处理视频侧使用avcodec_send_packetavcodec_receive_frame的标准解码 APIAVERROR(EAGAIN)表示“数据不足”需要继续喂包。音频侧有一个针对 MP3 的容错分支见 demuxer.cc当解码器为AV_CODEC_ID_MP3且avcodec_send_packet返回AVERROR_INVALIDDATAMP3 头部缺失时跳过该包继续读取下一包由于一个音频包可能解出多帧音频路径使用while (true)循环将同包内的所有帧全部取尽。7.3 帧发送解码得到的每一帧都会转换为ten::video_frame_t/ten::audio_frame_t并通过ten_env_proxy-notify(...)切回 TEN 线程调用ten_env.send_video_frame/send_audio_frame发送给下游扩展。发送时对帧的强引用shared_ptr在 lambda 中捕获确保线程安全。八、帧格式转换与时间戳归一化8.1 视频帧输出格式解复用器对视频输出采用双格式策略见 demuxer.cc若解码帧为AV_PIX_FMT_YUV420P/AV_PIX_FMT_YUVJ420P则直接以I420TEN_PIXEL_FMT_I420布局拷贝到 TEN 帧三个平面分别复制 Y / U / V若为AV_PIX_FMT_RGB24则以RGB24TEN_PIXEL_FMT_RGB24紧凑排列拷贝其他像素格式不转换直接丢弃源码中仅记录日志避免引入不必要的像素格式转换开销。与此同时create_video_converter使用sws_getContext准备了 RGB24 转换上下文SWS_POINT快速算法供有转换需求的路径使用。8.2 音频帧输出格式音频统一输出为S16AV_SAMPLE_FMT_S16交错布局TEN_AUDIO_FRAME_DATA_FMT_INTERLEAVE由 demuxer.cc 中的宏定义决定#define DEMUXER_OUTPUT_AUDIO_FRAME_SAMPLE_FMT AV_SAMPLE_FMT_S16 #define DEMUXER_OUTPUT_VIDEO_FRAME_PIXEL_FMT AV_PIX_FMT_RGB24音频转换借助swr_alloc/swr_init初始化重采样器将解码器的原始采样格式、采样率、声道布局统一转换为目标格式并通过swr_convert完成转换。转换后帧设置bytes_per_sample、sample_rate、channel_layout、number_of_channels、samples_per_channel等属性。代码注释特别提醒swr_convert返回的样本数可能少于预期因为部分样本可能暂存在 resampler 内部队列中。8.3 时间戳归一化到毫秒对于音视频帧扩展统一将best_effort_timestamp减去流start_time得到相对流起始的偏移再用av_rescale按时间基缩放为毫秒audio_frame-set_timestamp(av_rescale( frame-best_effort_timestamp - start_time, static_castint64_t(time_base.num) * 1000, time_base.den));这使得下游扩展拿到的音视频帧时间戳在同一毫秒尺度上可比对便于做音视频同步。九、资源生命周期与内存安全析构顺序集中体现了 FFmpeg 资源管理的最佳实践见 demuxer.ccav_packet_free/av_frame_free释放包与帧解码器上下文用avcodec_free_context释放解码器本身video_decoder/audio_decoder所有权归 FFmpeg不手动删除视频转换器用sws_freeContext、音频重采样器用swr_free释放输入上下文必须使用avformat_close_input关闭而非仅释放上下文源码注释明确警告Failing to do so may result in memory leaks, particularly with certain formats (e.g., HLS)中断回调参数用TEN_FREE释放。此外解复用器对象在线程内创建、在线程内销毁见 demuxer_thread.cc符合“谁创建谁销毁”的线程安全原则。十、快速开始集成到 TEN 应用10.1 前置条件TEN Framework 构建环境C依赖包ffmpeg7.1.0已按 manifest.json 声明安装应用侧遵循 TEN Framework 包安装指南安装本扩展包。10.2 集成方式安装扩展包使用 TEN 的包管理工具将ffmpeg_demuxer安装到应用的ten_packages/extension/目录并在应用property.json的扩展图中注册该扩展发送prepare_demuxer命令通过input_stream属性指定输入本地文件路径或网络流 URL不指定时使用默认测试资源ten_packages/extension/ffmpeg_demuxer/res/test.mp4读取返回的流元数据从cmd_result中获取帧率、宽高、码率、采样率、声道数、时间基等属性用于下游配置发送start_demuxer命令唤醒解复用线程开始输出帧下游扩展接收音视频帧在扩展图中将本扩展的video_frame/audio_frame输出连接到后续扩展如编码、推流、AI 分析并可监听complete命令与eoftrue帧判断输入流处理结束。10.3 验证路径仓库提供了现成的测试资源 res/test.mp4无需额外准备媒体文件即可快速验证构建配置见 BUILD.gn其resources已包含manifest.json、property.json、LICENSE与res/test.mp4并随包发布多语言docs/文档。十一、总结ffmpeg_demuxer展示了在 TEN Framework 中构建媒体处理扩展的完整范式以命令驱动生命周期prepare_demuxer→start_demuxer→complete、以独立线程承载 CPU 密集型解复用任务、以ten_env_proxy实现跨线程消息投递并在帧级统一输出 I420/RGB24 视频帧与 S16 交错音频帧及毫秒时间戳。无论是接入本地音视频文件还是对接网络流媒体输入该扩展都是一份可直接参考、可复用的 C 参考实现。其许可证遵循 TEN Framework 项目整体条款见 LICENSE。赞分享人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载相关推荐在 TEN Framework 中使用 gemini_tts_python基于 Google Gemini 2.5 的实时 TTS 扩展在 TEN Framework 中使用 gemini_tts_python基于 Google Gemini 2.5 的实时 TTS 扩展 gemini_tts人工智能AI Agent多模态语音AI 应用TEN Framework 中的 AWS ASR Python 扩展基于 Amazon Transcribe 流式 API 的实时语音识别实战指南TEN Framework 中的 AWS ASR Python 扩展基于 Amazon Transcribe 流式 API 的实时语音识别实战指南 导读 本文人工智能AI Agent多模态语音AI 应用TEN Framework 异步 HTTP 服务器 Python 扩展深度解析基于 aiohttp 的 HTTP/WebSocket 桥接到 TEN 命令的实现指南TEN Framework 异步 HTTP 服务器 Python 扩展深度解析基于 aiohttp 的 HTTP/WebSocket 桥接到 TEN 命令的实人工智能AI Agent多模态语音AI 应用上一篇PL/Rust安装教程在Debian/Ubuntu系统上快速部署PostgreSQL的Rust扩展下一篇GoClone 与其他工具对比为什么选择Go语言网站克隆器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
Mopidy 终端运行完全指南:手动启动、停止与配置管理(docs/running/terminal) 音视频后端 【免费下载链接】mopidy Mopidy is an extensible music server written in Python 项目地址: https://gitcode.com/gh_mirrors/mo/mopidy 点击查看 免费下载 本文基于 Mopidy 官方文档 docs/running/terminal.rst 展开,系统讲解如何在终端中… · 2026/9/25 5:15:28
Web安全学习合规边界与合法实践指南 我不能提供任何有关制作、传播或使用恶意软件(包括图片马、一句话木马、WebShell等)的技术指导。这类行为:严重违反《中华人民共和国网络安全法》第二十七条:“任何个人和组织不得从事非法侵入他人网络、干扰他人网络正常功能、窃… · 2026/9/25 5:15:22
VS Code + Arm Keil Studio Pack:嵌入式开发的声明式工程实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 6:56:41
Packet Tracer 6.0 安装汉化全攻略:从下载到中文界面一步不踩坑 1. 为什么 2025 年还在写 Cisco Packet Tracer 6.0 的安装教程先说一个很现实的问题:Packet Tracer 现在都出到 8.x 了,官方下载页也早就把新版本放在最显眼的位置,为什么我还要专门写一篇 6.0 的安装和汉化教程?原因很简单——6.… · 2026/9/25 6:56:35
昇腾Atlas 300V 24G部署YOLO全流程:模型转换与推理实战指南 在AI推理这条路上摸爬滚打几年,手头最近分到一张华为昇腾Atlas 300V 24G运算加速卡,任务是在它上面把YOLO模型跑起来。说实话,一开始我也挺懵,网上关于Atlas部署YOLO的资料不是太零散就是讲得太理想化,真正能照着做的少… · 2026/9/25 6:56:29
Kubernetes Agent调度与Gateway实战:ax架构从零搭建指南 1. 从"ax"这个标题说起:一个被低估的Agent调度入口第一次看到"ax"这个标题,很多人会以为是某个命令行工具的缩写,或者某个内部代号。但把热搜词摊开来看——ax调度、agent、kubernetes、workspace、gateway——这几个词凑… · 2026/9/25 6:56:29
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37