package imgconv import ( "bytes" "fmt" "github.com/nfnt/resize" "image/gif" "os" "os/exec" "strings" // "gocv.io/x/gocv" "golang.org/x/image/webp" "image" "image/jpeg" "image/png" "io" "path/filepath" ) // ffmpeg -i file.mp4 -vf "select='eq(n\,20)+eq(n\,40)+eq(n\,60)+eq(n\,80)'" -vsync 0 frame%d.png func scaleEncode(img image.Image) ([]byte, error) { var w, h uint aspect := float64(img.Bounds().Dx()) / float64(img.Bounds().Dy()) if aspect > 1 { w = 128 h = uint(float64(w) / aspect) } else { h = 128 w = uint(float64(h) * aspect) } img = resize.Resize(w, h, img, resize.NearestNeighbor) var buf bytes.Buffer err := png.Encode(&buf, img) if err != nil { return nil, fmt.Errorf("failed to encode image to PNG: %v", err) } return buf.Bytes(), nil } func getFirstFrame(path string) (image.Image, error) { // ffmpeg -i input.mp4 -vframes 1 -f image2pipe -vcodec png - // -vf "select='eq(pict_type\,I)'" -frames:v 1 var out bytes.Buffer cmd := exec.Command("ffmpeg", "-hide_banner", "-loglevel", "error", "-i", path, "-vf", "select='eq(pict_type\\,I)'", "-frames:v", "1", "-vsync", "0", "-f", "image2pipe", "-c:v", "png", "-") // cmd.Stdin = file cmd.Stdout = &out cmd.Stderr = os.Stdout err := cmd.Run() if err != nil { return nil, fmt.Errorf("error running ffmpeg: %v", err) } var img image.Image img, err = png.Decode(&out) if err != nil { return nil, fmt.Errorf("error decoding image: %v", err) } return img, nil } var medidaFuncs = map[string]func(file io.Reader) (image.Image, error){ ".jpg": jpeg.Decode, ".jpeg": jpeg.Decode, ".png": png.Decode, ".webp": webp.Decode, ".gif": gif.Decode, } func Media2Icon(path string) ([]byte, error) { var img image.Image var err error ext := strings.ToLower(filepath.Ext(path)) if ext == ".mp4" { img, err = getFirstFrame(path) } else if fn, ok := medidaFuncs[ext]; ok { var file *os.File file, err = os.Open(path) if err != nil { return nil, fmt.Errorf("error opening file: %v", err) } img, err = fn(file) file.Close() } else { err = fmt.Errorf("unsupported file type: %s", ext) } if err != nil { return nil, fmt.Errorf("error decoding image: %v", err) } return scaleEncode(img) } /* func getFirstFrameAsPNGBytes(videoPath string) ([]byte, error) { // Open the video file video, err := gocv.VideoCaptureFile(videoPath) if err != nil { return nil, fmt.Errorf("error opening video: %v", err) } img := gocv.NewMat() ok := video.Read(&img) if !ok || img.Empty() { img.Close() video.Close() return nil, fmt.Errorf("failed to read the first frame") } imgImg, err := img.ToImage() img.Close() video.Close() if err != nil { return nil, fmt.Errorf("failed to convert frame to image: %v", err) } return scaleEncode(imgImg) } */