我正在寻找重新复制一些容纳音频和视频的容器,以便我提取最好的第一音频流,并将其存储在一个新的容器中,例如,只有音频流存在。
FFmpeg的输出上下文的创建方式如下:
AVFormatContext* output_context = NULL;
avformat_alloc_output_context2( &output_context, NULL, "mp4", NULL );
我有一份可接受的输出名单,例如: MP4,M4A等......基本上是Apple的音频文件服务可读取的:
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
。
有一个动态的方法来解决这个问题。这枚举了每个容器的编解码器,但你也得到了反转:
// enumerate all codecs and put into list
std::vector<AVCodec*> encoderList;
AVCodec * codec = nullptr;
while (codec = av_codec_next(codec))
{
// try to get an encoder from the system
auto encoder = avcodec_find_encoder(codec->id);
if (encoder)
{
encoderList.push_back(encoder);
}
}
// enumerate all containers
AVOutputFormat * outputFormat = nullptr;
while (outputFormat = av_oformat_next(outputFormat))
{
for (auto codec : encoderList)
{
// only add the codec if it can be used with this container
if (avformat_query_codec(outputFormat, codec->id, FF_COMPLIANCE_STRICT) == 1)
{
// add codec for container
}
}
}
如果您只想要特定的容器或编解码器,可以使用带有name
或id
字段的白名单,并在枚举时使用它。