【问题标题】:Text on video ffmpeg视频ffmpeg上的文字
【发布时间】:2013-07-11 12:19:15
【问题描述】:

如何在 ffmpeg 中的视频上添加文本覆盖?

即给定一个视频“video1.flv”,如何在整个视频中添加“StackOverflow”文本,位于屏幕中间,带有白色文本和边框?

【问题讨论】:

  • 看here。天然橡胶6
  • @bitWorking - 我看到你的评论已经有 3 年历史了,但我仍然请求你不要侮辱和浪费 stackoverflow 社区成员的时间与你混淆的“让我为你谷歌”链接.特别是当您介绍递归时(我通过谷歌搜索来到这里)。此外,使用 URL 缩短可以隐藏潜在的恶意软件或垃圾邮件链接,因为您将不知道指向何处。

标签: ffmpeg


【解决方案1】:

这是所有 4 个方向的叠加过渡的备忘单...

************************* Text **********************

1) left to right given x=41 position 

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -vf "[in]drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text='Hi': y=53.48 :x=min(t*250-2*250\,41): fontsize=35: fontcolor=yellow: enable='between(t,2,10)', drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text='Ajeet': y=53.48 :x=min(t*250-3*250\,90): fontsize=35: fontcolor=yellow: enable='between(t,3,10)' [out]" -t 11 leftToRight.mp4




2) right to left given x=41 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -vf "[in]drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text='Hi': y=53.48 :x=w-min(t*250-2*250\,(w\-41)): fontsize=35: fontcolor=yellow: enable='between(t,2,10)', drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text='Ajeet': y=53.48 :x=w-min(t*250-3*250\,(w\-90)): fontsize=35: fontcolor=yellow: enable='between(t,3,10)' [out]" -t 11 rightToLeft.mp4




3) top to bottom given y=58 position 

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -vf "[in]drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text='Hi': x=41 :y=min(t*250-2*250\,53.48): fontsize=35: fontcolor=yellow: enable='between(t,2,10)', drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text='Ajeet': x=90 :y=min(t*250-3*250\,53.48): fontsize=35: fontcolor=yellow: enable='between(t,3,10)' [out]" -t 11 topToBottom.mp4




4) bottom to up given y=90 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -vf "[in]drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text='Hi': x=41 :y=h-min(t*250-2*250\,(h\-53.48)): fontsize=35: fontcolor=yellow: enable='between(t,2,10)', drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text='Ajeet': x=90 :y=h-min(t*250-3*250\,(h\-53.48)): fontsize=35: fontcolor=yellow: enable='between(t,3,10)' [out]" -t 11 bottomToTop.mp4

************************图片*********************

1) single left to right given x=41 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -loop 1 -i image.png -filter_complex "[1:v]scale=-2:100[png];[0:v][png]overlay=x=min(t*250-2*250\,41):y=60:shortest=1:enable='between(t,2,10)'" -t 11 imageLeftToRight1.mp4

ffmpeg -y -i 'https://player.vimeo.com/external/181472383.sd.mp4?s=103f42915141758d95a118f070d08190845bdf73&profile_id=164' -loop 1 -i image.png -filter_complex "[1:v]scale=-2:100[png];[0:v][png]overlay=x=min(t*250-2*250\,41):y=60:shortest=1:enable='between(t,2,10)'" -t 11 imageLeftToRight.mp4




2) Already added text then added single image left to right

ffmpeg -y -i leftToRight.mp4 -loop 1 -i image.png -filter_complex "[1:v]scale=-2:100[png];[0:v][png]overlay=x=min(t*250-2*250\,41):y=200:shortest=1:enable='between(t,2,10)'" -t 11 imageTextLeftToRight.mp4




3) 2 images left to right given x=41, x=100 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -loop 1 -i image.png -loop 1 -i image2.png -filter_complex "[1]scale=-2:100[img1];[2]scale=-2:100[img2];[0][img1]overlay=x=min(t*250-2*250\,41):y=60:enable='between(t,2,10)':shortest=1[o1];[o1][img2]overlay=x=min(t*250-3*250\,100):y=200:enable='between(t,3,10)':shortest=1" -t 11  multiImageLeftToRight.mp4




