使用ffmpeg保存PCM文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用ffmpeg保存PCM文件相关的知识,希望对你有一定的参考价值。


说明

  1. PCM是音频解码后的文件。或者说经过音频经过采样后形成的二进制文件。
  2. 对人来说,能听到的是20HZ-20KHZ,这也是次声波和超声波的分界线。
  3. 根据采样定理,2倍最高频率就可以还原,加速滤波器带来的畸变,44.1KHZ采样已经可以了。48KHZ以上的采样率,人已经无法分辨差异了。
  4. 保存PCM文件时使用的是采用有符号16位保存,而源音频不一定是,所以需要转换。

ffmpeg中的音频相关内容

概述

ffmpeg中AVPacket中可能会含有多个音频帧(AVFrame),一个音频帧含有多个采样,采样率决定了1s有多少个采样(或者说一个音频帧可以播放多久)。对于aac,一帧有1024个采样,mp3一帧则固定为1152个字节。

参数

AVPacket:音频或视频包,由成员stream_index区分。
AVFrame: 存储音频帧解码后的数据。
AVCodecContext->sample_fmt:采样格式,也就是数据存储格式:有无符号、位数等。
AVCodecContext->sample_rate:采样率
AVCodecContext->channel_layout:声道布局,也就是单声道,双声道,立体声。
AVFrame->nb_samples:这个音频帧含有多少个采样。

音频帧占用内存计算:

根据声道数、采样个数、采样格式可以计算出音频帧占用内存大小。

av_samples_get_buffer_size(NULL, 声道数,采样个数,采样格式, 1);

ffmpeg转换PCM格式步骤

  1. 设置转换参数SwrContext,包括声道数、采样率、采样格式 。
  2. 解码音频帧数据。
  3. 计算转换后内存占用大小并分配buf 。
  4. 使用swr_convert转换帧数据。
  5. 将数据写入文件。

示例代码

转换设置

SwrContext *swrCtx = swr_alloc();                               //音频重采样上下文

enum AVSampleFormat in_sample_fmt = pACodecCtx->sample_fmt; //输入的采样格式
int in_sample_rate = pACodecCtx->sample_rate; //输入的采样率
uint64_t in_ch_layout = pACodecCtx->channel_layout; //输入的声道布局

enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16; //输出的采样格式 16bit PCM
int out_sample_rate = 44100; //输出的采样率
uint64_t out_ch_layout = AV_CH_LAYOUT_MONO; //输出的声道布局
int out_channel_nb = av_get_channel_layout_nb_channels(out_ch_layout); //输出的声道个数

swr_alloc_set_opts(swrCtx, out_ch_layout, out_sample_fmt, out_sample_rate, in_ch_layout, in_sample_fmt, in_sample_rate, 0, NULL);
swr_init(swrCtx);

转码与存储

if (avPacket.stream_index == AUDIO_INDEX) 
AVPacket->AVFrameret = avcodec_decode_audio4(pACodecCtx, avFrame, &got_frame, &avPacket);if (ret < 0) printf("%s", "解码完成");

//获取对应参数的采样需要占用的内存大小
int out_buffer_size = av_samples_get_buffer_size(NULL, out_channel_nb, avFrame->nb_samples, out_sample_fmt, 1);

//存储pcm数据
uint8_t *out_buffer = (uint8_t *)av_malloc(out_buffer_size);

if (got_frame)
swr_convert(swrCtx, &out_buffer, out_buffer_size, (const uint8_t **)avFrame->data, avFrame->nb_samples);
//写入文件进行测试
fwrite(out_buffer, 1, out_buffer_size, pFile);
av_free(out_buffer);

播放

ffplay -f s16le -ar 44100 -ac 1  test.pcm

参考资料

​​音频帧概念详解​​


以上是关于使用ffmpeg保存PCM文件的主要内容,如果未能解决你的问题,请参考以下文章

FFmpeg命令行将mp3/wav/flac/ape转pcm

Android音视频系列(七):PCM音频单声道与双声道的相互转换

音频编解码基础知识

音频编解码基础知识

音频编解码基础知识

音视频编解码