Подтвердить что ты не робот

Настройка метаданных видеопотока с использованием Ffmpeg

Я использую класс JavaCV FFmpegFrameRecorder для кодирования кадров предварительного просмотра камеры Android в видео.

Целью будет репликация результата следующей командной строки:

ffmpeg -i input.mp4 -metadata:s:v:0 rotate="90" output.mp4

Я модифицировал метод startUnsafe() следующим образом, но ему не удалось создать желаемый результат:

if ((video_st = avformat_new_stream(oc, video_codec)) != null) {
        video_c = video_st.codec();
        video_c.codec_id(oformat.video_codec());
        video_c.codec_type(AVMEDIA_TYPE_VIDEO);
        ...
        AVDictionary avDictionary = new AVDictionary(null);
        av_dict_set(avDictionary, "rotate", "90", 0);
        video_st.metadata(avDictionaty);
        ...
}
...
avformat_write_header(oc, (PointerPointer) null);

Это по-прежнему правильно кодирует видео, но добавленные метаданные никогда не появляются на ffprobe. Если это помогает, кодирование видео - h264.

Кстати, здесь вывод ffprobe:

ffprobe version 2.3.3 Copyright (c) 2007-2014 the FFmpeg developers
  built on Jan 22 2015 18:22:57 with Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/2.3.3 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-nonfree --enable-hardcoded-tables --enable-avresample --enable-vda --cc=clang --host-cflags= --host-ldflags= --enable-libx264 --enable-libfaac --enable-libmp3lame --enable-libxvid --enable-libfreetype --enable-libvorbis --enable-libvpx --enable-libass --enable-ffplay --enable-libfdk-aac --enable-libopus --enable-libquvi --enable-libx265
  libavutil      52. 92.100 / 52. 92.100
  libavcodec     55. 69.100 / 55. 69.100
  libavformat    55. 48.100 / 55. 48.100
  libavdevice    55. 13.102 / 55. 13.102
  libavfilter     4. 11.100 /  4. 11.100
  libavresample   1.  3.  0 /  1.  3.  0
  libswscale      2.  6.100 /  2.  6.100
  libswresample   0. 19.100 /  0. 19.100
  libpostproc    52.  3.100 / 52.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'abcd.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf56.15.102
  Duration: 00:00:19.48, start: 0.023220, bitrate: 572 kb/s
    Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 1280x720, 573 kb/s, 5.71 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 64 kb/s (default)
    Metadata:
      handler_name    : SoundHandler

Любые предложения о том, почему это не удается? Спасибо.

4b9b3361

Ответ 1

Кажется, этот вопрос вызвал большой интерес, поэтому я добавляю дополнительную информацию. После этого проблема GitHub Самюэль из JavaCV совершил некоторые изменения, которые позволят более легкий доступ к настройкам метаданных.

Установка метаданных может быть достигнута с помощью следующего фрагмента кода:

AVDictionary metadata = new AVDictionary(null);
for (Entry<String, String> e : videoMetadata.entrySet()) {
    av_dict_set(metadata, e.getKey(), e.getValue(), 0);
}
video_st.metadata(metadata);

Вы можете включить его прямо сейчас, выполнив mvn install -Pffmpeg или дождитесь следующего выпуска JavacV, который должен быть 0.12.

PS: Как вы можете видеть, это очень похоже на то, что я представил в моем вопросе, поэтому я не уверен, почему это не сработало в первую очередь.

Ответ 2

В FFmpegFrameRecorder class, который вы используете, используется AVFormatContext класс. Вокруг строки 2579 вы можете видеть из сигнатур метода, что класс AVFormatContext использует собственный код для реализации как

  • public native AVDictionary metadata() метод
  • public native AVFormatContext metadata(AVDictionary metadata).

Ответ на указанную вами ссылку говорит, что они использовали свойство metadata для AVFormatContext напрямую - что-то вроде первого метода, который я думаю. Но линия 649 FFmpegFrameRecorder использует второй метод - я подозреваю. то есть:.

AVDictionary metadata = new AVDictionary(null);
... code to fill up dictionary ...
...

avformat_write_header(oc.metadata(metadata), options);

К сожалению, я не могу попробовать это в данный момент, но мне интересно, можете ли вы сделать что-то вроде этого:

AVDictionary metadata = co.metadata();
... code to fill up dictionary ...

//I would assume at this point that oc has the metadata so
avformat_write_header(oc, (PointerPointer) null);
//if not then maybe
// avformat_write_header(oc.metadata(metadata), options);

Подпись показывает, что она общедоступна, поэтому я не понимаю, почему вы не можете напрямую получить словарь метаданных из AVFormatContext. Я не уверен, как работает метод avformat_write_header, поэтому я предложил две вещи выше.

Примечание. Я использовал не эту библиотеку. Я пробовал, безуспешно использовать Xuggler в прошлом для некоторой базовой кодировки.