FFmpeg音视频开发_录制 PCM

一、FFmpeg 命令行录音

1、查看当前可用设备:

$ ffmpeg -devices

输出如下:

Devices:
D. = Demuxing supported
.E = Muxing supported
--
D  avfoundation    AVFoundation input device
D  lavfi           Libavfilter virtual input device
  E sdl,sdl2        SDL2 output device

在 Mac 平台输出结果中会有 avfoundation ,这是 Mac 平台的多媒体系统库,我们可以使用 avfoundation 操作多媒体输入设备。

2、查看 avfoundation 支持的设备:

$ ffmpeg -f avfoundation -list_devices true -i dummy

输出如下:

[AVFoundation indev @ 0x7fb3bcd10840] AVFoundation video devices:
[AVFoundation indev @ 0x7fb3bcd10840] [0] FaceTime HD Camera
[AVFoundation indev @ 0x7fb3bcd10840] [1] Capture screen 0
[AVFoundation indev @ 0x7fb3bcd10840] [2] Capture screen 1
[AVFoundation indev @ 0x7fb3bcd10840] AVFoundation audio devices:
[AVFoundation indev @ 0x7fb3bcd10840] [0] Built-in Microphone
: Input/output error

列举出了 avfoundation 支持的所有设备,-i dummy命令的作用是立即退出(或者 -i ‘’,或者 -i “”)。Built-in Microphone 是笔记本自带的内建麦克风,也就是我们接下来要使用的录音设备。

3、指定录音设备,开始录音:

$ ffmpeg -f avfoundation -i :0 out.wav

avfoundation 指定视频音频输入设备的语法:

-i "[[VIDEO]:[AUDIO]]"

在 Mac 平台上通过编号指定设备,冒号前是指定的音频设备,后面指定的是音频设备,例如 0:0 代表使用0号视频设备和0号音频设备,因为我们只采集音频,所以仅指定音频设备就可以。

输出如下:

Input #0, avfoundation, from ':0':
  Duration: N/A, start: 28541.967596, bitrate: 2822 kb/s
    Stream #0:0: Audio: pcm_f32le, 44100 Hz, stereo, flt, 2822 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (pcm_f32le (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, wav, to 'out.wav':
  Metadata:
    ISFT            : Lavf58.45.100
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s
    Metadata:
      encoder         : Lavc58.91.100 pcm_s16le
size=    4608kB time=00:00:30.54 bitrate=1235.8kbits/s speed=   1x    

结束录音直接使用 Ctrl + C 即可。可以看到输出到 out.wav 文件的音频参数:
采样率 44100 Hz
声道 2(stereo:立体声)
位深 16
比特率 1411 kb/s

二、FFmpeg 编程方式录音

使用 FFmpeg 录制 PCM 音频主要有五个步骤:

FFmpeg音视频开发_录制 PCM_第1张图片

我们使用到的 FFmpeg 库有 avdevice(设备相关API)、avformat(格式相关API) 和 avutil (工具相关API,比如错误处理)三个:

extern "C" {
    #include  
    #include 
    #include 
}

1、首先初始化 libavdevice,注册所有输入和输出设备,仅需要注册一次:

avdevice_register_all();

2、根据格式名称获取输入格式对象:

#define FMT_NAME “avfoundation”

AVInputFormat *fmt = av_find_input_format(FMT_NAME);
if (!fmt) {
    qDebug() << "获取输入格式对象失败:" << FMT_NAME;
    return;
}

3、打开输入设备,获取到格式上下文:

AVFormatContext *ctx = nullptr;
int ret = avformat_open_input(&ctx, DEVICE_NAME, fmt, nullptr);
if (ret < 0) {
    char errbuf[1024];
    av_strerror(ret, errbuf, sizeof (errbuf));
    qDebug() << "打开输入设备失败:" << errbuf;
    return;
}

返回 0 成功,出错返回负数。我们可以使用 libavutil 库中的 av_strerror 函数获取到错误原因。当音频数据采集完成或者发生错误时我们需要使用 avformat_close_input

函数关闭设备,并释放格式上下文。

4、打开文件:

QFile file(fileName);
if (!file.open(QFile::WriteOnly)) {
    qDebug() << "打开文件失败” << fileName;
    // 文件打开失败,关闭设备
    avformat_close_input(&ctx);
    return;
}

5、采集音频数据:

AVPacket pkt;
while (!isInterruptionRequested()) {
    ret = av_read_frame(ctx, &pkt);
    if (ret == 0) {
        file.write((const char *)pkt.data, pkt.size);
    } else if (ret == AVERROR(EAGAIN)) {
        continue;
    } else {
        char errbuf[1024];
        av_strerror(ret, errbuf, sizeof (errbuf));
        qDebug() << "av_read_frame error:" << errbuf;
    }
    av_packet_unref(&pkt);
}

返回 0 代表读取成功,此时把读取到的数据写入文件。当返回错误 AVERROR(EAGAIN) 时表示资源临时不可用,执行 continue 即可。pkt 不再需要时需要使用 av_packet_unref 函数释放。此处的 pkt 是在栈空间中,我们也可以在堆空间中创建,最后记得调用 av_packet_free 函数释放即可:

AVPacket *pkt = av_packet_alloc();
av_packet_free(&pkt);

6、关闭文件,关闭设备:

file.close();
avformat_close_input(&ctx);

7、查看录制的 PCM 参数:

AVStream *stream = ctx->streams[0];
AVCodecParameters *params = stream->codecpar;
qDebug() << "采样率:" << params->sample_rate;
qDebug() << "声道:" << params->channels;
qDebug() << "位深:" << av_get_bits_per_sample(params->codec_id);

你可能感兴趣的:(FFmpeg音视频开发_录制 PCM)