Audio 如何确定编解码器/容器组合是否与FFmpeg兼容?

Audio 如何确定编解码器/容器组合是否与FFmpeg兼容?,audio,ffmpeg,libavcodec,libav,libavformat,Audio,Ffmpeg,Libavcodec,Libav,Libavformat,我正在考虑重新混合一些保存音频和视频的容器,以便提取最好的第一个音频流,并将其存储在一个新的容器中,例如,仅存在音频流 FFmpeg的输出上下文是这样创建的: AVFormatContext* output_context = NULL; avformat_alloc_output_context2( &output_context, NULL, "mp4", NULL ); 我有一份可接受输出的短名单,例如MP4、M4A等……基本上是苹果音频文件服务可以读取的输出: kAudioFi

我正在考虑重新混合一些保存音频和视频的容器,以便提取最好的第一个音频流,并将其存储在一个新的容器中,例如,仅存在音频流

FFmpeg的输出上下文是这样创建的:

AVFormatContext* output_context = NULL;
avformat_alloc_output_context2( &output_context, NULL, "mp4", NULL );
我有一份可接受输出的短名单,例如MP4、M4A等……基本上是苹果音频文件服务可以读取的输出:

kAudioFileAIFFType              = 'AIFF',
kAudioFileAIFCType              = 'AIFC',
kAudioFileWAVEType              = 'WAVE',
kAudioFileSoundDesigner2Type    = 'Sd2f',
kAudioFileNextType              = 'NeXT',
kAudioFileMP3Type               = 'MPG3',   // mpeg layer 3
kAudioFileMP2Type               = 'MPG2',   // mpeg layer 2
kAudioFileMP1Type               = 'MPG1',   // mpeg layer 1
kAudioFileAC3Type               = 'ac-3',
kAudioFileAAC_ADTSType          = 'adts',
kAudioFileMPEG4Type             = 'mp4f',
kAudioFileM4AType               = 'm4af',
kAudioFileM4BType               = 'm4bf',
kAudioFileCAFType               = 'caff',
kAudioFile3GPType               = '3gpp',
kAudioFile3GP2Type              = '3gp2',
kAudioFileAMRType               = 'amrf'

我的问题是:在FFmpeg中是否有一个简单的API,可以根据音频流所在的编解码器选择一个兼容的输出容器,通常有一个编解码器标签写入功能。该功能将对照另一个源文件中的列表进行检查,或通过同一个源文件中的
switch
语句进行操作。没有中心花名册或容器匹配实用程序功能。您最好的办法是在
libavcodec/allcodecs.c
中识别编解码器id,然后在
libavformat/
中对该id进行grep,特别是在后缀为enc的文件中,例如
matroskaenc.c

有一种动态方法可以解决该问题。这将枚举每个容器的编解码器,但也会得到相反的结果:

//枚举所有编解码器并放入列表
std::矢量编码器列表;
AVCodec*codec=nullptr;
while(编解码器=av_编解码器_下一个(编解码器))
{
//尝试从系统中获取编码器
自动编码器=avcodec\u find\u编码器(编解码器->id);
中频(编码器)
{
编码器列表。推回(编码器);
}
}
//列举所有容器
AVOutputFormat*outputFormat=nullptr;
while(outputFormat=av_of format_next(outputFormat))
{
用于(自动编解码器:编码器列表)
{
//仅添加可与此容器一起使用的编解码器
if(avformat\u query\u codec(outputFormat,codec->id,FF\u COMPLIANCE\u STRICT)==1)
{
//为容器添加编解码器
}
}
}

如果您只需要特定的容器或编解码器,您可以在其
名称
id
字段中使用白名单,并在枚举时使用该白名单。

以下资源似乎表明某些音频编解码器可嵌入MP4容器中,但我遇到了一些问题,例如MP4中的MP3,有意思的是……例如,我在
isom.c
中找到了FFmpeg似乎与MP4相关的音频编解码器列表,以及其他类似列表。看起来我必须自己运行一些匹配的代码,或者在组合失败时使用回退策略。有更好的方法。请看我的答案。我尝试了这个,它似乎返回了合理的结果,但是对于某些格式
avformat\u query\u codec(outputFormat,codec->id,FF\u COMPLIANCE\u STRICT)
对于所有编解码器返回-1,因此这些格式不支持编解码器。值得注意的是,
mp3
格式没有支持的编解码器。我原以为会支持AVCODEC
libmp3lame
mp3
之一。在命令行上,我可以毫无问题地执行
ffmpeg-I输入-c:libmp3lame-f mp3输出.mp3