【ffmpeg】音频采集
- 前言
- 通过命令采集音频数据
- 采集音频的方式
- windows下采集音频
- 通过API采集音频数据
- 打开音频设备
- 从音频设备中读取音频数据
- API,数据封装简析
- 代码
- 录制音频数据
- 参考资料
个人简介
个人主页:一二三o-0-O的博客
技术方向:C/C++客户端资深工程师(直播+音视频剪辑)
作者简介:数据结构算法与音视频领域创作者
系列专栏:ffmpeg入门
专栏目标:务实的掌握FFmpeg相关专业知识
如果对您有帮助的话,欢迎点赞收藏,关注不迷路
前言
如果是刚刚开始学习音视频的伙伴,可以先看看音视频基 础专栏系列的内容,掌握音视频相关的一些基础理论。
音视频基础专栏系列
(一)【音视频基础】音频基础理论
(二)【音视频基础】视频基础理论
(三)【音视频基础】封装格式与编码数据
如果觉得理论学习枯燥的伙伴,可以先通过以下四篇文章使用ffmpeg实现一个播放器,可以获得些许成就感,为持续在音视频领域扎根打好兴趣基础。
ffmpeg专栏系列
(一)【ffmpeg】ffmpeg命令工具的使用
(二)【ffmpeg】视频解码器
(三)【ffmpeg】SDL视频显示
(四)【ffmpeg】ffmpeg+SDL实现播放器
下面正式开始使用ffmpeg采集音频数据。
通过命令采集音频数据
采集音频的方式
- Android
- AudioRecorder
- MediaRecoder
- IOS
- AudioUnit
- AVFoundation
- Windows
- DirectShow
- OpenAL
- AudioCore
windows下采集音频
- 首先要获取windows设备的信息,使用下面的命令
./ffmpeg -list_devices true -f dshow -i dummy
运行后会得到所有的设备信息如下图所示:
- 然后选择使用音频采集设备采集音频,使用下列命令行:
./ffmpeg -f dshow -i audio=“麦克风 (6- Logitech USB Headset H340)” out.wav
采集过程如下图,会默认使用16位、44.1K采样率以及双声道的采样数据进行采集:
- 然后在同级目录生成wav的音频文件,可以使用ffmplay进行播放,确认与自己刚刚录制的音频是否一致,如下图所示:
通过API采集音频数据
API与命令行的流程是一致的:
- 首先打开音频设备
- 然后从音频设备中读取PCM数据
- 最后将PCM数据录制下来
打开音频设备
使用ffmpeg4.2.2版本+Qt GUI框架
//音频设备QString sDeviceName = "audio=" + QString("麦克风 (6- Logitech USB Headset H340)");//vecDeviceName[0];//ffmpegint ret = 0;char errors[1024];// 声明上下文AVFormatContext *fmt_ctx = nullptr;//注册音频设备avdevice_register_all();//设置windows下的音频采集formatconst AVInputFormat *iformat = av_find_input_format("dshow");// 打开音频设备if ((ret = avformat_open_input(&fmt_ctx, sDeviceName.toUtf8().data(), iformat, &options)) < 0) { av_strerror(ret, errors, 1024); qDebug() << QString("Failed to open audio device, [%1]%2\n").arg(ret).arg( errors);}
从音频设备中读取音频数据
API,数据封装简析
- av_read_frame
- 读取音视频数据(本节只读取音频数据)
- AVformatContext:上下文,判断是从音视频设备还是从媒体文件中读取数据
- AVPacket:数据包(本节只是音频包)
- 返回0表示成功
- AVPacket
- data:存具体的数据
- size:缓冲区的大小
- 与AVPacket相关的API
- av_init_packet:初始化
- av_packet_unref:释放初始化的资源,与av_init_packet成对使用
- av_packet_alloc:申请资源、并调用av_init_packet初始化
- av_packet_free:释放资源,与av_packet_alloc成对使用
代码
int count{};// 声明数据包AVPacket pkt;// 初始化数据包av_init_packet(&pkt);// 从设备中读取数据包while ((ret = av_read_frame(fmt_ctx, &pkt)) == 0 && count <= 500) { qDebug() << "pkt size is:" << pkt.size;}// 释放数据包av_packet_unref(&pkt);
录制音频数据
// 声明文件QFile file("D:\\msys64\\home\\Administrator\\ffmpegDemon\\bin\\debug\\exercise\\record.pcm");// 打开文件if (!file.open(QIODevice::Truncate | QIODevice::WriteOnly)) { qDebug() << "open failed"; return;}// 从设备中读取数据包while ((ret = av_read_frame(fmt_ctx, &pkt)) == 0 && count <= 500) { qDebug() << "pkt size is:" << pkt.size;// 写文件 file.write((const char *)pkt.data, pkt.size);}av_packet_unref(&pkt);// 关闭文件file.close();
参考资料
【1】雷神博客
【2】ffmpeg官方文档
【3】李超:音视频基础+ffmpeg原理