video.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package renderer
  2. import (
  3. "bytes"
  4. "errors"
  5. "image"
  6. "image/jpeg"
  7. "os"
  8. "os/exec"
  9. "path/filepath"
  10. "github.com/oliamb/cutter"
  11. )
  12. func generateThumbnailForVideo(inputFile string, outputFolder string) error {
  13. if _, err := os.Stat(inputFile); os.IsNotExist(err) {
  14. // The user removed this file before the thumbnail is finished
  15. return errors.New("source not exists")
  16. }
  17. outputFile := filepath.Join(outputFolder, filepath.Base(inputFile)+".jpg")
  18. absInputFile, err := filepath.Abs(inputFile)
  19. if err != nil {
  20. return errors.New("failed to get absolute path of input file")
  21. }
  22. absOutputFile, err := filepath.Abs(outputFile)
  23. if err != nil {
  24. return errors.New("failed to get absolute path of output file")
  25. }
  26. //Get the first thumbnail using ffmpeg
  27. cmd := exec.Command("ffmpeg", "-i", absInputFile, "-ss", "00:00:05.000", "-vframes", "1", "-vf", "scale=-1:480", absOutputFile)
  28. _, err = cmd.CombinedOutput()
  29. if err != nil {
  30. return err
  31. }
  32. //Resize and crop the output image
  33. if _, err := os.Stat(outputFile); err == nil {
  34. imageBytes, err := os.ReadFile(outputFile)
  35. if err != nil {
  36. return err
  37. }
  38. os.Remove(outputFile)
  39. img, _, err := image.Decode(bytes.NewReader(imageBytes))
  40. if err != nil {
  41. return err
  42. } else {
  43. //Crop out the center
  44. croppedImg, err := cutter.Crop(img, cutter.Config{
  45. Width: 480,
  46. Height: 480,
  47. Mode: cutter.Centered,
  48. })
  49. if err == nil {
  50. //Write it back to the original file
  51. out, _ := os.Create(outputFile)
  52. jpeg.Encode(out, croppedImg, nil)
  53. out.Close()
  54. } else {
  55. //log.Println(err)
  56. }
  57. }
  58. }
  59. return nil
  60. }