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 协议。

相关推荐
动物园猫1 小时前
驾驶员危险行为目标检测数据集:3类别、14,000张图像 | 目标检测
人工智能·目标检测·计算机视觉
Zenova EdgeOS1 小时前
储能项目 BOT 模式演变:从单一建设到全周期运营的多元路径
大数据·人工智能
TMT星球1 小时前
萤石亮相IFA 2026,多款AI创新产品集中展示,全球化智能生活体验引关注
大数据·人工智能·生活
知了一笑1 小时前
Token消费不为结果买单
人工智能·aigc·token
deepdata_cn1 小时前
机器学习≠逻辑推理!分清统计AI与符号AI
人工智能·机器学习
大鹏的NLP博客1 小时前
拆解 Agent Memory:从认知心理学映射到工业级工程落地
人工智能·agent·memory
蓝速科技1 小时前
固定涉外场景台式翻译机选型与落地指南
网络·人工智能·自然语言处理·语音识别·技术分享
棣廷1 小时前
初识OpenCV——特征匹配与综合实战
人工智能·opencv·计算机视觉
aneasystone本尊1 小时前
学习大模型推理的两个阶段:Prefill 与 Decode
人工智能