package utils import ( "bufio" "context" "os/exec" "strconv" "strings" "github.com/go-pay/errgroup" "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) func GetMediaDuration(path string) (int64, error) { // use ffprobe to get media duration // ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 cmd := exec.Command("ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", path) durationOutput, err := cmd.Output() if err != nil { return 0, errors.Wrap(err, "ffprobe error") } duration := string(durationOutput) duration = strings.TrimSpace(duration) durationInt, err := strconv.Atoi(duration) if err != nil { return 0, errors.Wrap(err, "duration conversion error") } return int64(durationInt), nil } func CutMedia(input, output string, start, end int64) error { // ffmpeg -ss 00:00:00 -i input.mp4 -to 00:01:00 -c copy output.mp4 cmd := exec.Command("ffmpeg", "-ss", strconv.FormatInt(start, 10), "-i", input, "-t", strconv.FormatInt(end, 10), "-c", "copy", output) stdout, err := cmd.StdoutPipe() if err != nil { log.Errorf("Error creating stdout pipe: %v", err) return err } stderr, err := cmd.StderrPipe() if err != nil { log.Errorf("Error creating stderr pipe: %v", err) return err } if err := cmd.Start(); err != nil { log.Errorf("Error starting command: %v", err) return err } var eg errgroup.Group eg.Go(func(ctx context.Context) error { scanner := bufio.NewScanner(stdout) for scanner.Scan() { log.Info(scanner.Text()) } return nil }) eg.Go(func(ctx context.Context) error { scanner := bufio.NewScanner(stderr) for scanner.Scan() { log.Error(scanner.Text()) } return nil }) if err := cmd.Wait(); err != nil { log.Errorf("Error waiting for command: %v", err) return err } if err := eg.Wait(); err != nil { log.Errorf("Error waiting for command: %v", err) return err } return nil } // GetFrameImageFromVideo extracts target time frame from a video file and saves it as an image. func GetFrameImageFromVideo(input, output string, time int64) error { // ffmpeg -i input.mp4 -ss 00:00:01 -vframes 1 output.jpg cmd := exec.Command("ffmpeg", "-i", input, "-ss", strconv.FormatInt(time, 10), "-vframes", "1", output) stdout, err := cmd.StdoutPipe() if err != nil { return errors.Wrap(err, "stdout pipe error") } stderr, err := cmd.StderrPipe() if err != nil { return errors.Wrap(err, "stderr pipe error") } if err := cmd.Start(); err != nil { return errors.Wrap(err, "command start error") } var eg errgroup.Group eg.Go(func(ctx context.Context) error { scanner := bufio.NewScanner(stdout) for scanner.Scan() { log.Info(scanner.Text()) } return nil }) eg.Go(func(ctx context.Context) error { scanner := bufio.NewScanner(stderr) for scanner.Scan() { log.Error(scanner.Text()) } return nil }) if err := cmd.Wait(); err != nil { return errors.Wrap(err, "command wait error") } if err := eg.Wait(); err != nil { return errors.Wrap(err, "command wait error") } return nil }