本文使用FFmpeg + SoundTouch实现将音频解码后,进行变调变速处理,并将处理后的结果保存为WAV文件。
主要有以下内容:
- 实现一个FFmpeg的工具类,保存多媒体文件所需的解码信息
- 将解码后的音频保存为WAV文件
- SoundTouch的使用指南
1.从视频文件中提取音频保存为WAV文件
本小节实现从视频文件中提取音频,解码并保存为WAV文件。
在使用FFmpeg解码时,一般的流程是:
- 打开一个多媒体文件流
- 得到媒体流信息
- 查找视频、音频流的index
- 根据流的index查找相应的的CODEC,打开
AVCodecContext
进行完以上操作后,就得到解码所需的各种信息:AVFormateContext
、AVCodecContext
以及对应流的index。也就说,这些数据是解码多媒体流的必须信息,所以这里对上述操作做一个封装,提供一个单一接口来获取解码所需的信息。
1.1 MediaInfo工具类
在使用FFmpeg进行解码的时候,所需要的信息如下:
AVFormatContext
AVCodecContext
- 流的index
MediaInfo
的声明如下:
class CMediaInfo
{
public:
CMediaInfo();
CMediaInfo(MEDIA_TYPE media);
~CMediaInfo();
public:
ERROR_TYPE open(const char *filename);
void close();
void error_message(ERROR_TYPE error);
public:
MEDIA_TYPE type;
AVFormatContext *pFormatContext;
AVCodecContext *pVideo_codec_context;
AVCodecContext *pAudio_codec_context;
int video_stream_index;
int audio_stream_index;
};
- 构造函数需要一个参数,指出该类中包含的信息为视频、音频或者音视频都包含;
open
方法,根据传入的多媒体文件填充各个字段信息;close
方法,关闭打开的AVFormatContext
和AVCodecContext
等。- 字段 为解码所需的各类信息。
至于具体的实现,可参考前面的文章 ,在最后会提供本文使用的代码,这里不再多说。
1.2 从视频中提取音频
1.2.1 获取解码所需的信息
使用上面的提供的MediaInfo
工具类,首先根据视频文件路径填充MediaInfo
的各个字段
char* filename = "E:\\Wildlife.wmv";
CMediaInfo media(MEDIA_TYPE::AUDIO);
media.open(filename);
1.2.2 设置音频的保存格式
在真正的提取解码之前,需要首先设置好要保存的WAV的音频格式。FFmpeg使用SwrContext
设置音频的转换格式,具体代码如下:
AVSampleFormat dst_format = AV_SAMPLE_FMT_S16;
uint8_t dst_channels = 2;
auto dst_layout = av_get_default_channel_layout(dst_channels);
auto audio_ctx = media.pAudio_codec_context;
if (audio_ctx->channel_layout <= 0)
audio_ctx->channel_layout = av_get_default_channel_layout(audio_ctx->channels);
SwrContext *swr_ctx = swr_alloc();
swr_alloc_set_opts(swr_ctx, dst_layout, dst_format, audio_ctx->sample_rate,
audio_ctx->channel_layout, audio_ctx->sample_fmt, audio_ctx->sample_rate, 0, nullptr);
if (!swr_ctx || swr_init(swr_ctx))
return -1;
这里设置音频的sample格式为16位的有符号整数,通道数为2通道,采样率不变,具体关于音频格式的转换可参考: FFmpeg学习4:音频格式转换。