4) 3 images left to right given x=41, x=100, x=300 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -loop 1 -i image.png -loop 1 -i image2.png -loop 1 -i image3.png -filter_complex "[1]scale=-2:100[img1];[2]scale=-2:100[img2];[3]scale=-2:100[img3];[0][img1]overlay=x=min(t*250-2*250\,41):y=60:enable='between(t,2,10)':shortest=1[o1];[o1][img2]overlay=x=min(t*250-3*250\,130):y=130:enable='between(t,3,10)':shortest=1[o2];[o2][img3]overlay=x=min(t*250-4*250\,260):y=190:enable='between(t,4,10)':shortest=1" -t 11  threeImageLeftToRight.mp4




5) 3 images right to left given x=41, x=100, x=300 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -loop 1 -i image.png -loop 1 -i image2.png -loop 1 -i image3.png -filter_complex "[1]scale=-2:100[img1];[2]scale=-2:100[img2];[3]scale=-2:100[img3];[0][img1]overlay=x=W-min(t*250-2*250\,(W\-41)):y=60:enable='between(t,2,10)':shortest=1[o1];[o1][img2]overlay=x=W-min(t*250-3*250\,(W\-130)):y=130:enable='between(t,3,10)':shortest=1[o2];[o2][img3]overlay=x=W-min(t*250-4*250\,(W\-260)):y=190:enable='between(t,4,10)':shortest=1" -t 11  threeImageRightToLeft.mp4




6) 3 images top to bottom given y=41, y=100, y=300 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -loop 1 -i image.png -loop 1 -i image2.png -loop 1 -i image3.png -filter_complex "[1]scale=-2:100[img1];[2]scale=-2:100[img2];[3]scale=-2:100[img3];[0][img1]overlay=x=41:y=min(t*250-2*250\,60):enable='between(t,2,10)':shortest=1[o1];[o1][img2]overlay=x=130:y=min(t*250-3*250\,130):enable='between(t,3,10)':shortest=1[o2];[o2][img3]overlay=x=260:y=min(t*250-4*250\,190):enable='between(t,4,10)':shortest=1" -t 11  threeImageTopToBottom.mp4




7) 3 images bottom to top given y=41, y=100, y=300 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -loop 1 -i image.png -loop 1 -i image2.png -loop 1 -i image3.png -filter_complex "[1]scale=-2:100[img1];[2]scale=-2:100[img2];[3]scale=-2:100[img3];[0][img1]overlay=x=41:y=H-min(t*250-2*250\,(H\-60)):enable='between(t,2,10)':shortest=1[o1];[o1][img2]overlay=x=130:y=H-min(t*250-3*250\,(H\-130)):enable='between(t,3,10)':shortest=1[o2];[o2][img3]overlay=x=260:y=H-min(t*250-4*250\,(H\-190)):enable='between(t,4,10)':shortest=1" -t 11  threeImageBottomToTop.mp4

************************ GIF *********************

1) single left to right given x=41 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -ignore_loop 0 -i gif1.gif -filter_complex "[1:v]scale=-2:100[ovrl];[0:v][ovrl]overlay=x=min(t*250-2*250\,41):y=60:enable='between(t,2,10)'" -t 11 gifLeftToRight.mp4




2) double left to right given x=41 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -ignore_loop 0 -i gif1.gif -ignore_loop 0 -i gif2.gif -ignore_loop 0 -i gif3.gif -filter_complex "[1]scale=-2:100[gif1];[2]scale=-2:100[gif2];[0][gif1]overlay=x=min(t*250-2*250\,41):y=60:enable='between(t,2,10)':shortest=1[o1];[o1][gif2]overlay=x=min(t*250-3*250\,150):y=170:enable='between(t,3,10)':shortest=1" -t 11 doubleGifLeftToRight.mp4




3) three left to right given x=41 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -ignore_loop 0 -i gif1.gif -ignore_loop 0 -i gif2.gif -ignore_loop 0 -i gif3.gif -filter_complex "[1]scale=-2:100[gif1];[2]scale=-2:100[gif2];[3]scale=-2:100[gif3];[0][gif1]overlay=x=min(t*250-2*250\,41):y=60:enable='between(t,2,10)':shortest=1[o1];[o1][gif2]overlay=x=min(t*250-3*250\,150):y=170:enable='between(t,3,10)':shortest=1[o2];[o2][gif3]overlay=x=min(t*250-4*250\,240):y=240:enable='between(t,4,10)':shortest=1" -t 11 threeGifLeftToRight.mp4



