97 个 OpenCV 实例(二十一):音频进阶,音视频同抽与麦克风采集

上一篇把 VideoCapture 的两个冷门输入补齐了------图像序列和音频。这一篇在音频上再往前走一层:上一课只从文件里抽音频,这一课把视频和音频一起抽,还把输入源从「文件」换成「麦克风」。官方 samples 里 videocapture_audio_combination 和 videocapture_microphone 正好对应这两步。它们和前一篇的 audio 加起来,是官方音频采集的一条完整递进线。

一、三个音频示例的递进

官方音频相关的三个示例,其实是同一套 API 的三次递进:

示例 输入源 视频流 演示重点
videocapture_audio 文件 禁用 只抽音频
videocapture_audio_combination 文件 启用 音视频同抽
videocapture_microphone 设备 0 禁用 麦克风采集

看懂这一张表,三个示例的差异就清楚了:前两个都是读文件,差别在「要不要视频流」;第三个把文件换成麦克风设备。核心 API 就那几样,反复在用。

二、音视频同抽:一个开关的事

上一课抽音频,params 里把视频流设成 -1(禁用)。这一课要音视频一起抽,只要把它改成 0:

cpp 复制代码
vector<int> params { CAP_PROP_AUDIO_STREAM, 0,     // 选音频流
                     CAP_PROP_VIDEO_STREAM, 0,      // 0 = 也要视频
                     CAP_PROP_AUDIO_DATA_DEPTH, CV_16S };

就这一个数字,从「只抽音频」变成「音视频同抽」。然后 grab 一次、retrieve 多次:

cpp 复制代码
if (cap.grab()) {
    cap.retrieve(videoFrame);                          // 先解视频帧
    for (int nCh = 0; nCh < channels; nCh++)
        cap.retrieve(audioFrame, baseIndex + nCh);     // 再解每路音频
    imshow("Live", videoFrame);                        // 视频帧还能实时显示
}

这就是 grab/retrieve 分离的价值------一帧里既有视频又有音频,grab 只抓一次原始数据,retrieve 按通道分别解码,视频和每一路音频互不干扰。视频帧还能顺手 imshow 显示出来,边抽边看。

三、麦克风采集:设备号 0 + 定时

把输入从文件换成麦克风,open 的第一个参数从路径改成设备号:

cpp 复制代码
cap.open(0, CAP_MSMF, params);   // 0 = 默认麦克风

这个 0 和 VideoCapture(0) 里的摄像头设备号是同一套编号体系,只是走音频流。麦克风没有「文件路径」的概念,固定采默认设备。

采多久?官方用 tick 计时,采满 10 秒自动停:

cpp 复制代码
const double cvTickFreq = getTickFrequency();
int64 sysTimeCurr = getTickCount();
int64 sysTimePrev = sysTimeCurr;
while ((sysTimeCurr - sysTimePrev) / cvTickFreq < 10) {  // 采满 10 秒
    if (cap.grab()) { ... }
    sysTimeCurr = getTickCount();
}

这个公式 (t1 - t0) / getTickFrequency() 就是「经过的秒数」。上一篇测帧率是它的正用,这里反过来做「定时采集」------采固定时长而不是固定帧数。同一个公式,两个用法。

四、一个顺带发现的官方笔误

读源码时发现官方 sample 里有个小笔误:变量名写成了 numberOfSamles(少了字母 p,应为 Samples)。不影响运行,只是累加采样点的计数器名字拼错了。读官方源码时遇到这种小瑕疵不用慌,看清它干什么就行。

五、实测

这两个实例在 Linux 上都没跑通------它们和上一篇 audio 一样,用的是 CAP_MSMF 后端,这是 Microsoft Media Foundation,Windows 专属。Linux 上能编译过,但一运行就报错:combination 报 ERROR! Can't to open file,microphone 报 ERROR! Can't to open microphone,都是 exit 255。

