扭曲的spawnProcess如何发送带有嵌入引号的ffmpeg filter_complex参数?

问题描述 投票:0回答:1

我正在尝试通过reactor.spawnProcess将这些(简化的)参数发送到ffmpeg。

['-filter_complex', '"[0:v]setpts=PTS-STARTPTS,scale=-1:720 [a0];[a0]pad=w=1280:h=720:x=-1:y=-1:color=black[out]"'

但据推测代码正在执行某种形式的前缀,而 ffmpeg 无法理解,因为我的过滤器图总是出错,尽管我可以在命令行上将完全相同的文本发送到 ffmpeg 并且没问题。

我尝试了 repr 和 escape ('"'),但我不知道如何将这些字符串传递给 ffmpeg。

编辑:不知道为什么我之前没有尝试过,但我写了一个小脚本来接收输入参数,它们很好。仍然不明白为什么“”.join(params)将从终端运行但在spawnProcess中失败。

编辑:ffmpeg 输出

Splitting the commandline.
Reading option '-loglevel' ... matched as option 'loglevel' (set logging level) with argument 'debug'.
Reading option '-v' ... matched as option 'v' (set logging level) with argument 'verbose'.
Reading option '-threads' ... matched as AVOption 'threads' with argument 'auto'.
Reading option '-flags' ... matched as AVOption 'flags' with argument '-global_header'.
Reading option '-i' ... matched as input url with argument 'config/colorbars.jpg'.
Reading option '-c:v' ... matched as option 'c' (codec name) with argument 'copy'.
Reading option '-tag:v' ... matched as option 'tag' (force codec tag/fourcc) with argument 'hvc1'.
Reading option '-filter_complex' ... matched as option 'filter_complex' (create a complex filtergraph) with argument '"[0:v]setpts=(RTCTIME-RTCSTART)/(TB*1000000),scale=-1:720[outpad];[outpad]pad=w=1280:h=720:x=-1:y=-1:color=black[out]"'.
Reading option '-map' ... matched as option 'map' (set input stream mapping) with argument '"[out]"'.
Reading option '-c:v' ... matched as option 'c' (codec name) with argument 'hevc_videotoolbox'.
Reading option '-b:v' ... matched as option 'b' (video bitrate (please use -b:v)) with argument '3000K'.
Reading option '-preset' ... matched as AVOption 'preset' with argument 'medium'.
Reading option '-profile:v' ... matched as option 'profile' (set profile) with argument 'main'.
Reading option '-pix_fmt' ... matched as option 'pix_fmt' (set pixel format) with argument 'yuv420p'.
Reading option '-t' ... matched as option 't' (record or transcode "duration" seconds of audio/video) with argument '5'.
Reading option 'temp/apptest_1.mp4' ... matched as output url.
Reading option '-y' ... matched as option 'y' (overwrite output files) with argument '1'.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option loglevel (set logging level) with argument debug.
Applying option v (set logging level) with argument verbose.
Input #0, image2, from 'config/colorbars.jpg':
  Duration: 00:00:00.04, start: 0.000000, bitrate: 4712 kb/s
  Stream #0:0: Video: mjpeg (Baseline), 1 reference frame, yuvj420p(pc, bt470bg/unknown/unknown, center), 1280x720 [SAR 1:1 DAR 16:9], 25 fps, 25 tbr, 25 tbn
[AVFilterGraph @ 0x600001fbc600] No such filter: '"'
Error initializing complex filters.
Invalid argument

解决方案:请求帮助时问题总会解决。 ffmpeg wiki 上的每个示例都在过滤器图周围显示双引号。当使用spawnProcess发送时,这是不必要的。

python python-3.x ffmpeg twisted
1个回答
1
投票

问题是,当您将字符串列表传递给spawnProcess时,它们会按照您传递它们的方式完全显示给子进程,这意味着

ffmpeg
看到的命令行参数是字面上
"[0:v]setpts=PTS-STARTPTS,scale=-1:720 [a0];[a0]pad=w=1280:h=720:x=-1:y=-1:color=black[out]"
,包括引用。

通过让 Twisted 让开并简单地查看这个非常简单的 Python 程序以各种方式运行时的输出,可能有助于理解这里发生的情况:

# argv.py
import sys
print(repr(sys.argv))

让我们假设这个程序是

ffmpeg

在 shell 中,我们可以做

$ python3 argv.py -filter_complex \
    "[0:v]setpts=PTS-STARTPTS,scale=-1:720 [a0];[a0]pad=w=1280:h=720:x=-1:y=-1:color=black[out]"

我们会得到

['argv.py', '-filter_complex', '[0:v]setpts=PTS-STARTPTS,scale=-1:720 [a0];[a0]pad=w=1280:h=720:x=-1:y=-1:color=black[out]']

shell 已采用引用的参数并按原样传递它。

现在,shell 可以在双引号字符串中为我们做一些其他的事情,例如变量插值:

$ python3 argv.py here is my home "$HOME"
['argv.py', 'here', 'is', 'my', 'home', '/Users/glyph']

但是 Python 对变量扩展一无所知;这是在我们看到之前由 shell 完成的。

另一个使用

os.execv
的简短脚本可以以相同的方式向您展示
spawnProcess
对参数的作用。 例如:

from sys import executable
from os import execv
execv(
    executable,
    [executable, "argv.py", "here", "is", "my", "$HOME"],
)

简单地打印出来

['argv.py', 'here', 'is', 'my', '$HOME']

当直接使用 exec 执行程序(不涉及 shell)时,Python 对 shell 引号的了解就像它对 shell 变量的了解一样。 因此,更接近您最初的示例,在 shell 中,我们可能有

$ python3 argv.py "one argument with spaces, quoted"

加上引号,然后得到

['argv.py', 'one argument with spaces, quoted']

作为输出。 但是,如果我们将这些引号放入 Python 字符串中,

from sys import executable
from os import execv
execv(
    executable,
    [executable, "argv.py", '"one argument with spaces, quoted too much"'],
)

你会看到引号进入论点

['argv.py', '"one argument with spaces, quoted too much"']

就像你在 shell 中双引号它一样:

$ python3 argv.py '"one argument with spaces, extra-quoted from the shell"'
['argv.py', '"one argument with spaces, extra-quoted from the shell"']

这就是这里正在发生的事情。 如果您将像 '"' 这样的字符串传递给

exec
系列函数,它就会像 '"' 一样传递到您正在调用的程序。 ffmpeg 文档在其文档中使用引号,因为它对 shell 的参数数据进行编码,而您需要对 Python 的参数数据进行编码

您可以考虑的另一种方式是,虽然 shell 具有不带引号的字符串的特殊情况,但带引号的字符串的工作原理几乎相同。

在 Python 中,您输入了

'"[0:v]setpts=PTS-STARTPTS,scale=-1:720 [a0];[a0]pad=w=1280:h=720:x=-1:y=-1:color=black[out]"'
。 如果我们在 shell 中准确地键入该内容 - 以及双引号inside单引号 - 到 shell 中,我们会得到相同的结果:

$ python3 argv.py '"[0:v]setpts=PTS-STARTPTS,scale=-1:720 [a0];[a0]pad=w=1280:h=720:x=-1:y=-1:color=black[out]"'
['argv.py', '"[0:v]setpts=PTS-STARTPTS,scale=-1:720 [a0];[a0]pad=w=1280:h=720:x=-1:y=-1:color=black[out]"']

结论:这就是在 shell 和 Python 中引用字符串的工作方式,与 Twisted 没有任何关系。

© www.soinside.com 2019 - 2024. All rights reserved.