我需要在视频中加入时间码,想知道ffmpeg是否有这种功能?
我需要在视频中加入时间码,想知道ffmpeg是否有这种功能?
FFMPEG的drawtext过滤器适用于我,你可以这样指定起始时间码和其格式:
-vf drawtext="fontsize=15:fontfile=/Library/Fonts/DroidSansMono.ttf:\
timecode='00\:00\:00\:00':rate=25:text='TCR\:':fontsize=72:fontcolor='white':\
boxcolor=0x000000AA:box=1:x=860-text_w/2:y=960"
你需要在时间码格式中指定hh:mm:ss[:;,]ff的形式。请注意,必须转义时间码格式字符串中的冒号,并指定时间码速率(这里是25fps)。您还可以指定其他文本-此处为“TCR:”
您可以使用ffprobe和一些shell fu来获取帧率:
frame_rate=$(ffprobe -i "movie.mov" -show_streams 2>&1|grep fps|sed "s/.*, \([0-9.]*\) fps,.*/\1/")
因此,您可以轻松地将所有内容插入批处理脚本中进行处理,例如:
for i in *.mov
frame_rate=$(ffprobe -i "$i" -show_streams 2>&1|grep fps|sed "s/.*, \([0-9.]*\) fps,.*/\1/")
clipname=${(basename "$i")/\.*/}
ffmpeg -i "$i" -vcodec whatever -acodec whatever \
-vf drawtext="fontsize=15:fontfile=/Library/Fonts/DroidSansMono.ttf:\
timecode='00\:00\:00\:00':rate=$frame_rate:text='$clipname' TCR:':\
fontsize=72:fontcolor='white':boxcolor=0x000000AA:\
box=1:x=860-text_w/2:y=960" "${i/.mov/_tc.mov}"
done
这将在1920x1080的帧的底部中心以半透明框的形式添加剪辑名称和滚动时间编码。
编辑 由于我现在使用Windows Powershell环境,因此我使用以下内容:
ls -R -File -filter *.M*|%{
ffmpeg -n -i $_.fullname -vf drawtext="fontsize=72:x=12:y=12:`
timecode='00\:00\:00\:00':rate=25:fontcolor='white':`
boxcolor=0x000000AA:box=1" `
("c:\path\to\destination\{0}" -F ($_.name -replace 'M[OPT][V4S]', 'mp4'))}
这个命令会根据含有 .MOV、.MP4 和 .MTS 文件的文件夹生成 mp4 文件(使用 -filter
命令查找文件名中包含 *.M* 的文件,如果你要处理 .AVI 文件则需要更改)。它的设置比较简单,只使用 libx264 作为输出编解码器,并且不指定字体等其他参数。在这种情况下,时间码会被烧录在帧的左上角。
12.34 fps
这样的分数。 - Lekensteyntimecode
选项不能匹配实际时间。如果你将r
(timecode_rate)参数设置错误,则时间不会与播放时间匹配。text ='%{prt}'
选项允许您以微秒精度显示经过的时间。命令:ffmpeg -i video.mp4 -vf "drawtext=text='%{prt}'" output.mp4
为了获得一个时钟,我不得不使用已弃用的strftime
选项。这个选项有一个未记录在文档中的basetime
选项,可以用来设置微秒级别的起始时间。以下是一个示例,我在2013年12月1日中午12点设置了起始时间($(...)
部分是由shell执行的扩展),并仅显示时间(请参见strftime手册以获取可能的格式):
ffmpeg -i video.mp4 -vf "drawtext=expansion=strftime: \
basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \
text='%H\\:%S\\:%S'" output.mp4
\\:
用于转义:
,否则会被解释为选项分隔符。
另一个例子:一个命令用于在黑盒子内插入日期+时间,距离左上角一些像素,并在边缘添加"一些填充"(实际上是两个空格和换行符):
newline=$'\r'
ffmpeg -i video.mp4 -vf "drawtext=x=8:y=8:box=1:fontcolor=white:boxcolor=black: \
expansion=strftime:basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \
text='$newline %Y-%m-%d %H\\:%M\\:%S $newline'" output.mp4
获取当前时间戳的微秒示例:
newline=$'\r'
ffmpeg -i video.mp4 -vf "drawtext=expansion=strftime: \
basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \
text='$newline %H\\:%M\\:%S $newline':fontcolor=white:box=1:boxcolor=black, \
drawtext=text='$newline %{pts} $newline': \
y=2*th/3:box=1:fontcolor=white:boxcolor=black:" output.mp4
这个方法利用了文本实际上是三行长的事实,并且两个文本都有一个换行符(回车,^M
)前缀和后缀。(没有这个换行符,空格将被剥离)
其他提示:
-vf
和 -filter:v
是等效的。-vf drawtext=text=1 -vf drawtext=text=2
只会绘制第二个文本。可以像我上面展示的那样用逗号来组合滤镜。ffplay -i video.mp4 -vf drawtext='expansion=normal:text=%{localtime\\:%a %b %d %Y}'
。 - Lekensteyn简短回答,不行。
详细回答是,可以通过使用另一个库来创建带有渲染时间代码的帧,并用透明填充剩余部分,然后使用FFmpeg将这些帧叠加在现有视频上。我头脑中没有具体方法,但我相信如果你有创意,就能想出解决方法。
编辑:我一直在解决这个问题,因为这对我来说是一个有趣的问题/项目。我已经写了一个Perl脚本,它可以为任何一个FFmpeg可以读取元数据的视频文件生成嵌入时间代码的.srt
文件。它使用Video::FFmpeg
库读取持续时间,并将字幕文件保存为${video}.srt
。如果您在~/.mplayer/config
中插入以下行,则可以自动在Mplayer中呈现:
# select subtitle files automatically in the current directory, all files
# matching the basename of the current playing file
sub-fuzziness=1
我正在努力研究如何在视频上定位和叠加渲染的字幕,并在相同格式下重新编码。如果有更多信息,我会更新此帖子。
这是我的解决方案,我相信它是正确的,因为它既避免了手动设置速率,又允许您格式化输出。
ffmpeg -i test.mp4 -vf \
"drawtext=fontfile=arialbd.ttf:text='%{pts\:gmtime\:0\:%H\\\:%M\\\:%S}'" test.avi
gmtime
插入时间戳,但实际上并不是这样。它实际上将视频当前时间(以秒为单位)馈送给gmtime,产生一个日期为1970年1月1日,时间为午夜后多少秒的日期和时间。因此,您只需丢弃日期部分并使用时间部分即可。
请注意pts函数中的三重转义冒号,如果像上面那样输入,则必须这样做。此外,您可以看到我复制了Arial Bold字体文件并将其放入了工作目录中,以简化操作。t
选项。它被命名为 basetime
(http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavfilter/vf_drawtext.c;h=dde3b0a3202d45b82326f1f523673d52eff6236b;hb=HEAD#l190)。无论如何,我无法使其正常工作。 - Lekensteynt
在FFMPEG 4.1中,您可以使用ffmpeg -i input.mp4 -vf drawtext="fontsize=60:fontcolor=yellow:text='%{e\:t*1000}':x=(w-text_w):y=(h-text_h)" output.mp4
。 - bk138D:\Temp\2>ffmpeg.exe -i test.avi -vf "drawtext=fontfile=C\\:/Windows/Fonts/arial.ttf:timecode='00\:20\:10\:00':rate=25:text='TCR\:':fontsize=46:fontcolor=white:x=500:y=50: box=1: boxcolor=0x00000000@1" -f mp4 textts.mp4
时间码非常简单 - 输入起始时间,然后计数就会正常运行!以下示例适用于Windows。
FFMPEG可以完成大部分的工作,但它不会全部打包好。使用FFMPEG,你可以让它按顺序解码所有帧并给出“演示时间戳”(某些格式可能还有其他与时间相关的元数据,但你想要开始时找到PTS)。然后,你需要自己将文本绘制到已解码的帧上。我使用Qt来做类似的事情,通过在带有帧数据的QImage上使用QPainter,但你可能会找到其他API更容易绘制图像。然后,使用FFMPEG API制作一个压缩视频,其中包含你新绘制的帧。如果你还想添加音频,这将会更加复杂。我自己的工作并不关心音频,所以我没有烦恼地学习API的音频方面。基本上,在从文件中获取包的读取循环中,其中一些将是音频。你需要将它们保存并将它们写入输出文件。
我只使用过C API,而不是C#,所以我不知道是否有任何特殊的问题需要担心。