所以官方音频三个示例在 Linux 下都只能按源码分析来学。它们的价值不在「能在 Linux 跑通」,而在「理解 grab/retrieve 分离 + CAP_PROP_AUDIO_* 参数」这套 API 设计。真要在 Linux 上采音频,得换 CAP_ANY 或 FFmpeg 后端,而且 OpenCV 在 Linux 上的音频采集能力本身就有限。

六、踩坑记录

坑 现象 正确姿势
视频流开关记反 想同抽却只抽到音频 CAP_PROP_VIDEO_STREAM 设 0 启用、-1 禁用
多流不判空 推入空 Mat 污染数据 retrieve 后各自 empty() 判空
麦克风当文件传 传路径打不开 麦克风用设备号 0
tick 定时算错 采不满或超时 (t1-t0)/freq 得秒数
照搬 CAP_MSMF Linux 报错 跨平台换 CAP_ANY,别用 Windows 专属后端

七、AI 与 LLM Wiki:这一课沉淀了什么

这一课照例新增「音频进阶」概念页,两条硬要求一个不少------API 汇总表列了音视频同抽和麦克风采集用到的全部接口,从 open 的三参数重载、到 grab/retrieve、到一组 CAP_PROP_AUDIO_* 属性;demo 语法分析把两个源码逐块拆透,重点讲了 CAP_PROP_VIDEO_STREAM 的 0/-1 语义、麦克风设备号、tick 定时采集的公式、范围 for 遍历。

最有意思的是那张「三个音频示例递进表」------AI 学知识库不满足于单个示例,而是把相关的几个示例串起来找递进关系,一次看清一个 API 家族的完整用法。这种「横向串联」比单个示例的「纵向深挖」更能建立体系。

进度表上两个实例勾选完成,从 41 个变成 43 个,进度 44%。

写在最后

97 个实例,今天完成第 43 个,进度 44%。这一站把音频线走完了:抽音频、音视频同抽、麦克风采集,一个 API 家族三种用法。下一篇收尾第三阶段的重头戏------videocapture_gstreamer_pipeline,用 GStreamer 管道字符串自定义采集和写入,测不同后端的编解码性能,380 行的官方大示例一次拆透。

本文示例代码均出自 OpenCV 官方 samples,遵循 Apache 2.0 协议。

相关推荐
lucas_AI9 分钟前
Agent 基准也会烂:Terminal-Bench 三成任务有缺陷,修复后分数集体上涨 10 个点
人工智能·agent
AI源码10 分钟前
基于深度学习的日常服饰分类与推荐系统设计
人工智能·深度学习·分类
johnsong8 小时前
AI前沿日报 · 2026-10-31 | 安全失守——当AI工具被下毒、当云端门户洞开
人工智能·安全
得帆低代码PaaS10 小时前
企业级 Agent 架构:MCP、Integration、数据与治理能力
大数据·人工智能·架构·ai agent·企业数字化·mcp
一条大祥脚11 小时前
TVM 的前世今生:从深度学习编译器到 AI 基础设施
人工智能·深度学习·tvm
9527华安11 小时前
FPGA纯verilog实现DP视频接口,支持2K60帧分辨率,提供3套工程源码和技术支持
fpga开发·音视频·dp
冬奇Lab11 小时前
一天一个开源项目(第255篇):Mika —— 装在安卓手机里的 AI 代理,在后台虚拟屏上替你操作 App 和网页
人工智能·开源·资讯
孟健13 小时前
实测 agent-desktop:AI 控制桌面不截图、不占鼠标键盘,连点 55 次计算器 0 失误
人工智能·架构·开源
MUSHANGXS13 小时前
大模型时代的新蓝海-基于OS底层的AI-Agent应用
人工智能·职场和发展·交互
伞伞悦读13 小时前
【第76期】两张3行表左连接变5行:主键、validate与未匹配排查完整教程
人工智能·python