20

我需要将时间码刻录到视频中,并且想知道这是否是 ffmpeg 能够做到的?

4

7 回答 7

34

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 作为输出编解码器,并且没有指定字体等。在这种情况下,时间码被刻录在帧的左上角。

于 2012-09-03T08:27:57.557 回答
20

@stib的答案中提到的 drawtext 过滤器是插入时间的关键。但是,使用该选项与挂钟时间不匹配。如果您弄错了 (timecode_rate) 参数,那么您的时间将与您的播放时间不匹配。timecoder

存在其他选项,例如该text='%{prt}'选项允许您以微秒精度显示经过的时间。命令:

ffmpeg -i video.mp4 -vf "drawtext=text='%{prt}'" output.mp4

为了获得时钟,我不得不使用不推荐使用的strftime选项。这有一个未记录的basetime选项,可用于以微秒为单位设置开始时间。我在 2013 年 12 月 1 日将开始时间设置为 12:00 PM 的示例(该$(...)部分是由 shell 完成的 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只会绘制第二个文本。如上所示,您可以将过滤器与逗号组合。
于 2013-12-01T15:22:17.433 回答
8

简短的回答,不。

长答案,是的,但不是不使用单独的库来创建带有渲染时间码的帧,透明度填充帧的其余部分,然后使用 FFmpeg 覆盖现有视频上的帧。我不知道该怎么做,但是我敢肯定,如果您有创意,您可以弄清楚。

编辑:我一直在研究这个问题,因为这对我来说是一个有趣的问题/项目。通过编写一个 Perl 脚本,我在解决方案中走得更远,该脚本将为任何给定的视频文件生成一个.srt文件,其中嵌入了时间码,FFmpeg 配置为能够从中读取元数据。它使用Video::FFmpeg库来读取持续时间并将字幕文件保存为${video}.srt. 如果您在以下行中插入以下行,它将使其在 Mplayer 中自动呈现~/.mplayer/config

# select subtitle files automatically in the current directory, all files
# matching the basename of the current playing file
sub-fuzziness=1

仍在研究如何在视频上定位和覆盖渲染的字幕并以相同的格式重新编码。我会更新这篇文章,因为我知道更多。

于 2010-07-03T01:17:10.747 回答
1

在最近的版本中,您可以使用drawtext过滤器(我相信其示例中的“t”是帧的时间戳)来插入文本。它也适用于“当前”系统时间的 srtftime。

于 2012-08-11T05:17:40.563 回答
1

我发现最简单的解决方案是在文件被捕获时显示时钟,而不是它的持续时间,它工作/基于这篇文章,谢谢!/

D:\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

于 2015-08-09T06:13:20.827 回答
1

这是我的解决方案,我相信它是正确的,因为它既避免了手动设置速率,又允许您格式化输出。

ffmpeg -i test.mp4 -vf \
    "drawtext=fontfile=arialbd.ttf:text='%{pts\:gmtime\:0\:%H\\\:%M\\\:%S}'" test.avi

这会生成 HH:MM:SS 格式的印章;您可以使用strftime将其更改为您想要的任何内容。

看起来它会在时间戳中加上gmtime,但事实并非如此。它实际上将视频的当前时间(以秒为单位)提供给 gmtime,生成日期为 1970 年 1 月 1 日,以及午夜后几秒的时间。因此,您只需丢弃日期部分并使用时间部分。

注意 pts 函数中的三重转义冒号,如果你像我上面那样输入它,你必须这样做。您还可以看到,为了简单起见,我复制了 Arial Bold 的字体文件并将其直接放入工作目录。

于 2017-08-12T01:41:38.877 回答
-1

FFMPEG 将能够完成大部分工作,但不会全部打包。使用 FFMPEG,您可以让它按顺序解码所有帧,并为您提供“Presentation Time Stamp”(在某些格式上可能会提供与时间相关的其他元数据,但 PTS 是您要开始寻找的内容.) 然后,您自己将文本实际绘制到解码帧上。我将 Qt 用于类似的事情,通过在带有帧数据的 QImage 上使用 QPainter,但可能有一些其他 API 可以在您发现更明显的图像上绘制。然后,使用 FFMPEG API 制作包含新绘制帧的压缩视频。如果您还想要音频,它会有点复杂。我自己的工作并不真正关心音频,所以我没有费心去学习 API 的音频方面。基本上,当您执行读取循环从文件中获取数据包时,其中一些将是音频。不要像我一样丢弃它们,您需要保留它们并在获得它们时将它们写入输出文件。

我只使用了 C API,而不是 C#,所以我不知道是否有任何特殊的问题需要担心。

于 2010-07-13T02:10:48.130 回答