ffmpeg可以刻录时间码吗?

spi*_*non 16 c# ffmpeg video-processing timecodes

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

sti*_*tib 25

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"
Run Code Online (Sandbox Code Playgroud)

你必须以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/")
Run Code Online (Sandbox Code Playgroud)

因此,您可以轻松地将它们一起插入批处理脚本中,例如

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
Run Code Online (Sandbox Code Playgroud)

这会将剪辑的名称和滚动时间码添加到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'))}
Run Code Online (Sandbox Code Playgroud)

这创建了mp4s给定一个包含.MOV,.MP4和.MTS文件的文件夹(使用-filter命令查找名称中包含*.M*的文件,如果你在做.AVI文件则必须更改),这是更简单一点,它只使用libx264默认设置作为输出编解码器,并没有指定字体等.在这种情况下,时间码烧在框架的左上角.


Lek*_*eyn 16

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

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

ffmpeg -i video.mp4 -vf "drawtext=text='%{prt}'" output.mp4
Run Code Online (Sandbox Code Playgroud)

为了获得时钟,我不得不使用已弃用的strftime选项.这有一个未记录的basetime选项,可用于设置以微秒为单位的开始时间.我将开始时间设置为2013年12月1日中午12点(该$(...)部分由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
Run Code Online (Sandbox Code Playgroud)

\\:用于转义:,否则将获得选项分隔符的含义.

另一个例子:在黑盒子中插入日期+时间的命令,远离左上角的一些像素和"一些填充"(实际上,边缘上有两个空格和换行符):

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
Run Code Online (Sandbox Code Playgroud)

另一个让时间低于微秒的例子:

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
Run Code Online (Sandbox Code Playgroud)

这使用了这样的事实:文本实际上是三行,并且两个文本都有一个^M前缀和附加的换行符(回车符).(没有这个换行符,空间被剥离)

其他提示:

  • -vf并且-filter:v是平等的.
  • 您不能多次指定过滤器,例如,-vf drawtext=text=1 -vf drawtext=text=2只会绘制第二个文本.您可以将过滤器与逗号结合使用,如上所示.


amp*_*ine 8

简短的回答,没有。

答案很长,是的,但不是不使用单独的库来创建带有渲染时间码的帧,透明填充帧的其余部分,然后使用 FFmpeg 将帧覆盖在现有视频上。在我的脑海里,我不知道该怎么做,但我相信如果你有创意,你可以想出来。

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

# select subtitle files automatically in the current directory, all files
# matching the basename of the current playing file
sub-fuzziness=1
Run Code Online (Sandbox Code Playgroud)

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

  • 显然,现在可以使用视频过滤器。见 https://gist.github.com/reidransom/2630650 (2认同)