Dan*_*Dan 4 audio ffmpeg libavcodec libav libavformat
我正在考虑重新混合一些保存音频和视频的容器,以便提取最好的第一个音频流,并将其存储在一个新容器中,例如仅存在音频流。
\n\nFFmpeg 的输出上下文是这样创建的:
\n\nAVFormatContext* output_context = NULL;\navformat_alloc_output_context2( &output_context, NULL, "mp4", NULL );\nRun Code Online (Sandbox Code Playgroud)\n\n我有一个可接受的输出的候选列表,例如 MP4、M4A 等 \xe2\x80\xa6 基本上是 Apple 的音频文件服务可读的输出:
\n\nkAudioFileAIFFType = \'AIFF\',\nkAudioFileAIFCType = \'AIFC\',\nkAudioFileWAVEType = \'WAVE\',\nkAudioFileSoundDesigner2Type = \'Sd2f\',\nkAudioFileNextType = \'NeXT\',\nkAudioFileMP3Type = \'MPG3\', // mpeg layer 3\nkAudioFileMP2Type = \'MPG2\', // mpeg layer 2\nkAudioFileMP1Type = \'MPG1\', // mpeg layer 1\nkAudioFileAC3Type = \'ac-3\',\nkAudioFileAAC_ADTSType = \'adts\',\nkAudioFileMPEG4Type = \'mp4f\',\nkAudioFileM4AType = \'m4af\',\nkAudioFileM4BType = \'m4bf\',\nkAudioFileCAFType = \'caff\',\nkAudioFile3GPType = \'3gpp\',\nkAudioFile3GP2Type = \'3gp2\',\nkAudioFileAMRType = \'amrf\'\nRun Code Online (Sandbox Code Playgroud)\n\n我的问题是:FFmpeg 中是否有一个简单的 API,可以根据音频流所在的编解码器来选择兼容的输出容器?
\n有一个动态的方法可以解决这个问题。这枚举了每个容器的编解码器,但您也得到了相反的结果:
// 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
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您只需要特定的容器或编解码器,您可以将白名单与它们name或id字段一起使用,并在枚举时使用它。