文章目录
- 1.使用命令行实现采集PCM数据
- 2.使用代码实现
- 3.播放PCM
- 4.PCM转换为WAV
1.使用命令行实现采集PCM数据
-
确保你的系统有FFmpeg安装。你可以通过在终端运行
ffmpeg -version
来检查是否已安装。 -
找出你的麦克风设备名。在Linux中,你可以使用
arecord -l
命令列出所有的音频录制设备。 -
使用FFmpeg录制音频。下面是一个基本的命令示例,它使用FFmpeg从麦克风捕获音频并将其保存为PCM格式的文件:
ffmpeg -f alsa -i hw:0 -acodec pcm_s16le -ar 44100 -ac 2 output.pcm
-f alsa
: 指定使用ALSA音频框架。-i hw:0
: 指定输入设备,hw:0
根据你的arecord -l
结果而定。-acodec pcm_s16le
: 指定音频编解码器为PCM 16位小端格式。-ar 44100
: 设置音频采样率为44100Hz。-ac 2
: 设置音频通道数为2(立体声)。output.pcm
: 指定输出文件名。
-
执行命令。复制并粘贴上述命令到你的终端中,根据需要修改输入设备。按下回车键开始录制,使用Ctrl+C停止录制。
确保你有足够的权限来访问麦克风设备。如果遇到权限问题,可能需要以root用户执行命令或修改用户权限设置。
2.使用代码实现
实现步骤:
1. 包含必要的库
代码首先通过extern "C"
包含了FFmpeg库的头文件,保证了C++编译器能够正确地处理这些C语言编写的库。
2. 注册设备和初始化
使用avdevice_register_all()
注册所有可用的设备和编解码器,以便FFmpeg能够识别和使用它们。然后,初始化一个AVPacket
来存储从设备读取的数据。
3. 设置日志级别
通过av_log_set_level(AV_LOG_INFO)
设置日志级别,这样FFmpeg在运行时会提供信息级别的日志输出,有助于调试和跟踪问题。
4. 打开音频输入设备
使用av_find_input_format("alsa")
查找ALSA音频设备格式,并尝试用avformat_open_input()
打开指定的音频设备(在这个例子中是"default",即系统默认音频设输入设备)。注:Linux是使用alsa,Windows上使用dshow,MacOs上使用avfoundation
5. 打开输出文件
创建并打开一个文件output.pcm
用于写入捕获的音频数据。
6. 读取和保存音频数据
通过一个循环使用av_read_frame()
从音频设备中读取数据,每次读取的数据被存储在之前初始化的AVPacket
中。随后将这些数据写入到之前打开的输出文件中。循环继续执行,直到读取了5000个数据包或遇到读取错误。
7. 清理资源
在录制完成后,关闭输出文件,释放与音频设备关联的AVFormatContext
,并关闭输入流。这一步骤确保所有打开的资源得到适当的管理和释放。
extern "C"
{
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <libavutil/audio_fifo.h>
#include <libavcodec/avcodec.h>
}
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{AVFormatContext *formatCtx = NULL;AVInputFormat *inputFormat;AVPacket packet;int ret;FILE *outputFile;// 注册所有设备avdevice_register_all();// 初始化数据包av_init_packet(&packet);// 设置日志级别av_log_set_level(AV_LOG_INFO);// 寻找 ALSA 音频设备inputFormat = av_find_input_format("alsa");if (!inputFormat){fprintf(stderr, "Cannot find input device\n");return -1;}// 打开音频设备if ((ret = avformat_open_input(&formatCtx, "default", inputFormat, NULL)) < 0){av_log(NULL, AV_LOG_ERROR, "Cannot open input device\n");return -1;}outputFile = fopen("output.pcm", "wb");if (!outputFile){fprintf(stderr, "Could not open output file\n");return -1;}int count = 0;// 读取数据包while ((ret = av_read_frame(formatCtx, &packet)) >= 0 && count++ <5000){// 在这里处理捕获的音频数据cout << "packet size is " << packet.size << endl;fwrite(packet.data, 1, packet.size, outputFile); // Write raw audio dataav_packet_unref(&packet);}// Clean upfclose(outputFile);// 清理avformat_close_input(&formatCtx);avformat_free_context(formatCtx);return 0;
}
3.播放PCM
生成的PCM为纯二进制数据,没有关键信息头,如果想要播放这段数据,可以使用ffplay制定采样的参数来播放,在Linux中一般默认的参数为
-f alsa
: 指定使用ALSA音频框架。-i hw:0
: 指定输入设备,hw:0
根据你的arecord -l
结果而定。-acodec pcm_s16le
: 指定音频编解码器为PCM 16位小端格式。-ar 44100
: 设置音频采样率为44100Hz。-ac 2
: 设置音频通道数为2(立体声)。output.pcm
: 指定输出文件名。
命令示例:
ffplay -f s16le -ar 48000 -ac 1 input.pcm
可以看出来ffplay 已经成功将二进制数据转换为模拟信号进行播放了
4.PCM转换为WAV
如果不清楚什么是PCM和WAV 请看这篇blog
可以使用ffmpeg 通过添加参数的方式将PCM数据转换为WAV格式,以供各种播放器进行播放。
ffmpeg -f s16le -ar 44100 -ac 2 -i output.pcm output.wav