【问题标题】:Can ffmpeg burn in time code?ffmpeg可以烧录时间码吗?
【发布时间】:2011-03-11 08:09:39
【问题描述】:

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

【问题讨论】:

  • 所以我假设您想将“视频的当前时间”刻录到视频本身?或者您想使用 libav* 在此处使用您自己的时间码向视频添加文本?​​

标签: c# ffmpeg video-processing timecodes


【解决方案1】:

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等分数。
  • 实际上它似乎只适用于frame_rate标准,例如25,必须转码,即使那样,由于某种原因,时间对我来说是错误的。
  • 批处理脚本中有一个错字会强制它使用 25fps,现在已修复。看看进展如何。
  • 另外@ntg,你将不得不转码。不进行转码就无法更改视频光栅的内容。
  • 我不确定你将如何使用 ffprobe 执行此操作,但如果您将其指定为有理数,rate 参数将起作用,因此如果您说“24000/1001”它对我有用。
【解决方案2】:

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

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

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

为了获得时钟,我不得不使用已弃用的 strftime 选项。这有一个未记录的basetime 选项,可用于以微秒 为单位设置开始时间。我将开始时间设置为 2013 年 12 月 1 日下午 12:00 的示例($(...) 部分是由 shell 完成的 shell 扩展)并且只显示时间(参见strftime manual for possible formats):

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 只会绘制第二个文本。如上所示,您可以使用逗号组合过滤器。

【讨论】:

  • “本地时间”选项在这里有帮助吗? ffmpeg.org/pipermail/ffmpeg-user/2014-July/022355.html
  • localtime 没有帮助,它基于本地时间而不是固定时刻。我试过的命令:ffplay -i video.mp4 -vf drawtext='expansion=normal:text=%{localtime\\:%a %b %d %Y}'
  • 这个工作 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='$换行 %{pts} $newline': \ y=2*th/3:box=1:fontcolor=white:boxcolor=black:" output.mp4
【解决方案3】:

简短的回答,不。

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

编辑:我一直在研究这个问题,因为这对我来说是一个有趣的问题/项目。我通过编写a Perl script 在解决方案中走得更远一点,它将生成一个.srt 文件,其中嵌入了时间码,用于将FFmpeg 配置为能够从中读取元数据的任何给定视频文件。它使用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

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

【讨论】:

  • 这是一个有趣的方法。可能会这样做的图书馆的任何线索?如果没有,我可以四处看看。
  • 我应该补充一点,因为你显然在这里做了一些很棒的工作。这就是我最终想要做的是创建一个带有时间码的新视频。因此,不仅要在播放器中播放它们,还要创建一个新视频,以便可以在任何播放器中播放。既然你已经付出了这么多的努力,我会为这个问题添加一个赏金。
  • 显然现在可以使用视频过滤器。见gist.github.com/reidransom/2630650
【解决方案4】:

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

【讨论】:

  • 文档包含错误,没有t 选项。它is named basetime。无论如何,我无法让它正常工作。
  • 是的,显然它已被弃用和删除。其他一些可能有用的东西:你可以使用任何“eval”支持的东西,并为 strftime 的东西提供“frame_num”和“localtime”......
  • my answer to this question,我昨天发现了一些其他的获取时间的方法。 t 似乎是一个文档错误,它应该是 basetime(仅适用于 expansion=strftime)。
  • 其实t在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
【解决方案5】:

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

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

【讨论】:

  • 这行得通,太棒了,顺便说一句,这里的TCR是什么意思
【解决方案6】:

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

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 字体文件并将其直接放入工作目录中。

【讨论】:

    【解决方案7】:

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

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

    【讨论】:

      猜你喜欢
      • 2023-03-09
      • 2022-11-09
      • 1970-01-01
      • 2017-05-11
      • 1970-01-01
      • 2012-02-27
      • 2016-04-11
      • 2020-09-02
      • 2018-07-06
      相关资源
      最近更新 更多