3) three right to left given x=41 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -ignore_loop 0 -i gif1.gif -ignore_loop 0 -i gif2.gif -ignore_loop 0 -i gif3.gif -filter_complex "[1]scale=-2:100[gif1];[2]scale=-2:100[gif2];[3]scale=-2:100[gif3];[0][gif1]overlay=x=W-min(t*250-2*250\,(W\-41)):y=60:enable='between(t,2,10)':shortest=1[o1];[o1][gif2]overlay=x=W-min(t*250-3*250\,(W\-150)):y=170:enable='between(t,3,10)':shortest=1[o2];[o2][gif3]overlay=x=W-min(t*250-4*250\,(W\-240)):y=240:enable='between(t,4,10)':shortest=1" -t 11 threeGifRightToLeft.mp4




3) three top to bottom given x=41 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -ignore_loop 0 -i gif1.gif -ignore_loop 0 -i gif2.gif -ignore_loop 0 -i gif3.gif -filter_complex "[1]scale=-2:100[gif1];[2]scale=-2:100[gif2];[3]scale=-2:100[gif3];[0][gif1]overlay=x=41:y=min(t*250-2*250\,60):enable='between(t,2,10)':shortest=1[o1];[o1][gif2]overlay=x=150:y=min(t*250-3*250\,170):enable='between(t,3,10)':shortest=1[o2];[o2][gif3]overlay=x=240:y=min(t*250-4*250\,240):enable='between(t,4,10)':shortest=1" -t 11 threeGifTopToBottom.mp4




3) three bottom to top given x=41 position

ffmpeg -y -i 'https://player.vimeo.com/external/181545195.sd.mp4?s=176d502710df829442a83565bb79efbe3c9c0b93&profile_id=164' -ignore_loop 0 -i gif1.gif -ignore_loop 0 -i gif2.gif -ignore_loop 0 -i gif3.gif -filter_complex "[1]scale=-2:100[gif1];[2]scale=-2:100[gif2];[3]scale=-2:100[gif3];[0][gif1]overlay=x=41:y=H-min(t*250-2*250\,(H\-60)):enable='between(t,2,10)':shortest=1[o1];[o1][gif2]overlay=x=150:y=H-min(t*250-3*250\,(H\-170)):enable='between(t,3,10)':shortest=1[o2];[o2][gif3]overlay=x=240:y=H-min(t*250-4*250\,(H\-240)):enable='between(t,4,10)':shortest=1" -t 11 threeGifBottomToTop.mp4

