From 2a41acb422624e0b56efa672b2f3caeaae4ef648 Mon Sep 17 00:00:00 2001 From: Denis Borzenko Date: Tue, 28 Feb 2023 22:55:03 +0300 Subject: [PATCH 1/2] Move platform-specific code under build tags; fix corresponding tests --- ffmpeg_linux_test.go | 14 ++++++++++++++ ffmpeg_test.go | 7 ------- ffmpeg_windows_test.go | 20 ++++++++++++++++++++ run.go | 10 ---------- run_linux.go | 9 +++++++++ 5 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 ffmpeg_linux_test.go create mode 100644 ffmpeg_windows_test.go diff --git a/ffmpeg_linux_test.go b/ffmpeg_linux_test.go new file mode 100644 index 0000000..8492dba --- /dev/null +++ b/ffmpeg_linux_test.go @@ -0,0 +1,14 @@ +package ffmpeg_go + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCompileWithOptions(t *testing.T) { + out := Input("dummy.mp4").Output("dummy2.mp4") + cmd := out.Compile(SeparateProcessGroup()) + assert.Equal(t, cmd.SysProcAttr.Pgid, 0) + assert.True(t, cmd.SysProcAttr.Setpgid) +} diff --git a/ffmpeg_test.go b/ffmpeg_test.go index fe137a8..7eb2af7 100644 --- a/ffmpeg_test.go +++ b/ffmpeg_test.go @@ -277,13 +277,6 @@ func TestCompile(t *testing.T) { assert.Equal(t, out.Compile().Args, []string{"ffmpeg", "-i", "dummy.mp4", "dummy2.mp4"}) } -func TestCompileWithOptions(t *testing.T) { - out := Input("dummy.mp4").Output("dummy2.mp4") - cmd := out.Compile(SeparateProcessGroup()) - assert.Equal(t, cmd.SysProcAttr.Pgid, 0) - assert.True(t, cmd.SysProcAttr.Setpgid) -} - func TestPipe(t *testing.T) { width, height := 32, 32 diff --git a/ffmpeg_windows_test.go b/ffmpeg_windows_test.go new file mode 100644 index 0000000..c7ac10e --- /dev/null +++ b/ffmpeg_windows_test.go @@ -0,0 +1,20 @@ +package ffmpeg_go + +import ( + "os/exec" + "syscall" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCompileWithOptions(t *testing.T) { + out := Input("dummy.mp4").Output("dummy2.mp4") + cmd := out.Compile(func(s *Stream, cmd *exec.Cmd) { + if cmd.SysProcAttr == nil { + cmd.SysProcAttr = &syscall.SysProcAttr{} + } + cmd.SysProcAttr.HideWindow = true + }) + assert.Equal(t, true, cmd.SysProcAttr.HideWindow) +} diff --git a/run.go b/run.go index e917404..c4c5b2e 100644 --- a/run.go +++ b/run.go @@ -9,7 +9,6 @@ import ( "os/exec" "sort" "strings" - "syscall" "time" ) @@ -239,15 +238,6 @@ func (s *Stream) ErrorToStdOut() *Stream { type CompilationOption func(s *Stream, cmd *exec.Cmd) -// SeparateProcessGroup ensures that the command is run in a separate process -// group. This is useful to enable handling of signals such as SIGINT without -// propagating them to the ffmpeg process. -func SeparateProcessGroup() CompilationOption { - return func(s *Stream, cmd *exec.Cmd) { - cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true, Pgid: 0} - } -} - func (s *Stream) SetFfmpegPath(path string) *Stream { s.FfmpegPath = path return s diff --git a/run_linux.go b/run_linux.go index afe8213..641a167 100644 --- a/run_linux.go +++ b/run_linux.go @@ -140,3 +140,12 @@ func (s *Stream) RunLinux() error { return cmd.Wait() } + +// SeparateProcessGroup ensures that the command is run in a separate process +// group. This is useful to enable handling of signals such as SIGINT without +// propagating them to the ffmpeg process. +func SeparateProcessGroup() CompilationOption { + return func(s *Stream, cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true, Pgid: 0} + } +} From bbf2881ff483112b8173d0656ade07cdcb68fb43 Mon Sep 17 00:00:00 2001 From: Denis Borzenko Date: Tue, 28 Feb 2023 23:46:11 +0300 Subject: [PATCH 2/2] Close u2takey/ffmpeg-go#80 Discover CommandOption type and ffmpeg.GlobalCommandOptions array, that is processed before running ffmpeg or ffprobe commands. Add tests. --- ffmpeg_linux_test.go | 15 ++++++++++++++- ffmpeg_windows_test.go | 15 +++++++++++++++ probe.go | 3 +++ run.go | 7 +++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/ffmpeg_linux_test.go b/ffmpeg_linux_test.go index 8492dba..f9fc62e 100644 --- a/ffmpeg_linux_test.go +++ b/ffmpeg_linux_test.go @@ -9,6 +9,19 @@ import ( func TestCompileWithOptions(t *testing.T) { out := Input("dummy.mp4").Output("dummy2.mp4") cmd := out.Compile(SeparateProcessGroup()) - assert.Equal(t, cmd.SysProcAttr.Pgid, 0) + assert.Equal(t, 0, cmd.SysProcAttr.Pgid) + assert.True(t, cmd.SysProcAttr.Setpgid) +} + +func TestGlobalCommandOptions(t *testing.T) { + out := Input("dummy.mp4").Output("dummy2.mp4") + GlobalCommandOptions = append(GlobalCommandOptions, func(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true, Pgid: 0} + }) + defer func() { + GlobalCommandOptions = GlobalCommandOptions[0 : len(GlobalCommandOptions)-1] + }() + cmd := out.Compile() + assert.Equal(t, 0, cmd.SysProcAttr.Pgid) assert.True(t, cmd.SysProcAttr.Setpgid) } diff --git a/ffmpeg_windows_test.go b/ffmpeg_windows_test.go index c7ac10e..68a677c 100644 --- a/ffmpeg_windows_test.go +++ b/ffmpeg_windows_test.go @@ -18,3 +18,18 @@ func TestCompileWithOptions(t *testing.T) { }) assert.Equal(t, true, cmd.SysProcAttr.HideWindow) } + +func TestGlobalCommandOptions(t *testing.T) { + out := Input("dummy.mp4").Output("dummy2.mp4") + GlobalCommandOptions = append(GlobalCommandOptions, func(cmd *exec.Cmd) { + if cmd.SysProcAttr == nil { + cmd.SysProcAttr = &syscall.SysProcAttr{} + } + cmd.SysProcAttr.HideWindow = true + }) + defer func() { + GlobalCommandOptions = GlobalCommandOptions[0 : len(GlobalCommandOptions)-1] + }() + cmd := out.Compile() + assert.Equal(t, true, cmd.SysProcAttr.HideWindow) +} diff --git a/probe.go b/probe.go index 7f1318a..93ea902 100644 --- a/probe.go +++ b/probe.go @@ -34,6 +34,9 @@ func ProbeWithTimeoutExec(fileName string, timeOut time.Duration, kwargs KwArgs) cmd := exec.CommandContext(ctx, "ffprobe", args...) buf := bytes.NewBuffer(nil) cmd.Stdout = buf + for _, option := range GlobalCommandOptions { + option(cmd) + } err := cmd.Run() if err != nil { return "", err diff --git a/run.go b/run.go index c4c5b2e..539f577 100644 --- a/run.go +++ b/run.go @@ -236,6 +236,10 @@ func (s *Stream) ErrorToStdOut() *Stream { return s.WithErrorOutput(os.Stdout) } +type CommandOption func(cmd *exec.Cmd) + +var GlobalCommandOptions = make([]CommandOption, 0) + type CompilationOption func(s *Stream, cmd *exec.Cmd) func (s *Stream) SetFfmpegPath(path string) *Stream { @@ -259,6 +263,9 @@ func (s *Stream) Compile(options ...CompilationOption) *exec.Cmd { for _, option := range options { option(s, cmd) } + for _, option := range GlobalCommandOptions { + option(cmd) + } log.Printf("compiled command: ffmpeg %s\n", strings.Join(args, " ")) return cmd }