From 11cb15aa0e6ec34c2c827fb586c04f7faf406eac Mon Sep 17 00:00:00 2001 From: lifegpc Date: Sun, 9 Jun 2024 12:01:18 +0800 Subject: [PATCH] FFMPEG Binary support contain and cover generate method --- Dockerfile | 2 +- routes/api/thumbnail/[id].ts | 7 +++--- thumbnail/base.ts | 1 + thumbnail/ffmpeg_binary.ts | 46 ++++++++++++++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9c8eb9d..6aabc96 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,7 +34,7 @@ RUN cd ~ && \ --disable-parsers --enable-parser=h264,png,gif \ --disable-bsfs --enable-bsf=dts2pts,null \ --disable-protocols --enable-protocol=async,concat,concatf,data,fd,file,md5,pipe,subfile \ - --disable-devices --disable-filters --enable-filter=scale && \ + --disable-devices --disable-filters --enable-filter=crop,pad,scale && \ make -j$(grep -c ^processor /proc/cpuinfo) && make install && \ cd ~ && rm -rf FFmpeg-n7.0.1 ffmpeg.tar.gz diff --git a/routes/api/thumbnail/[id].ts b/routes/api/thumbnail/[id].ts index 586de90..d531fc5 100644 --- a/routes/api/thumbnail/[id].ts +++ b/routes/api/thumbnail/[id].ts @@ -111,12 +111,13 @@ export const handler: Handlers = { return Response.redirect(`${get_host(req)}/api/file/${f.id}`); } } - if (method === ThumbnailMethod.FFMPEG_BINARY) { - cfg.method = ThumbnailGenMethod.Unknown; - } const output = generate_filename(b, f, cfg); if (!(await exists(output))) { if (method === ThumbnailMethod.FFMPEG_BINARY) { + cfg.input = { + width: Number(f.width), + height: Number(f.height), + }; const re = await fb_generate_thumbnail( m.cfg.ffmpeg_path, f.path, diff --git a/thumbnail/base.ts b/thumbnail/base.ts index f0b791b..42de7ed 100644 --- a/thumbnail/base.ts +++ b/thumbnail/base.ts @@ -23,6 +23,7 @@ export type ThumbnailConfig = { quality: number; method: ThumbnailGenMethod; align: ThumbnailAlign; + input?: { width: number; height: number }; }; export function gen_thumbnail_config_params(cfg: ThumbnailConfig) { diff --git a/thumbnail/ffmpeg_binary.ts b/thumbnail/ffmpeg_binary.ts index b191979..abe9f2b 100644 --- a/thumbnail/ffmpeg_binary.ts +++ b/thumbnail/ffmpeg_binary.ts @@ -1,4 +1,5 @@ -import type { ThumbnailConfig } from "./base.ts"; +import { ThumbnailAlign } from "./base.ts"; +import { type ThumbnailConfig, ThumbnailGenMethod } from "./base.ts"; export async function check_ffmpeg_binary(p: string) { const cmd = new Deno.Command(p, { @@ -45,18 +46,59 @@ export async function fb_generate_thumbnail( o: string, cfg: ThumbnailConfig, ) { + let add = ""; + if (cfg.method == ThumbnailGenMethod.Cover) { + const size = cfg.input ?? await fb_get_size(i); + if (!size) return false; + const twidth = Math.floor(size.width * cfg.height / size.height); + const frwidth = Math.floor(twidth > cfg.width ? twidth : cfg.width); + const frheight = Math.floor( + twidth > cfg.width + ? cfg.height + : size.height * cfg.width / size.width, + ); + const xy = cfg.align == ThumbnailAlign.Center + ? "" + : cfg.align == ThumbnailAlign.Left + ? ":x=0:y=0" + : `:x=${frwidth - cfg.width}:y=${frheight - cfg.height}`; + add = + `scale=${frwidth}x${frheight},crop=${cfg.width}:${cfg.height}${xy}`; + } else if (cfg.method == ThumbnailGenMethod.Contain) { + const size = cfg.input ?? await fb_get_size(i); + if (!size) return false; + const twidth = Math.floor(size.width * cfg.height / size.height); + const frwidth = Math.floor(twidth > cfg.width ? cfg.width : twidth); + const frheight = Math.floor( + twidth > cfg.width + ? size.height * cfg.width / size.width + : cfg.height, + ); + const xy = cfg.align == ThumbnailAlign.Center + ? `:x=${Math.floor((cfg.width - frwidth) / 2)}:y=${ + Math.floor((cfg.height - frheight) / 2) + }` + : cfg.align == ThumbnailAlign.Left + ? "" + : `:x=${cfg.width - frwidth}:y=${cfg.height - frheight}`; + add = + `scale=${frwidth}x${frheight},pad=${cfg.width}:${cfg.height}${xy}:color=white`; + } else { + add = `scale=${cfg.width}:${cfg.height}`; + } const args = [ "-n", "-i", i, "-vf", - `scale=${cfg.width}:${cfg.height}`, + add, "-qmin", `${cfg.quality}`, "-qmax", `${cfg.quality}`, o, ]; + console.log(args); const cmd = new Deno.Command(p, { args, stdout: "null", stderr: "piped" }); const c = cmd.spawn(); const s = await c.output();