linux下使用ffmpeg采集音频数据

  • Post author:
  • Post category:linux


本文讲解如何在linux下面采集音频数据,分成3部分讲解。

  1. 采集音频所需的软硬件环境。
  2. 如何使用ffmpeg命令采集音频。
  3. 如何使用ffmpeg代码采集音频。



软硬件环境

使用ffmpeg来采集音频数据,主要需要2个软硬件环境:

  1. 硬件环境,需要有一个录音设备,我这里使用的是麦克风,并且插入了机箱后面的粉色圆孔中(绿色圆孔是耳机/喇叭的接口)。
  2. 软件环境,需要安装ffmpeg。可以使用软件源中编译好的ffmpeg,也可以自己编译安装ffmpeg。

    这两个环境具备了,本文后面内容才具备可行性。



使用ffmpeg命令采集音频

使用ffmpeg来采集音频,我们首先需要知道,如何访问麦克风,这个其实我们可以像访问文件一样,访问麦克风。文件的话,我们一般给出一个文件路径,就可以访问了,比如“/home/test/a.mp4”,同理,我们的麦克风的地址是“hw:0”,我只知道是这个地址,不知道为什么是这个地址,假如大家有知道为什么的,欢迎留言交流。

其次,我们需要知道,麦克风这个文件格式是什么?对于麦克风这种硬件设备,与其说是格式,我更觉得这是驱动程序。在linux上,通用的音频驱动程序,就是alsa。

这样的话,我们很容易形成了下面这样的命令:


ffmpeg -f alsa -i hw:0 out.wav


这里, -f 指定格式(驱动程序)为alsa, -i 指出文件路径,这里是麦克风地址“hw:0”,最后一个是输出文件路径,这里为当前路径下,保存为 out.wav文件。

我们在终端运行这条命令之后,然后对着麦克风讲话“123456”,然后按q结束录音,就可以看到当前路径下面,生成了 out.wav。然后我们使用


ffplay out.wav


播放这段录音,就可以听到刚刚我们喊的“123456”。



使用ffmpeg代码采集音频

使用ffmpeg代码来采集音频,其实也就和上面命令行一样,需要注意上面个两个内容:

  1. 麦克风地址“hw:0”
  2. 麦克风格式(驱动)“alsa”。

然后我们像正常的打开文件一样,采用avformat_open_input 函数,打开文件(这里是麦克风),设置好文件格式(这里是alsa驱动程序)。打开这个文件之后,我们使用av_read_frame从这个文件(麦克风)中读取数据,最后把读取到的数据,保存在文件中。下面分3个部分讲解这些内容:

  1. 打开麦克风
  2. 读取麦克风数据
  3. 将数据保存为文件



打开麦克风

由于我们这里,打开了麦克风设备,在这之前,需要先注册所有的设备,通过调用

avdevice_register_all()

来注册。然后就是像正常打开文件一样,调用

avformat_open_input

打开文件。文件路径为“hw:0”,文件格式为通过

av_find_input_format

找到的alsa的AVInputFormat,这样,就会构造出我们想要的fmt_ctx。

AVFormatContext *fmt_ctx = NULL; 
char *devicename =  "hw:0";
avdevice_register_all();
AVInputFormat *iformat = av_find_input_format("alsa");
avformat_open_input(&fmt_ctx, devicename, iformat, NULL)
avformat_close_input(&fmt_ctx);



读取麦克风数据

读取麦克风数据,就通过

av_read_frame

,把前面的fmt_ctx对应的数据,读取出来就行。读取完的数据,保存在AVPacket pkt的 data里面,长度为pkt.size。

 int ret = 0;
AVPacket pkt;
av_init_packet(&pkt);
while(ret = (av_read_frame(fmt_ctx, &pkt))== 0) {
	        av_log(NULL, AV_LOG_INFO, "pkt size is %d(%p)\n",
            	pkt.size,pkt.data);
            av_packet_unref(&pkt);
}



保存文件

保存文件,就比较简单了,把pkt.data,通过fwrite写到文件中去即可。

    char *out = "./audio.pcm";
    FILE *outfile = fopen(out,"wb+");
    fwrite(pkt.data, 1, pkt.size, outfile);
     fclose(outfile);



全部代码

下面贴上所有代码。保存为record_audio.c 文件。

#include <stdio.h>
#include "libavutil/avutil.h"
#include "libavdevice/avdevice.h"  //打开音频设备相关的头文件
#include "libavformat/avformat.h"  //ffmpeg下的所有文件都是以格式来呈现的


void main(int argc, char **argv)
{
    int ret = 0;
    char errors[1024] = {0};
    //context
    AVFormatContext *fmt_ctx = NULL;   //ffmpeg下的“文件描述符”

    //paket
    int count = 0;
    AVPacket pkt;

    //create file
    char *out = "./audio.pcm";
    FILE *outfile = fopen(out,"wb+");

    char *devicename =  "hw:0";
    //register audio device
    avdevice_register_all();

    //get format
    AVInputFormat *iformat = av_find_input_format("alsa");

    //open audio
    if( (ret = avformat_open_input(&fmt_ctx, devicename, iformat, NULL)) < 0)
    {
        av_strerror(ret, errors, 1024);
        printf("Failed to open audio device, [%d]%s\n", ret, errors);
        return;
    };

    av_init_packet(&pkt);
    //read data form audio
    while(ret = (av_read_frame(fmt_ctx, &pkt))== 0&& 
        count++ < 500) {
        av_log(NULL, AV_LOG_INFO, "pkt size is %d(%p), count=%d\n",
            pkt.size,pkt.data, count);
        fwrite(pkt.data, 1, pkt.size, outfile);
        fflush(outfile);
        av_packet_unref(&pkt);//release pkt
    }

    fclose(outfile);
    avformat_close_input(&fmt_ctx);//releas ctx
    return;
}

然后通过命令

gcc record_audio.c -lavformat -lavutil -lavdevice -lavcodec -o record_audio

生成可执行文件。

然后执行 ./record_audio, 并录音。录音结果保存在audio.pcm文件中。

然后通过命令


ffplay -ar 44100 -ac 2 -f s16le audio.pcm


播放此音频,发现结果正常。

上面命令解析

-ar 表示 audio sampling rate,即音频采样率,为44100 Hz。

-ac表示 audio channels,即音频通道数,一般为2,左声道和右声道。

-f s16le,表示采样大小为 有符号的 16位 小端字节序。 signed 16 bit little endian。



版权声明:本文为snail_hunan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。