summaryrefslogtreecommitdiff
path: root/internal/media/ffmpeg.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/media/ffmpeg.go')
-rw-r--r--internal/media/ffmpeg.go67
1 files changed, 60 insertions, 7 deletions
diff --git a/internal/media/ffmpeg.go b/internal/media/ffmpeg.go
index add79e26b..6d4c9ac87 100644
--- a/internal/media/ffmpeg.go
+++ b/internal/media/ffmpeg.go
@@ -47,10 +47,21 @@ func ffmpegClearMetadata(ctx context.Context, filepath string, ext string) error
// Clear metadata with ffmpeg.
if err := ffmpeg(ctx, dirpath,
"-loglevel", "error",
+
+ // Input file.
"-i", filepath,
+
+ // Drop all metadata.
"-map_metadata", "-1",
+
+ // Copy input codecs,
+ // i.e. no transcode.
"-codec", "copy",
+
+ // Overwrite.
"-y",
+
+ // Output.
outpath,
); err != nil {
return err
@@ -64,23 +75,54 @@ func ffmpegClearMetadata(ctx context.Context, filepath string, ext string) error
return nil
}
-// ffmpegGenerateThumb generates a thumbnail jpeg from input media of any type, useful for any media.
+// ffmpegGenerateThumb generates a thumbnail webp from input media of any type, useful for any media.
func ffmpegGenerateThumb(ctx context.Context, filepath string, width, height int) (string, error) {
+
// Get directory from filepath.
dirpath := path.Dir(filepath)
// Generate output frame file path.
- outpath := filepath + "_thumb.jpg"
+ outpath := filepath + "_thumb.webp"
+
+ // Thumbnail size scaling argument.
+ scale := strconv.Itoa(width) + ":" +
+ strconv.Itoa(height)
// Generate thumb with ffmpeg.
if err := ffmpeg(ctx, dirpath,
"-loglevel", "error",
+
+ // Input file.
"-i", filepath,
- "-filter:v", "thumbnail=n=10",
- "-filter:v", "scale="+strconv.Itoa(width)+":"+strconv.Itoa(height),
- "-qscale:v", "12", // ~ 70% quality
+
+ // Encode using libwebp.
+ // (NOT as libwebp_anim).
+ "-codec:v", "libwebp",
+
+ // Select thumb from first 10 frames
+ // (thumb filter: https://ffmpeg.org/ffmpeg-filters.html#thumbnail)
+ "-filter:v", "thumbnail=n=10,"+
+
+ // scale to dimensions
+ // (scale filter: https://ffmpeg.org/ffmpeg-filters.html#scale)
+ "scale="+scale+","+
+
+ // YUVA 4:2:0 pixel format
+ // (format filter: https://ffmpeg.org/ffmpeg-filters.html#format)
+ "format=pix_fmts=yuva420p",
+
+ // Only one frame
"-frames:v", "1",
+
+ // ~40% webp quality
+ // (codec options: https://ffmpeg.org/ffmpeg-codecs.html#toc-Codec-Options)
+ // (libwebp codec: https://ffmpeg.org/ffmpeg-codecs.html#Options-36)
+ "-qscale:v", "40",
+
+ // Overwrite.
"-y",
+
+ // Output.
outpath,
); err != nil {
return "", err
@@ -100,10 +142,21 @@ func ffmpegGenerateStatic(ctx context.Context, filepath string) (string, error)
// Generate static with ffmpeg.
if err := ffmpeg(ctx, dirpath,
"-loglevel", "error",
+
+ // Input file.
"-i", filepath,
- "-codec:v", "png", // specifically NOT 'apng'
- "-frames:v", "1", // in case animated, only take 1 frame
+
+ // Only first frame.
+ "-frames:v", "1",
+
+ // Encode using png.
+ // (NOT as apng).
+ "-codec:v", "png",
+
+ // Overwrite.
"-y",
+
+ // Output.
outpath,
); err != nil {
return "", err