FFmpeg 在多行上绘制文本

发布于 2024-12-17 06:36:44 字数 534 浏览 1 评论 0原文

我有代码:

import subprocess , os

ffmpeg = "C:\\ffmpeg_10_6_11.exe"
inVid = "C:\\test_in.avi"
outVid = "C:\\test_out.avi"

if os.path.exists( outVid ):
os.remove( outVid )
proc = subprocess.Popen(ffmpeg + " -i " + inVid + ''' -vf drawtext=fontfile=/Windows/Fonts/arial.ttf:text="onLine1 onLine2 onLine3":fontcolor=white:fontsize=20 -y ''' + outVid , shell=True, stderr=subprocess.PIPE)
proc.wait()
print proc.stderr.read()
os.startfile( outVid )

将文本写入视频文件。但我想写出多行文本,而不是只将其全部写在一行上。

我怎样才能做到这一点?

I have the code:

import subprocess , os

ffmpeg = "C:\\ffmpeg_10_6_11.exe"
inVid = "C:\\test_in.avi"
outVid = "C:\\test_out.avi"

if os.path.exists( outVid ):
os.remove( outVid )
proc = subprocess.Popen(ffmpeg + " -i " + inVid + ''' -vf drawtext=fontfile=/Windows/Fonts/arial.ttf:text="onLine1 onLine2 onLine3":fontcolor=white:fontsize=20 -y ''' + outVid , shell=True, stderr=subprocess.PIPE)
proc.wait()
print proc.stderr.read()
os.startfile( outVid )

to write text to a video file. But I want to write out many lines of text instead of just having it all on the one line.

How can I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

眼趣 2024-12-24 06:36:44

您可以使用 [in] 标签在一个文件上指定多个绘图文本,并使用逗号列出每个绘图文本。如果您通过各自的定位方法来定位每个绘图文本,则这允许您使用多条线。在您的示例中,命令行将如下所示(将第一行放在屏幕中间,并将后续的每一行向下 25 像素):

ffmpeg -i test_in.avi -vf "[in]drawtext=fontsize=20:fontcolor=White:fontfile='/Windows/Fonts/arial.ttf':text='onLine1':x=(w)/2:y=(h)/2, drawtext=fontsize=20:fontcolor=White:fontfile='/Windows/Fonts/arial.ttf':text='onLine2':x=(w)/2:y=((h)/2)+25, drawtext=fontsize=20:fontcolor=White:fontfile='/Windows/Fonts/arial.ttf':text='onLine3':x=(w)/2:y=((h)/2)+50[out]" -y test_out.avi

You can specify multiple drawtexts on one file by using the [in] tag and listing each drawtext using commas. This allows you to use multiple lines if you orient each drawtext through their respective positioning methods. In your example, the command line would look something like this (puts the first line in the middle of the screen, and puts each subsequent line 25 pixels down):

ffmpeg -i test_in.avi -vf "[in]drawtext=fontsize=20:fontcolor=White:fontfile='/Windows/Fonts/arial.ttf':text='onLine1':x=(w)/2:y=(h)/2, drawtext=fontsize=20:fontcolor=White:fontfile='/Windows/Fonts/arial.ttf':text='onLine2':x=(w)/2:y=((h)/2)+25, drawtext=fontsize=20:fontcolor=White:fontfile='/Windows/Fonts/arial.ttf':text='onLine3':x=(w)/2:y=((h)/2)+50[out]" -y test_out.avi
把昨日还给我 2024-12-24 06:36:44

查看ffmpegvs_drawtext.c)中的源代码:

static inline int is_newline(uint32_t c)
{
    return c == '\n' || c == '\r' || c == '\f' || c == '\v';
}

因此您可以尝试插入\f\v 在文本行中对应于 ^L^K 字符。例如:

-filter_complex "[in] drawtext=fontsize=40:fontcolor=white:fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf:x=(w-tw)/2:y=(h-th)/2:box=1:[email protected]:text='two^Llines'[out]"

^L 是实际的 Ctrl-L 字符,而不是 ^L 显然。

Looking at the source code in ffmpeg (vs_drawtext.c):

static inline int is_newline(uint32_t c)
{
    return c == '\n' || c == '\r' || c == '\f' || c == '\v';
}

so you can try inserting \f or \v in your text line which correspond to ^L or ^K characters. For example:

-filter_complex "[in] drawtext=fontsize=40:fontcolor=white:fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf:x=(w-tw)/2:y=(h-th)/2:box=1:[email protected]:text='two^Llines'[out]"

