feat: update video cut and extract head image job
This commit is contained in:
120
backend/pkg/utils/ffmpeg.go
Normal file
120
backend/pkg/utils/ffmpeg.go
Normal file
@@ -0,0 +1,120 @@
|
||||
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 <file>
|
||||
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
|
||||
}
|
||||
@@ -31,3 +31,12 @@ func GetFileMd5(file string) (string, error) {
|
||||
|
||||
return fmt.Sprintf("%x", h.Sum(nil)), nil
|
||||
}
|
||||
|
||||
// GetFileSize
|
||||
func GetFileSize(file string) (int64, error) {
|
||||
fi, err := os.Stat(file)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return fi.Size(), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user