使用ffmpeg保存PCM文件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用ffmpeg保存PCM文件相关的知识,希望对你有一定的参考价值。
说明
- PCM是音频解码后的文件。或者说经过音频经过采样后形成的二进制文件。
- 对人来说,能听到的是20HZ-20KHZ,这也是次声波和超声波的分界线。
- 根据采样定理,2倍最高频率就可以还原,加速滤波器带来的畸变,44.1KHZ采样已经可以了。48KHZ以上的采样率,人已经无法分辨差异了。
- 保存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格式步骤
- 设置转换参数SwrContext,包括声道数、采样率、采样格式 。
- 解码音频帧数据。
- 计算转换后内存占用大小并分配buf 。
- 使用swr_convert转换帧数据。
- 将数据写入文件。
示例代码
转换设置
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