通过Golang exec运行FFMPEG命令

huangapple go评论86阅读模式
英文:

Running FFMPEG command through Golang exec

问题

我需要运行一个ffmpeg命令,从图像中创建一个视频,并在图像之间使用淡入淡出作为过渡效果。该命令源自这个帖子。我需要通过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错误:No such filter: '"', Error configuring filters. 我知道这与必须在视频滤镜中使用引号有关,但我已经尝试了一切办法来让它工作,但我无法弄清楚。

非常感谢您的帮助!

英文:

I need to run an ffmpeg command to create a video from images with a crossfade between images as the transition. The command is derived from this post. I need to run it through the Golang os/exec package. The command I need to run is:

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

If you run this command directly in the terminal, it works just fine. However, it does not work through my code. This is my code that takes a string command and runs it through the os/exec package:

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
}

When I run this, I get the ffmpeg error: No such filter: '"', Error configuring filters. I know it has something to do with the quotes that HAVE to be in the video filters, but I have tried everything to get it to work and I can't figure it out.

Any help is greatly appreciated!

答案1

得分: 6

这实际上是正确的工作方式:

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函数。

英文:

This actually does work correctly :

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

Notice that I did remove start and end double quotes from the -filter_complex parameters and two single quotes from the -map parameters.

Did it by hand, though, not sure of a strings function that could do it automagically.

huangapple
  • 本文由 发表于 2016年9月22日 23:56:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/39643692.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定