【发布时间】:2016-09-22 15:56:45
【问题描述】:
我需要运行ffmpeg 命令来从图像创建视频,并在图像之间使用交叉淡入淡出作为过渡。该命令派生自此post。我需要通过 Golang os/exec 包运行它。我需要运行的命令是:
ffmpeg -loop 1 -t 5 -i img-0.png -loop 1 -t 5 -i img-1.png -loop 1 -t 5 -i img-2.png -filter_complex "[1:v][0:v]blend=all_expr='A*(if(gte(T,0.5),1,T/0.5))+B*(1-(if(gte(T,0.5),1,T/0.5)))'[b1v];[2:v][1:v]blend=all_expr='A*(if(gte(T,0.5),1,T/0.5))+B*(1-(if(gte(T,0.5),1,T/0.5)))'[b2v];[0:v][b1v][1:v][b2v][2:v]concat=n=5:v=1:a=0,format=yuv420p[v]" -map '[v]' -c:v libx264 -pix_fmt yuv420p -r 30 -s 1280x720 -aspect 16:9 -crf 1 -preset ultrafast output.mp4
如果您直接在终端中运行此命令,它就可以正常工作。但是,它不适用于我的代码。这是我的代码,它接受一个字符串命令并通过os/exec 包运行它:
command := "ffmpeg -loop 1 -t 5 -i img-0.png -loop 1 -t 5 -i img-1.png -loop 1 -t 5 -i img-2.png -filter_complex "[1:v][0:v]blend=all_expr='A*(if(gte(T,0.5),1,T/0.5))+B*(1-(if(gte(T,0.5),1,T/0.5)))'[b1v];[2:v][1:v]blend=all_expr='A*(if(gte(T,0.5),1,T/0.5))+B*(1-(if(gte(T,0.5),1,T/0.5)))'[b2v];[0:v][b1v][1:v][b2v][2:v]concat=n=5:v=1:a=0,format=yuv420p[v]" -map '[v]' -c:v libx264 -pix_fmt yuv420p -r 30 -s 1280x720 -aspect 16:9 -crf 1 -preset ultrafast output.mp4"
lastQuote := rune(0)
f := func(c rune) bool {
switch {
case c == lastQuote:
lastQuote = rune(0)
return false
case lastQuote != rune(0):
return false
case unicode.In(c, unicode.Quotation_Mark):
lastQuote = c
return false
default:
return unicode.IsSpace(c)
}
}
parts := strings.FieldsFunc(command, f)
cmd := exec.Command(parts[0], parts[1:]...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
err := cmd.Run()
if err != nil {
return err
}
当我运行它时,我得到了 ffmpeg 错误:没有这样的过滤器:'"',配置过滤器时出错。我知道这与视频过滤器中必须包含的引号有关,但我已经尝试了一切让它工作,我想不通。
非常感谢任何帮助!
【问题讨论】:
-
您的字段 func 没有删除封闭引号。与其尝试对 shell 输入进行 lex,为什么不使用正确执行此操作的包,或者只是将字符串传递给 shell 执行?
-
我试图在过滤器复合体周围不带引号的情况下运行命令,因为即使它直接从终端工作,但我收到此错误:缺少')'或'gte( T' [AVFilterGraph @ 0x3b94ee0] 使用 args 'all_expr=A*(if(gte(T' 配置过滤器时出错。
-
是的,我不确定你想用那个开关来完成什么,但我的感觉是你不应该有任何这些。只需将“ffmpeg”作为第一个参数传递,然后使用反引号让您制作字符串文字(在这里不能这样做,因为标记会将其变成代码 sn-p),这样您就可以在命令中保留必要的引号并通过ffmpeg 之后的所有内容都作为单个字符串,而不是将其分开并尝试使用
parts[1:]...传播数组。我认为除非你真的需要微调这些参数,否则你只是做了比必要更多的工作。 -
该开关通过尊重周围的引号将可能包含空格的参数作为一个参数保存在一起。
-
在 shell 中引用参数不会将引号传递给程序。同样,您可以正确地对其进行 lex,或者让 shell 为您运行命令。