【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原理