来自电影元数据的ffmpeg和时间码

时间:2014-07-14 19:44:20

标签: ffmpeg

我想添加数码摄像机时间码制作的电影。在相机回放期间可以看到此时间码,一些提取和可视化EXIF元数据的工具也会显示它们。

我很少尝试配置ffmpeg,但只能成功添加CURRENT PC时间,而不是文件中的时间。

ffmpeg -y -i S1480002.MP4 -vf "drawtext=fontfile=arial.ttf :expansion=normal: text=%{metadata\\:creation_time}: \ x=(w-tw)/2: y=h-(2*lh): fontcolor=white@0.8" output.mp4

我需要从输入文件元数据中提取创建时间。 ffprobe这次显示,但ffmpeg不显示。

3 个答案:

答案 0 :(得分:1)

元数据和creation_time之间的冒号必须excessively and painfully转义才能正常工作。试试text=%{metadata\\\\\:creation_time}:

答案 1 :(得分:0)

我认为你必须和我在ffmpeg-user邮件列表上回答的那个人一样......我终于想出了一个使用ffprobe用脚本执行此操作的hackish方法。我不是一个真正的shell程序员,所以请原谅我,如果这里真的很蠢。我刚从几十个stackoverflow帖子拼凑起来,它可以在第2和第7秒之间在视频的右下角覆盖格式化的creation_date。

我的文件中的creation_date似乎是GMT,所以我不得不将它们转换为CDT ......也许这会对你有所帮助。这适用于Mac OSX 10.10.5,您可能需要在其他平台上调整一些内容:

#!/bin/bash

for CURRENT_FILE in *.mov; do
    CREATION_TIME=`ffprobe -v quiet "$CURRENT_FILE" -print_format compact -show_entries format_tags=creation_time`

    # in the format like: "format|tag:creation_time=2015-12-08 16:13:13"
    CDATE=${CREATION_TIME:(25)}

    SECONDS=`TZ="Europe/London" date -j -f "%Y-%m-%d %T" "$CDATE" +%s`
    MY_TIME=`TZ="America/Chicago" date -r $SECONDS +"%Y-%m-%d %I:%M %p"`

    ffmpeg -i "$CURRENT_FILE" -vf "drawtext=enable='between(t,2,7)':fontfile=/Library/Fonts/Microsoft/Arial.ttf:fontcolor=white:fontsize=64:text=\'${MY_TIME}\':x=main_w-(text_w+64):y=main_h-(text_h*2)" -acodec copy -y "../output/$CURRENT_FILE"

done

我终于让这个工作,但我尝试使用concat组装视频,音频关闭,视频播放速度太慢。我一整天都在搞乱这件事,我几乎放弃了。视频处理对于我的巨型磁脑来说太难了。

答案 2 :(得分:0)

首先,确保您的文件具有您希望以ffmpeg可以理解的方式使用的标记。像这样:

ffprobe -i file.jpg -show_entries frames

这将输出如下内容:

.
.
.
[FRAME]
media_type=video
stream_index=0
key_frame=1
pkt_pts=0
pkt_pts_time=0.000000
pkt_dts=0
pkt_dts_time=0.000000
best_effort_timestamp=0
best_effort_timestamp_time=0.000000
pkt_duration=1
pkt_duration_time=0.040000
pkt_pos=N/A
pkt_size=40439
width=501
height=493
pix_fmt=yuvj420p
sample_aspect_ratio=1:1
pict_type=I
coded_picture_number=0
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
[/FRAME]

在此特定示例中,文件中没有创建时间(CreateDate),因此ffm​​peg无法为您执行任何操作。

但现在假设您有一个包含所需元数据的文件。然后,输出将是,例如:

.
.
.
[FRAME]
media_type=video
stream_index=0
key_frame=1
pkt_pts=0
pkt_pts_time=0.000000
pkt_dts=0
pkt_dts_time=0.000000
best_effort_timestamp=0
best_effort_timestamp_time=0.000000
pkt_duration=1
pkt_duration_time=0.040000
pkt_pos=N/A
pkt_size=40681
width=501
height=493
pix_fmt=yuvj420p
sample_aspect_ratio=1:1
pict_type=I
coded_picture_number=0
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
TAG:XResolution=     72:1      
TAG:YResolution=     72:1      
TAG:ResolutionUnit=    2
TAG:DateTime=2015:12:17 19:28:47
TAG:YCbCrPositioning=    1
TAG:ExifVersion= 48,  50,  49,  48
TAG:DateTimeDigitized=2015-01-01 00:00:00
TAG:ComponentsConfiguration=  1,   2,   3,   0
TAG:FlashpixVersion= 48,  49,  48,  48
TAG:ColorSpace=65535
TAG:PixelXDimension=      0
TAG:PixelYDimension=      0
[/FRAME]

在这里,您可以注意到以TAG:为前缀的行。这些是ffmpeg喜欢的行。有了这些,您可以使用:

ffmpeg -f image2 -pattern_type glob -framerate 20 -i "myfiles*.jpg" -filter_complex "drawtext='fontfile=/usr/share/fonts/truetype/msttcorefonts/Arial.ttf:fontsize=32:fontcolor=yellow:borderw=2:bordercolor=black:x=10:y=10:text=%{metadata\:DateTimeDigitized}'" "out.avi"

打破部分:

-f image2

使用" image2"文件分离器。

-pattern_type glob -i "myfiles*.jpg"

获取与全局模式匹配的所有文件" myfiles * .jpg"

drawtext=

启用" drawtext"过滤

fontfile=/usr/share/fonts/truetype/msttcorefonts/Arial.ttf

要使用的字体。

fontsize=32

字体大小。

fontcolor=yellow

字体颜色。

borderw=2

在文字周围画一个2px边框。

bordercolor=black

边境将是黑色的。

x=10

从视频左侧开始播放10px文本。

y=10

从视频顶部开始播放文字10px。

text=%{metadata\:DateTimeDigitized}

要重新定义的文本,在这种情况下,将取自" DateTimeDigitized"元数据,包含在源文件中。

"out.avi"

输出文件名。

嗯,那就是它。希望有所帮助!