package status import ( "bufio" "github.com/fsnotify/fsnotify" "io" "log" "os" "strconv" "strings" "time" ) type Status struct { Frame int FPS float64 Bitrate float64 Dupframes int Speed float64 } //nolint:funlen func FFmpegStatusWatcher(c chan<- Status, path string) error { var ffmpegStatus Status watcher, err := fsnotify.NewWatcher() if err != nil { return err } file, err := os.Open(path) if err != nil { return err } defer file.Close() reader := bufio.NewReader(file) defer watcher.Close() defer close(c) go func() { for { select { case event, ok := <-watcher.Events: if !ok { return } if event.Op&fsnotify.Write == fsnotify.Write { for { line, err := reader.ReadString('\n') if err == io.EOF { break } else if err != nil { log.Println(err) } splits := strings.Split(line, "=") key := strings.TrimSpace(splits[0]) value := strings.TrimSpace(splits[1]) switch key { case "frame": ffmpegStatus.Frame, err = strconv.Atoi(value) case "fps": ffmpegStatus.FPS, err = strconv.ParseFloat(value, 64) case "bitrate": ffmpegStatus.Bitrate, err = strconv.ParseFloat(strings.TrimSuffix(value, "kbits/s"), 64) case "out_time_ms": // test["Progress.Out_time_ms"], err = strconv.Atoi(value) continue case "dup_frames": ffmpegStatus.Dupframes, err = strconv.Atoi(value) case "speed": ffmpegStatus.Speed, err = strconv.ParseFloat(strings.TrimSuffix(value, "x"), 64) } if err != nil { log.Println(err) } } c <- ffmpegStatus } case <-time.After(5 * time.Second): log.Println("Timeout of Status Reading") return case err, ok := <-watcher.Errors: if !ok { return } log.Println("error:", err) } } }() err = watcher.Add(path) return err }