【讨论】:

    【解决方案2】:

    使用drawtext filter 在视频中添加简单的文字。如果您需要更复杂的计时、格式或动态文本,请参阅subtitles filter。这个答案侧重于drawtext过滤器。

    示例

    以白色文本将Stack Overflow 打印到视频中心,黑色背景框不透明度为 50%:

    ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/font.ttf:text='Stack Overflow':fontcolor=white:fontsize=24:box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)/2:y=(h-text_h)/2" -codec:a copy output.mp4
    
    • 在此示例中,音频是流式复制的(类似于复制和粘贴)。
    • @0.5 控制背景框的不透明度。 0.5 是 50%。如果您不想要任何透明度,请删除 @0.5。
    • 请参阅drawtext filter documentation 以获取完整的选项列表和说明。

    预览

    您可以使用ffplay 预览您的文本,而无需等待文件编码:

    ffplay -vf "drawtext=fontfile=/path/to/font.ttf:text='Stack Overflow':fontcolor=white:fontsize=24:box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)/2:y=(h-text_h)/2" input.mp4
    

    您也可以使用mpv,但syntax 略有不同:

    mpv --vf="lavfi=[drawtext=fontfile=/path/to/font.ttf:text='Stack Overflow':fontcolor=white:fontsize=24:box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)/2:y=(h-text_h)/2]" input.mp4
    

    多个文本

    您可以链接多个绘图文本过滤器:

    ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/font.ttf:text='Stack Overflow':fontcolor=white:fontsize=24:box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)/2:y=(h-text_h)/2,drawtext=fontfile=/path/to/font.ttf:text='Bottom right text':fontcolor=black:fontsize=14:x=w-tw-10:y=h-th-10" -codec:a copy output.mp4
    

    位置

    x 和y 确定文本位置:

    Position x:y With 10 px padding
    Top left x=0:y=0 x=10:y=10
    Top center x=(w-text_w)/2:y=0 x=(w-text_w)/2:y=10
    Top right x=w-tw:y=0 x=w-tw-10:y=10
    Centered x=(w-text_w)/2:y=(h-text_h)/2
    Bottom left x=0:y=h-th x=10:y=h-th-10
    Bottom center x=(w-text_w)/2:y=h-th x=(w-text_w)/2:y=h-th-10
    Bottom right x=w-tw:y=h-th x=w-tw-10:y=h-th-10
    Random See this answer

    按需重新定位文本

    您可以使用 sendcmd 和 zmq 过滤器重新定位文本:

    移动/动画/循环/滚动文本

    见:

    时间

    使用enable option 控制文本出现的时间。

    在 5-10 秒之间显示文本:

    ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/font.ttf:text='Stack Overflow':fontcolor=white:fontsize=24:box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)/2:y=(h-text_h)/2:enable='between(t,5,10)'" -codec:a copy output.mp4
    

    3秒后显示文字:

    ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/font.ttf:text='Stack Overflow':fontcolor=white:fontsize=24:box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)/2:y=(h-text_h)/2:enable='gte(t,3)'" -codec:a copy output.mp4
    

    闪烁的文字。每 10 秒显示文本 5 秒:

    ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/font.ttf:text='Stack Overflow':fontcolor=white:fontsize=24:box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)/2:y=(h-text_h)/2:enable='lt(mod(t,10),5)'" -codec:a copy output.mp4
    

    每 30 秒随机位置:

    见ffmpeg - Dynamic letters and random position watermark to video?

    更改/更新文本

    为drawtext添加textfile和reload选项:

    ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/font.ttf:textfile=text.txt:reload=1:fontcolor=white:fontsize=24:box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)/2:y=(h-text_h)/2" -codec:a copy output.mp4
    
    • 每次您希望更改文本时更新text.txt。
    • 重要提示:您必须自动更新文本文件,否则可能会失败。您可以在 Linux 或 macOS 上使用 mv 命令执行此操作。
    • 如果文字改动较多,比如制作字幕,制作字幕文件(比如通过Aegisub制作.ass文件)并使用subtitles filter会更容易。

    字体系列而不是字体文件

    您可以声明字体系列,例如 Times New Roman,而不必指向字体文件。见How to include font in FFMPEG command without using the fontfile option?

    要求

    drawtext 过滤器需要ffmpeg 与--enable-libfreetype 一起编译。如果您得到No such filter: 'drawtext',则缺少--enable-libfreetype。大多数可用的ffmpeg 静态构建都支持这一点:请参阅FFmpeg Download 页面以获取链接。

    【讨论】:

    • @NoahTernullo 您还可以使用 strftime 选项和“pts”变量。就让它在底部滚动而言,您可能可以使用一些函数来根据 pts 或帧数更改 x 变量值。
    • @chovy 你的ffmpeg 需要用--enable-libfreetype 构建。
    • 仅供参考,对于使用 brew 安装的用户,您可以将该标志 --with-libefreetype 传递给安装命令。
    • @chovy 我认为你提到的自制选项应该是--with-freetype
    • 添加:enable='between(t,00:00:15,00:00:20) 指定文本持续时间,类似于ffmpeg -i part02.mp4 -vf drawtext="text='Stack Overflow': fontcolor=white: fontsize=24: box=1: boxcolor=black@0.5: \ boxborderw=5: x=(w-text_w)/2: y=(h-text_h)/2: enable='between(t,00:00:15,00:00:20)" -codec:a copy output.mp4
    【解决方案3】:

    在 macOS 上启用='between(t,0,10)'

    在 macOS 上,enable='between(t,start_second, end_seconds)' 的语法不同。输入应该以秒为单位,而不是 hh:mm:ss。

    我的 ffmpeg 版本 4.3.1

    ffmpeg -i input.mp4 -vf "drawtext=text='My Text':enable='between(t,20,120)': x=(w-text_h)/2: y=(h-text_h)/2: fontsize=32: fontcolor=white: box=1: boxcolor=black@0.5: boxborderw=5:" -c:a copy output.mp4
    

    【讨论】:

      猜你喜欢
      • 2019-01-07
      • 1970-01-01
      • 2018-05-06
      • 2013-04-19
      • 2013-10-16
      • 2016-09-06
      • 1970-01-01
      • 2016-06-16
      • 2023-04-06
      相关资源
      最近更新 更多