^L being the actual Ctrl-L character and not ^ and L obviously.

べ繥欢鉨o。 2024-12-24 06:36:44

我简单地在命令中添加了新行,并且 ffmpeg 正确处理了它。

ffmpeg -i input.avi -vf "[in]drawtext=fontsize=20:text='hello
world':x=(w)/2:y=(h)/2:fontcolor=white[out]" -y out.mp4

不需要 Ctrl+L、Ctrl+K 黑客!

即我只是在“hello”之后按 Enter。

您可以编辑脚本文件甚至在 bash 命令行中进行操作。

I simple added new lines inside command and ffmpeg handled it properly.

ffmpeg -i input.avi -vf "[in]drawtext=fontsize=20:text='hello
world':x=(w)/2:y=(h)/2:fontcolor=white[out]" -y out.mp4

No Ctrl+L, Ctrl+K hacks are needed!

I.e. I just pressed Enter after 'hello'.

You can do it editing script file or even in bash command line.

ま昔日黯然 2024-12-24 06:36:44

我已经通过指定“textfile”参数并将我的文本放入此文件中,设法从命令行使其正常工作。

请参阅 http://ffmpeg.org/libavfilter.html#drawtext 获取更多帮助。在 Windows 上使用 ffmpeg 构建 N-35057-g2c44aed,但重要的是您拥有最新版本的 libavfilter。

I have managed to get this to work from the command line by specifying the 'textfile' parameter and putting my text into this file.

See http://ffmpeg.org/libavfilter.html#drawtext for more help. Using ffmpeg build N-35057-g2c44aed on windows, but the important thing is that you have recent version of the libavfilter.

愁杀 2024-12-24 06:36:44

只需将文本分割成一定长度的行(20个字符,您可以根据需要设置),然后再传递给ffmpeg

import subprocess , os

ffmpeg = "C:\\ffmpeg_10_6_11.exe"
inVid = "C:\\test_in.avi"
outVid = "C:\\test_out.avi"
length = 20
txt = "onLine1 onLine2 onLine3"
inpTxt = split_txt_into_multi_lines(txt,length)

if os.path.exists( outVid ):
  os.remove( outVid )
  proc = subprocess.Popen(ffmpeg + " -i " + inVid + f''' -vf drawtext=fontfile=/Windows/Fonts/arial.ttf:text={inpTxt}:fontcolor=white:fontsize=20 -y ''' + outVid , shell=True, 
  stderr=subprocess.PIPE)
  proc.wait()
  print proc.stderr.read()
  os.startfile( outVid )


#################################################################
def split_txt_into_multi_lines(input_str: str, line_length: int):
    words = input_str.split(" ")
    line_count = 0
    split_input = ""
    for word in words:
        line_count += 1
        line_count += len(word)
        if line_count > line_length:
            split_input += "\n"
            line_count = len(word) + 1
            split_input += word
            split_input += " "
        else:
            split_input += word
            split_input += " "
    
    return split_input
        


Just split the text into lines of a certain length (20 characters, you can set according to your need) before passing to ffmpeg.

import subprocess , os

ffmpeg = "C:\\ffmpeg_10_6_11.exe"
inVid = "C:\\test_in.avi"
outVid = "C:\\test_out.avi"
length = 20
txt = "onLine1 onLine2 onLine3"
inpTxt = split_txt_into_multi_lines(txt,length)

if os.path.exists( outVid ):
  os.remove( outVid )
  proc = subprocess.Popen(ffmpeg + " -i " + inVid + f''' -vf drawtext=fontfile=/Windows/Fonts/arial.ttf:text={inpTxt}:fontcolor=white:fontsize=20 -y ''' + outVid , shell=True, 
  stderr=subprocess.PIPE)
  proc.wait()
  print proc.stderr.read()
  os.startfile( outVid )


#################################################################
def split_txt_into_multi_lines(input_str: str, line_length: int):
    words = input_str.split(" ")
    line_count = 0
    split_input = ""
    for word in words:
        line_count += 1
        line_count += len(word)
        if line_count > line_length:
            split_input += "\n"
            line_count = len(word) + 1
            split_input += word
            split_input += " "
        else:
            split_input += word
            split_input += " "
    
    return split_input
        


亢潮 2024-12-24 06:36:44
TEXT=$(printf "$1") 

在 shell 脚本中

使用文本作为 shell 脚本参数,包括换行符

TEXT=$(printf "$1") 

In a shell script

With your text as your shell script argument including new line characters

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文