diff --git a/README.md b/README.md index cbb2904..c9614d3 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,11 @@ func main() { // Handle error... // Start transcoder process - done, err := trans.Run() + done := trans.Run() // This channel is used to wait for the process to end - <-done + err = <-done + // Handle error... } ``` @@ -59,10 +60,10 @@ func main() { // Handle error... // Start transcoder process - done, err := trans.Run() + done := trans.Run() // Returns a channel to get the transcoding progress - progress, err := trans.Output() + progress := trans.Output() // Example of printing transcoding progress for msg := range progress { @@ -70,7 +71,7 @@ func main() { } // This channel is used to wait for the transcoding process to end - <-done + err = <-done } ``` @@ -139,10 +140,10 @@ func main() { trans.MediaFile().SetPreset("ultrafast") // Start transcoder process - done, err := trans.Run() + done := trans.Run() // Returns a channel to get the transcoding progress - progress, err := trans.Output() + progress := trans.Output() // Example of printing transcoding progress for msg := range progress { @@ -150,7 +151,7 @@ func main() { } // This channel is used to wait for the transcoding process to end - <-done + err = <-done } ``` diff --git a/ffmpeg/ffmpeg.go b/ffmpeg/ffmpeg.go index a703e9f..ebba99c 100644 --- a/ffmpeg/ffmpeg.go +++ b/ffmpeg/ffmpeg.go @@ -10,49 +10,33 @@ import ( type Configuration struct { FfmpegBin string FfprobeBin string - ExecCmd string - ExecArgs string } func Configure() (Configuration, error) { var outFFmpeg bytes.Buffer var outProbe bytes.Buffer - - execCmd := utils.GetExec() execFFmpegCommand := utils.GetFFmpegExec() execFFprobeCommand := utils.GetFFprobeExec() - execArgs := utils.GetExecArgs() - cmdFFmpeg := exec.Command(execCmd, execArgs, execFFmpegCommand) - cmdProbe := exec.Command(execCmd, execArgs, execFFprobeCommand) + cmdFFmpeg := exec.Command(execFFmpegCommand[0], execFFmpegCommand[1]) + cmdProbe := exec.Command(execFFprobeCommand[0], execFFprobeCommand[1]) cmdFFmpeg.Stdout = &outFFmpeg cmdProbe.Stdout = &outProbe - err := cmdFFmpeg.Start() + err := cmdFFmpeg.Run() if err != nil { return Configuration{}, err } - _, err = cmdFFmpeg.Process.Wait() + err = cmdProbe.Run() if err != nil { return Configuration{}, err } - err = cmdProbe.Start() - if err != nil { - return Configuration{}, err - } - - _, err = cmdProbe.Process.Wait() - if err != nil { - return Configuration{}, err - } - - ffmpeg := strings.Replace(outFFmpeg.String(), "\n", "", -1) - fprobe := strings.Replace(outProbe.String(), "\n", "", -1) - - cnf := Configuration{ffmpeg, fprobe, execCmd, execArgs} + ffmpeg := strings.Replace(outFFmpeg.String(), utils.LineSeparator(), "", -1) + fprobe := strings.Replace(outProbe.String(), utils.LineSeparator(), "", -1) + cnf := Configuration{ffmpeg, fprobe} return cnf, nil } diff --git a/models/media.go b/models/media.go index f9ac2f7..186b1d8 100644 --- a/models/media.go +++ b/models/media.go @@ -362,10 +362,10 @@ func (m *Mediafile) Metadata() Metadata { } /** OPTS **/ -func (m *Mediafile) ToStrCommand() string { - var strCommand string +func (m *Mediafile) ToStrCommand() []string { + var strCommand []string - opts := [] string { + opts := []string { "SeekTimeInput", "SeekUsingTsInput", "NativeFramerateInput", @@ -409,278 +409,276 @@ func (m *Mediafile) ToStrCommand() string { if (opt != reflect.Value{}) { result := opt.Call([]reflect.Value{}) - if result[0].String() != "" { - strCommand += " " - strCommand += result[0].String() + if val, ok := result[0].Interface().([]string); ok { + strCommand = append(strCommand, val...) } } } return strCommand - } -func (m *Mediafile) ObtainAspect() string { +func (m *Mediafile) ObtainAspect() []string { // Set aspect if m.resolution != "" { resolution := strings.Split(m.resolution, "x") if len(resolution) != 0 { width, _ := strconv.ParseFloat(resolution[0], 64) height, _ := strconv.ParseFloat(resolution[1], 64) - return fmt.Sprintf("-aspect %f", width/height) + return []string{"-aspect", fmt.Sprintf("%f", width/height)} } } if m.aspect != "" { - return fmt.Sprintf("-aspect %s", m.aspect) + return []string{"-aspect", m.aspect} } - return "" + return nil } -func (m *Mediafile) ObtainInputPath() string { - return fmt.Sprintf("-i \"%s\"", m.inputPath) +func (m *Mediafile) ObtainInputPath() []string { + return []string{"-i", m.inputPath} } -func (m *Mediafile) ObtainNativeFramerateInput() string { +func (m *Mediafile) ObtainNativeFramerateInput() []string { if m.nativeFramerateInput { - return "-re" + return []string{"-re"} } - return "" + return nil } -func (m *Mediafile) ObtainOutputPath() string { - return fmt.Sprintf("\"%s\"", m.outputPath) +func (m *Mediafile) ObtainOutputPath() []string { + return []string{m.outputPath} } -func (m *Mediafile) ObtainVideoCodec() string { +func (m *Mediafile) ObtainVideoCodec() []string { if m.videoCodec != "" { - return fmt.Sprintf("-c:v %s", m.videoCodec) + return []string{"-c:v", m.videoCodec} } - return "" + return nil } -func (m *Mediafile) ObtainFrameRate() string { +func (m *Mediafile) ObtainFrameRate() []string { if m.frameRate != 0 { - return fmt.Sprintf("-r %d", m.frameRate) + return []string{"-r",fmt.Sprintf("%d", m.frameRate)} } - return "" + return nil } -func (m *Mediafile) ObtainResolution() string { +func (m *Mediafile) ObtainResolution() []string { if m.resolution != "" { - return fmt.Sprintf("-s %s", m.resolution) + return []string{"-s", m.resolution} } - return "" + return nil } -func (m *Mediafile) ObtainVideoBitRate() string { +func (m *Mediafile) ObtainVideoBitRate() []string { if m.videoBitRate != 0 { - return fmt.Sprintf("-b:v %d", m.videoBitRate) + return []string{"-b:v", fmt.Sprintf("%d", m.videoBitRate)} } - return "" + return nil } -func (m *Mediafile) ObtainAudioCodec() string { +func (m *Mediafile) ObtainAudioCodec() []string { if m.audioCodec != "" { - return fmt.Sprintf("-c:a %s", m.audioCodec) + return []string{"-c:a", m.audioCodec} } - return "" + return nil } -func (m *Mediafile) ObtainAudioBitRate() string { +func (m *Mediafile) ObtainAudioBitRate() []string { if m.audioBitrate != 0 { - return fmt.Sprintf("-b:a %d", m.audioBitrate) + return []string{"-b:a", fmt.Sprintf("%d", m.audioBitrate)} } - return "" + return nil } -func (m *Mediafile) ObtainAudioChannels() string { +func (m *Mediafile) ObtainAudioChannels() []string { if m.audioChannels != 0 { - return fmt.Sprintf("-ac %d", m.audioChannels) + return []string{"-ac",fmt.Sprintf("%d", m.audioChannels)} } - return "" + return nil } -func (m *Mediafile) ObtainVideoMaxBitRate() string { +func (m *Mediafile) ObtainVideoMaxBitRate() []string { if m.videoMaxBitRate != 0 { - return fmt.Sprintf("-maxrate %dk", m.videoMaxBitRate) + return []string{"-maxrate",fmt.Sprintf("%dk", m.videoMaxBitRate)} } - return "" + return nil } -func (m *Mediafile) ObtainVideoMinBitRate() string { +func (m *Mediafile) ObtainVideoMinBitRate() []string { if m.videoMinBitrate != 0 { - return fmt.Sprintf("-minrate %dk", m.videoMinBitrate) + return []string{"-minrate",fmt.Sprintf("%dk", m.videoMinBitrate)} } - return "" + return nil } -func (m *Mediafile) ObtainBufferSize() string { +func (m *Mediafile) ObtainBufferSize() []string { if m.bufferSize != 0 { - return fmt.Sprintf("-bufsize %dk", m.bufferSize) + return []string{"-bufsize",fmt.Sprintf("%dk", m.bufferSize)} } - return "" + return nil } -func (m *Mediafile) ObtainVideoBitRateTolerance() string { +func (m *Mediafile) ObtainVideoBitRateTolerance() []string { if m.videoBitRateTolerance != 0 { - return fmt.Sprintf("-bt %dk", m.videoBitRateTolerance) + return []string{"-bt",fmt.Sprintf("%dk", m.videoBitRateTolerance)} } - return "" + return nil } -func (m *Mediafile) ObtainThreads() string { +func (m *Mediafile) ObtainThreads() []string { if m.threads != 0 { - return fmt.Sprintf("-threads %d", m.threads) + return []string{"-threads",fmt.Sprintf("%d", m.threads)} } - return "" + return nil } -func (m *Mediafile) ObtainTarget() string { +func (m *Mediafile) ObtainTarget() []string { if m.target != "" { - return fmt.Sprintf("-target %s", m.target) + return []string{"-target",m.target} } - return "" + return nil } -func (m *Mediafile) ObtainDuration() string { +func (m *Mediafile) ObtainDuration() []string { if m.duration != "" { - return fmt.Sprintf("-t %s", m.duration) + return []string{"-t",m.duration} } - return "" + return nil } -func (m *Mediafile) ObtainDurationInput() string { +func (m *Mediafile) ObtainDurationInput() []string { if m.durationInput != "" { - return fmt.Sprintf("-t %s", m.durationInput) + return []string{"-t",m.durationInput} } - return "" + return nil } -func (m *Mediafile) ObtainKeyframeInterval() string { +func (m *Mediafile) ObtainKeyframeInterval() []string { if m.keyframeInterval != 0 { - return fmt.Sprintf("-g %d", m.keyframeInterval) + return []string{"-g",fmt.Sprintf("%d", m.keyframeInterval)} } - return "" + return nil } -func (m *Mediafile) ObtainSeekTime() string { +func (m *Mediafile) ObtainSeekTime() []string { if m.seekTime != "" { - return fmt.Sprintf("-ss %s", m.seekTime) + return []string{"-ss",m.seekTime} } - return "" + return nil } -func (m *Mediafile) ObtainSeekTimeInput() string { +func (m *Mediafile) ObtainSeekTimeInput() []string { if m.seekTimeInput != "" { - return fmt.Sprintf("-ss %s", m.seekTimeInput) + return []string{"-ss",m.seekTimeInput} } - return "" + return nil } -func (m *Mediafile) ObtainPreset() string { +func (m *Mediafile) ObtainPreset() []string { if m.preset != "" { - return fmt.Sprintf("-preset %s", m.preset) + return []string{"-preset",m.preset} } - return "" + return nil } -func (m *Mediafile) ObtainTune() string { +func (m *Mediafile) ObtainTune() []string { if m.tune != "" { - return fmt.Sprintf("-tune %s", m.tune) + return []string{"-tune",m.tune} } - return "" + return nil } -func (m *Mediafile) ObtainQuality() string { +func (m *Mediafile) ObtainQuality() []string { if m.quality != 0 { - return fmt.Sprintf("-crf %d", m.quality) + return []string{"-crf",fmt.Sprintf("%d", m.quality)} } - return "" + return nil } -func (m *Mediafile) ObtainVideoProfile() string { +func (m *Mediafile) ObtainVideoProfile() []string { if m.videoProfile != "" { - return fmt.Sprintf("-profile:v %s", m.videoProfile) + return []string{"-profile:v",m.videoProfile} } - return "" + return nil } -func (m *Mediafile) ObtainAudioProfile() string { +func (m *Mediafile) ObtainAudioProfile() []string { if m.audioProfile != "" { - return fmt.Sprintf("-profile:a %s", m.audioProfile) + return []string{"-profile:a", m.audioProfile} } - return "" + return nil } -func (m *Mediafile) ObtainCopyTs() string { +func (m *Mediafile) ObtainCopyTs() []string { if m.copyTs { - return "-copyts" + return []string{"-copyts"} } - return "" + return nil } -func (m *Mediafile) ObtainOutputFormat() string { +func (m *Mediafile) ObtainOutputFormat() []string { if m.outputFormat != "" { - return fmt.Sprintf("-f %s", m.outputFormat) + return []string{"-f",m.outputFormat} } - return "" + return nil } -func (m *Mediafile) ObtainMuxDelay() string { +func (m *Mediafile) ObtainMuxDelay() []string { if m.muxDelay != "" { - return fmt.Sprintf("-muxdelay %s", m.muxDelay) + return []string{"-muxdelay",m.muxDelay} } - return "" + return nil } -func (m *Mediafile) ObtainSeekUsingTsInput() string { +func (m *Mediafile) ObtainSeekUsingTsInput() []string { if m.seekUsingTsInput { - return "-seek_timestamp 1" + return []string{"-seek_timestamp", "1"} } - return "" + return nil } -func (m *Mediafile) ObtainRtmpLive() string { +func (m *Mediafile) ObtainRtmpLive() []string { if m.rtmpLive != "" { - return fmt.Sprintf("-rtmp_live %s", m.rtmpLive) + return []string{"-rtmp_live",m.rtmpLive} } else { - return "" + return nil } } -func (m *Mediafile) ObtainHlsPlaylistType() string { +func (m *Mediafile) ObtainHlsPlaylistType() []string { if m.hlsPlaylistType != "" { - return fmt.Sprintf("-hls_playlist_type %s", m.hlsPlaylistType) + return []string{"-hls_playlist_type",m.hlsPlaylistType} } else { - return "" + return nil } } -func (m *Mediafile) ObtainInputInitialOffset() string { +func (m *Mediafile) ObtainInputInitialOffset() []string { if m.inputInitialOffset != "" { - return fmt.Sprintf("-itsoffset %s", m.inputInitialOffset) + return []string{"-itsoffset",m.inputInitialOffset} } else { - return "" + return nil } } -func (m *Mediafile) ObtainHlsSegmentDuration() string { +func (m *Mediafile) ObtainHlsSegmentDuration() []string { if m.hlsSegmentDuration != 0 { - return fmt.Sprintf("-hls_time %d", m.hlsSegmentDuration) + return []string{"-hls_time",fmt.Sprintf("%d", m.hlsSegmentDuration)} } else { - return "" + return nil } } -func (m *Mediafile) ObtainStreamIds() string { +func (m *Mediafile) ObtainStreamIds() []string { if m.streamIds != nil && len(m.streamIds) != 0 { result := []string{} for i, val := range m.streamIds { - result = append(result, fmt.Sprintf("-streamid %d:%s", i, val)) + result = append(result, []string{"-streamid", fmt.Sprintf("%d:%s", i, val)}...) } - return strings.Join(result, " ") + return result } - return "" + return nil } diff --git a/tests/transcoding_test.go b/tests/transcoding_test.go index 02ab3bc..6fc9637 100755 --- a/tests/transcoding_test.go +++ b/tests/transcoding_test.go @@ -2,7 +2,7 @@ package test import ( "testing" - "goffmpeg/transcoder" + "github.com/xfrr/goffmpeg/transcoder" ) func TestInputNotFound(t *testing.T) { @@ -31,13 +31,12 @@ func TestTranscoding3GP(t *testing.T) { return } - done, err := trans.Run() + done := trans.Run() + err = <- done if err != nil { t.Error(err) return } - - <-done } func TestTranscodingAVI(t *testing.T) { @@ -53,13 +52,12 @@ func TestTranscodingAVI(t *testing.T) { return } - done, err := trans.Run() + done := trans.Run() + err = <- done if err != nil { t.Error(err) return } - - <-done } func TestTranscodingFLV(t *testing.T) { @@ -75,13 +73,12 @@ func TestTranscodingFLV(t *testing.T) { return } - done, err := trans.Run() + done := trans.Run() + err = <- done if err != nil { t.Error(err) return } - - <-done } func TestTranscodingMKV(t *testing.T) { @@ -97,13 +94,12 @@ func TestTranscodingMKV(t *testing.T) { return } - done, err := trans.Run() + done := trans.Run() + err = <-done if err != nil { t.Error(err) return } - - <-done } func TestTranscodingMOV(t *testing.T) { @@ -119,13 +115,12 @@ func TestTranscodingMOV(t *testing.T) { return } - done, err := trans.Run() + done := trans.Run() + err = <-done if err != nil { t.Error(err) return } - - <-done } func TestTranscodingMPEG(t *testing.T) { @@ -141,13 +136,12 @@ func TestTranscodingMPEG(t *testing.T) { return } - done, err := trans.Run() + done := trans.Run() + err = <-done if err != nil { t.Error(err) return } - - <-done } func TestTranscodingOGG(t *testing.T) { @@ -163,13 +157,12 @@ func TestTranscodingOGG(t *testing.T) { return } - done, err := trans.Run() + done := trans.Run() + err = <- done if err != nil { t.Error(err) return } - - <-done } func TestTranscodingWAV(t *testing.T) { @@ -185,13 +178,12 @@ func TestTranscodingWAV(t *testing.T) { return } - done, err := trans.Run() + done := trans.Run() + err = <- done if err != nil { t.Error(err) return } - - <-done } func TestTranscodingWEBM(t *testing.T) { @@ -207,13 +199,12 @@ func TestTranscodingWEBM(t *testing.T) { return } - done, err := trans.Run() + done := trans.Run() + err = <- done if err != nil { t.Error(err) return } - - <-done } func TestTranscodingWMV(t *testing.T) { @@ -229,11 +220,10 @@ func TestTranscodingWMV(t *testing.T) { return } - done, err := trans.Run() + done := trans.Run() + err = <- done if err != nil { t.Error(err) return } - - <-done } diff --git a/transcoder/command.go b/transcoder/command.go deleted file mode 100644 index 37cc4cf..0000000 --- a/transcoder/command.go +++ /dev/null @@ -1,29 +0,0 @@ -package transcoder - -import ( - "fmt" - "log" - "os/exec" -) - -type Worker struct { - Command string - Args string - Output chan string -} - -func (cmd *Worker) Run() { - out, err := exec.Command(cmd.Command, cmd.Args).Output() - if err != nil { - log.Fatal(err) - } - - cmd.Output <- string(out) -} - -func Collect(c chan string) { - for { - msg := <-c - fmt.Printf("The command result is %s\n", msg) - } -} \ No newline at end of file diff --git a/transcoder/transcoder.go b/transcoder/transcoder.go index 6523a48..8477001 100644 --- a/transcoder/transcoder.go +++ b/transcoder/transcoder.go @@ -14,16 +14,17 @@ import ( "strings" "regexp" "strconv" + "io" ) type Transcoder struct { - process *exec.Cmd + stdErrPipe io.ReadCloser mediafile *models.Mediafile configuration ffmpeg.Configuration } -func (t *Transcoder) SetProccess(v *exec.Cmd) { - t.process = v +func (t *Transcoder) SetProcessStderrPipe(v io.ReadCloser) { + t.stdErrPipe = v } func (t *Transcoder) SetMediaFile(v *models.Mediafile) { @@ -36,10 +37,6 @@ func (t *Transcoder) SetConfiguration(v ffmpeg.Configuration) { /*** GETTERS ***/ -func (t Transcoder) Process() *exec.Cmd { - return t.process -} - func (t Transcoder) MediaFile() *models.Mediafile { return t.mediafile } @@ -52,17 +49,10 @@ func (t Transcoder) FFprobeExec() string { return t.configuration.FfprobeBin } -func (t Transcoder) GetCommand() string { - var rcommand string - - rcommand = fmt.Sprintf("%s -y ", t.configuration.FfmpegBin) - +func (t Transcoder) GetCommand() []string { media := t.mediafile - - rcommand += media.ToStrCommand() - + rcommand := append([]string{"-y"}, media.ToStrCommand()...) return rcommand - } /*** FUNCTIONS ***/ @@ -84,25 +74,16 @@ func (t *Transcoder) Initialize(inputPath string, outputPath string) (error) { return errors.New("error: transcoder.Initialize -> input file not found") } - command := fmt.Sprintf("%s -i \"%s\" -print_format json -show_format -show_streams -show_error", configuration.FfprobeBin, inputPath) + command := []string{"-i", inputPath, "-print_format", "json", "-show_format", "-show_streams", "-show_error"} - cmd := exec.Command(configuration.ExecCmd, configuration.ExecArgs, command) - - fmt.Println("FFprobe command: " + command) + cmd := exec.Command(configuration.FfprobeBin, command...) var out bytes.Buffer - cmd.Stdout = &out - err = cmd.Start() - + err = cmd.Run() if err != nil { - return err - } - - _, err = cmd.Process.Wait() - if err != nil { - return err + return fmt.Errorf("Failed FFPROBE (%s) with %s, message %s", command, err, out.String()) } var Metadata models.Metadata @@ -112,151 +93,154 @@ func (t *Transcoder) Initialize(inputPath string, outputPath string) (error) { } // Set new Mediafile - MediaFile := new(models.Mediafile) - MediaFile.SetMetadata(Metadata) - MediaFile.SetInputPath(inputPath) - MediaFile.SetOutputPath(outputPath) - // Set transcoder configuration + MediaFile := new(models.Mediafile) + MediaFile.SetMetadata(Metadata) + MediaFile.SetInputPath(inputPath) + MediaFile.SetOutputPath(outputPath) + // Set transcoder configuration - t.SetMediaFile(MediaFile) - t.SetConfiguration(configuration) + t.SetMediaFile(MediaFile) + t.SetConfiguration(configuration) - return nil + return nil } -func (t *Transcoder) Run() (<-chan bool, error) { - done := make(chan bool) - var err error - +func (t *Transcoder) Run() <-chan error { + done := make(chan error) command := t.GetCommand() - fmt.Println("FFmpeg command: " + command) + proc := exec.Command(t.configuration.FfmpegBin, command...) - proc := exec.Command(t.configuration.ExecCmd, t.configuration.ExecArgs, command) + errStream, err := proc.StderrPipe() + if err != nil { + fmt.Println("Progress not available: "+ err.Error()) + } else { + t.SetProcessStderrPipe(errStream) + } - t.SetProccess(proc) + out := &bytes.Buffer{} + proc.Stdout = out - go func() { - err := proc.Start() + err = proc.Start() + + go func(err error, out *bytes.Buffer, errStream io.ReadCloser) { + defer func() { + if errStream != nil { + errStream.Close() + } + }() if err != nil { + done <- fmt.Errorf("Failed Start FFMPEG (%s) with %s, message %s", command, err, out.String()) + close(done) return } - - proc.Wait() - - done <- true + err = proc.Wait() + if err != nil { + err = fmt.Errorf("Failed Finish FFMPEG (%s) with %s message %s", command, err, out.String()) + } + done <- err close(done) - }() - - return done, err + }(err, out, errStream) + return done } -func (t Transcoder) Output() (<-chan models.Progress, error) { +func (t Transcoder) Output() <-chan models.Progress { out := make(chan models.Progress) - var err error - go func() { - defer close(out) + go func() { + defer close(out) + if t.stdErrPipe == nil { + return + } + scanner := bufio.NewScanner(t.stdErrPipe) + filetype := utils.CheckFileType(t.MediaFile().Metadata().Streams) - stderr, stderror := t.Process().StderrPipe() - if err != nil { - err = stderror - return - } - - scanner := bufio.NewScanner(stderr) - filetype := utils.CheckFileType(t.MediaFile().Metadata().Streams) - - split := func(data []byte, atEOF bool) (advance int, token []byte, spliterror error) { - - if atEOF && len(data) == 0 { - return 0, nil, nil - } - - Iframe := strings.Index(string(data), "frame=") - - if filetype == "video" { - if Iframe > 0 { - return Iframe + 1, data[Iframe:], nil - } - } else { - if i := bytes.IndexByte(data, '\n'); i >= 0 { - // We have a full newline-terminated line. - return i + 1, data[0:i], nil - } - } - - if atEOF { - return len(data), data, nil - } + split := func(data []byte, atEOF bool) (advance int, token []byte, spliterror error) { + if atEOF && len(data) == 0 { return 0, nil, nil } - scanner.Split(split) - buf := make([]byte, 2) - scanner.Buffer(buf, bufio.MaxScanTokenSize) + Iframe := strings.Index(string(data), "frame=") - var lastProgress float64 - for scanner.Scan() { - Progress := new(models.Progress) - line := scanner.Text() - - if strings.Contains(line, "time=") && strings.Contains(line, "bitrate=") { - var re= regexp.MustCompile(`=\s+`) - st := re.ReplaceAllString(line, `=`) - - f := strings.Fields(st) - - var framesProcessed string - var currentTime string - var currentBitrate string - - for j := 0; j < len(f); j++ { - field := f[j] - fieldSplit := strings.Split(field, "=") - - if len(fieldSplit) > 1 { - fieldname := strings.Split(field, "=")[0] - fieldvalue := strings.Split(field, "=")[1] - - if fieldname == "frame" { - framesProcessed = fieldvalue - } - - if fieldname == "time" { - currentTime = fieldvalue - } - - if fieldname == "bitrate" { - currentBitrate = fieldvalue - } - } - } - - timesec := utils.DurToSec(currentTime) - dursec, _ := strconv.ParseFloat(t.MediaFile().Metadata().Format.Duration, 64) - // Progress calculation - progress := (timesec * 100) / dursec - - Progress.Progress = progress - Progress.CurrentBitrate = currentBitrate - Progress.FramesProcessed = framesProcessed - Progress.CurrentTime = currentTime - - if progress != lastProgress { - lastProgress = progress - out <- *Progress - } + if filetype == "video" { + if Iframe > 0 { + return Iframe + 1, data[Iframe:], nil + } + } else { + if i := bytes.IndexByte(data, '\n'); i >= 0 { + // We have a full newline-terminated line. + return i + 1, data[0:i], nil } } - if scerror := scanner.Err(); err != nil { - err = scerror + if atEOF { + return len(data), data, nil } - }() - return out, err + return 0, nil, nil + } + + scanner.Split(split) + buf := make([]byte, 2) + scanner.Buffer(buf, bufio.MaxScanTokenSize) + + var lastProgress float64 + for scanner.Scan() { + Progress := new(models.Progress) + line := scanner.Text() + // fmt.Println(line) + if strings.Contains(line, "time=") && strings.Contains(line, "bitrate=") { + var re= regexp.MustCompile(`=\s+`) + st := re.ReplaceAllString(line, `=`) + + f := strings.Fields(st) + + var framesProcessed string + var currentTime string + var currentBitrate string + + for j := 0; j < len(f); j++ { + field := f[j] + fieldSplit := strings.Split(field, "=") + + if len(fieldSplit) > 1 { + fieldname := strings.Split(field, "=")[0] + fieldvalue := strings.Split(field, "=")[1] + + if fieldname == "frame" { + framesProcessed = fieldvalue + } + + if fieldname == "time" { + currentTime = fieldvalue + } + + if fieldname == "bitrate" { + currentBitrate = fieldvalue + } + } + } + + timesec := utils.DurToSec(currentTime) + dursec, _ := strconv.ParseFloat(t.MediaFile().Metadata().Format.Duration, 64) + // Progress calculation + progress := (timesec * 100) / dursec + + Progress.Progress = progress + Progress.CurrentBitrate = currentBitrate + Progress.FramesProcessed = framesProcessed + Progress.CurrentTime = currentTime + + if progress != lastProgress { + lastProgress = progress + out <- *Progress + } + } + } + }() + + return out } diff --git a/utils/utils.go b/utils/utils.go index b12ff2c..716b13a 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -22,67 +22,34 @@ func DurToSec(dur string) (sec float64) { return secs } -func GetExec() string { +func GetFFmpegExec() []string { var platform = runtime.GOOS - var command = "" + var command = []string{"", "ffmpeg"} switch platform { case "windows": - command = "cmd" + command[0] = "where" break default: - command = "/bin/sh" + command[0] = "which" break } return command } -func GetExecArgs() string { +func GetFFprobeExec() []string { var platform = runtime.GOOS - var args = "" + var command = []string{"", "ffprobe"} switch platform { case "windows": - args = "/C" + command[0] = "where" break default: - args = "-c" + command[0] = "which" break } - - return args -} - -func GetFFmpegExec() string { - var platform = runtime.GOOS - var command = "" - - switch platform { - case "windows": - command = "where ffmpeg" - break - default: - command = "which ffmpeg" - break - } - - return command -} - -func GetFFprobeExec() string { - var platform = runtime.GOOS - var command = "" - - switch platform { - case "windows": - command = "where ffprobe" - break - default: - command = "which ffprobe" - break - } - return command } @@ -98,5 +65,11 @@ func CheckFileType(streams []models.Streams) string { return "audio" } - - +func LineSeparator() string { + switch runtime.GOOS { + case "windows": + return "\r\n" + default: + return "\n" + } +}