Estoy buscando volver a mezclar algunos contenedores que contienen audio y video de modo que extraiga la mejor, la primera transmisión de audio y la almacene en un nuevo contenedor donde, por ejemplo, solo la transmisión de audio está presente.

El contexto de salida para FFmpeg se crea así:

AVFormatContext* output_context = NULL;
avformat_alloc_output_context2( &output_context, NULL, "mp4", NULL );

Tengo una lista de resultados aceptables, p. Ej. MP4, M4A, etc ... esencialmente aquellos que son legibles por los servicios de archivos de audio de 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'

Mi pregunta es la siguiente: ¿hay una API fácil en FFmpeg que se pueda aprovechar para elegir un contenedor de salida compatible dado el códec en el que se encuentra la transmisión de audio?

1
Dan 14 nov. 2017 a las 05:28

2 respuestas

La mejor respuesta

Para cada muxer individual, generalmente hay una función de escritura de etiquetas de códec. Esa función se comparará con una lista en otro archivo fuente o funcionará a través de una declaración switch en el mismo. No hay una lista central o una función de utilidad de comparación de contenedores. Su mejor opción es identificar el ID del códec en libavcodec/allcodecs.c y luego grep en libavformat/ para ese ID, particularmente dentro de los archivos con el sufijo enc, p. matroskaenc.c.

1
Gyan 14 nov. 2017 a las 04:56

Hay un enfoque dinámico para ese problema. Esto enumera los códecs para cada contenedor, pero también obtiene lo inverso:

// 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
        }
    }
}

Si solo desea contenedores o códecs específicos, puede usar una lista blanca con sus campos name o id y usar eso al enumerar.

2
Bim 14 feb. 2019 a las 13:09