使用 Ffmpeg 设置视频流元数据
Posted
技术标签:
【中文标题】使用 Ffmpeg 设置视频流元数据【英文标题】:Setting video stream metadata using Ffmpeg 【发布时间】:2015-07-10 11:47:45 【问题描述】:我正在使用 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
关于它为什么失败的任何建议?谢谢。
【问题讨论】:
类似问题:***.com/questions/17024192/… 【参考方案1】:似乎这个问题引起了很多兴趣,所以我添加了更多信息。在 JavaCV committed 的 GitHub issue Samuel 之后进行了一些更改,以便更轻松地访问元数据设置。
设置元数据可以通过以下代码sn -p实现:
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
class。在第 2579 行附近,您可以从方法签名中看到,AVFormatContext
类使用本机代码来实现两者
public native AVDictionary metadata()
方法
public native AVFormatContext metadata(AVDictionary metadata)
方法。
您提供的链接的答案说他们直接使用了AVFormatContext
的metadata
属性-类似于我认为的第一种方法。但是FFmpegFrameRecorder
的第 649 行使用了第二种方法——我怀疑。即:
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 进行一些基本编码,但未成功。
【讨论】:
以上是关于使用 Ffmpeg 设置视频流元数据的主要内容,如果未能解决你的问题,请参考以下文章
如何从 .mp3 文件中获取元数据并使用 FFmpeg 将其作为文本放入视频中?
ffmpeg vs mediainfo 用于获取缩略图和元数据
视频转码成mp4格式,添加关键帧,添加元数据,把元数据放在第一帧