diff --git a/ffmpeg/ffmpeg.go b/ffmpeg/ffmpeg.go index 2ceef33e5d..04c6fb93bf 100755 --- a/ffmpeg/ffmpeg.go +++ b/ffmpeg/ffmpeg.go @@ -33,6 +33,7 @@ var ErrTranscoderHw = errors.New("TranscoderInvalidHardware") var ErrTranscoderInp = errors.New("TranscoderInvalidInput") var ErrTranscoderClipConfig = errors.New("TranscoderInvalidClipConfig") var ErrTranscoderVid = errors.New("TranscoderInvalidVideo") +var ErrTranscoderDuration = errors.New("TranscoderInvalidDuration") var ErrTranscoderStp = errors.New("TranscoderStopped") var ErrTranscoderFmt = errors.New("TranscoderUnrecognizedFormat") var ErrTranscoderPrf = errors.New("TranscoderUnrecognizedProfile") @@ -880,6 +881,10 @@ func (t *Transcoder) Transcode(input *TranscodeOptionsIn, ps []TranscodeOptions) if err != nil { return nil, err } + if format.DurSecs > 300 { + glog.Errorf("Input file %s has duration of %d seconds, which is more than 5 minutes. This is not supported by the transcoder.", input.Fname, format.DurSecs) + return nil, ErrTranscoderDuration + } // TODO hoist the rest of this into C so we don't have to invoke GetCodecInfo if !t.started { // NeedsBypass is state where video is present in container & without any frames diff --git a/ffmpeg/ffmpeg_test.go b/ffmpeg/ffmpeg_test.go index 5501c35478..923f694b13 100644 --- a/ffmpeg/ffmpeg_test.go +++ b/ffmpeg/ffmpeg_test.go @@ -3,6 +3,7 @@ package ffmpeg import ( "bufio" "fmt" + "io" "io/ioutil" "os" "os/exec" @@ -2424,3 +2425,45 @@ func TestTranscoder_PNGDemuxerOpts(t *testing.T) { assert.Equal(t, 3, res.Decoded.Frames) assert.Equal(t, 180, res.Encoded[0].Frames) } + +func TestTranscode_DurationLimit(t *testing.T) { + run, dir := setupTest(t) + defer os.RemoveAll(dir) + cmd := ` + # generate a 1fps sample + ffmpeg -i "$1"/../transcoder/test.ts -c copy -bsf:v setts=ts=N/TB/1 -frames:v 301 -y test.ts + # double check the sample actually has the characteristics we expect + ffprobe -show_format test.ts | grep duration=301.00 + ` + run(cmd) + + // Set up transcode options + fileInput := &TranscodeOptionsIn{ + Fname: fmt.Sprintf("%v/test.ts", dir), + } + options := []TranscodeOptions{ + { + Oname: fmt.Sprintf("%s/out-test.ts", dir), + VideoEncoder: ComponentOptions{Name: "copy"}, + AudioEncoder: ComponentOptions{Name: "copy"}, + Muxer: ComponentOptions{Name: "md5"}, + }, + } + + // transcode long input from file, should error out + _, err := Transcode3(fileInput, options) + assert.Equal(t, ErrTranscoderDuration, err) + + // transcode long input from pipe, should *not* error out + ir, iw, err := os.Pipe() + go func(iw *os.File) { + defer iw.Close() + f, _ := os.Open(fileInput.Fname) + io.Copy(iw, f) + }(iw) + pipeInput := &TranscodeOptionsIn{ + Fname: fmt.Sprintf("pipe:%d", ir.Fd()), + } + _, err = Transcode3(pipeInput, options) + assert.Nil(t, err) +}