我正在考虑重新复制一些容纳音频和视频的容器,以便我提取最好的第一个音频流,并将其存储在一个新的容器中,例如, 仅音频流存在。
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,可以利用音频流所在的编解码器来选择兼容的输出容器?
答案 0 :(得分:2)
有一个动态的方法可以解决这个问题。这枚举了每个容器的编解码器,但您也会得到相反的结果:
// 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
字段使用,并在枚举时使用。
答案 1 :(得分:1)
对于每个单独的复用器,通常都有一个编解码器标签写入功能。该功能将检查另一个源文件中的列表,或者通过相同的switch
语句进行处理。没有中央名册或容器匹配效用函数。您最好的选择是在libavcodec/allcodecs.c
中识别编解码器ID,然后在libavformat/
中为该ID识别,特别是在以enc为后缀的文件中,例如matroskaenc.c
。