【问题标题】:Running FFMPEG command through Golang exec通过 Golang exec 运行 FFMPEG 命令
【发布时间】: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 为您运行命令。

标签: go ffmpeg


【解决方案1】:

这实际上可以正常工作:

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")

请注意,我确实删除了 -filter_complex 参数中的开始和结束双引号以及 -map 参数中的两个单引号。

虽然是手动完成的,但不确定 strings 函数是否可以自动完成。

【讨论】:

  • 感谢您的帮助。
  • @MurtadhaS。您是否设法为此找到解决方案?使用 strings.replace 不起作用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-11
  • 1970-01-01
  • 1970-01-01
  • 2017-01-22
  • 1970-01-01
  • 2014-01-11
  • 1970-01-01
相关资源
最近更新 更多