diff --git a/internal/ffmpeg/ffprobe.go b/internal/ffmpeg/ffprobe.go index 8aa18fc..ac8c2f9 100644 --- a/internal/ffmpeg/ffprobe.go +++ b/internal/ffmpeg/ffprobe.go @@ -5,11 +5,14 @@ import ( "fyne.io/fyne/v2/lang" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/utils" "os/exec" + "strconv" "strings" + "unicode" ) type FFprobeContract interface { GetPath() string + GetTotalDuration(file *File) (float64, error) } type ffprobe struct { @@ -38,6 +41,50 @@ func (f *ffprobe) GetPath() string { return f.path } +func (f *ffprobe) GetTotalDuration(file *File) (duration float64, err error) { + args := []string{"-v", "error", "-select_streams", "v:0", "-count_packets", "-show_entries", "stream=nb_read_packets", "-of", "csv=p=0", file.Path} + cmd := exec.Command(f.path, args...) + utils.PrepareBackgroundCommand(cmd) + out, err := cmd.CombinedOutput() + if err != nil { + errString := strings.TrimSpace(string(out)) + if len(errString) > 1 { + return 0, errors.New(errString) + } + return 0, err + } + frames := strings.TrimSpace(string(out)) + if len(frames) == 0 { + return f.getAlternativeTotalDuration(file) + } + + duration, err = strconv.ParseFloat(frames, 64) + if err != nil { + // fix .mts duration + return strconv.ParseFloat(getFirstDigits(frames), 64) + } + return duration, err +} + +func (f *ffprobe) getAlternativeTotalDuration(file *File) (duration float64, err error) { + args := []string{"-v", "error", "-select_streams", "a:0", "-count_packets", "-show_entries", "stream=nb_read_packets", "-of", "csv=p=0", file.Path} + cmd := exec.Command(f.path, args...) + utils.PrepareBackgroundCommand(cmd) + out, err := cmd.CombinedOutput() + if err != nil { + errString := strings.TrimSpace(string(out)) + if len(errString) > 1 { + return 0, errors.New(errString) + } + return 0, err + } + frames := strings.TrimSpace(string(out)) + if len(frames) == 0 { + return 0, errors.New("error getting number of frames") + } + return strconv.ParseFloat(frames, 64) +} + func checkFFprobePath(path string) (bool, error) { cmd := exec.Command(path, "-version") utils.PrepareBackgroundCommand(cmd) @@ -50,3 +97,15 @@ func checkFFprobePath(path string) (bool, error) { } return true, nil } + +func getFirstDigits(s string) string { + result := "" + for _, r := range s { + if unicode.IsDigit(r) { + result += string(r) + } else { + break + } + } + return result +}