From 47a98ba81b68076c578d88fb627acd4f0c0ca1ca Mon Sep 17 00:00:00 2001 From: xz-dev Date: Tue, 16 Jul 2024 21:56:00 +0800 Subject: [PATCH] perf: optimize gif via gifsicle --- sticker/lib/util.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/sticker/lib/util.py b/sticker/lib/util.py index b2796bd..e84b450 100644 --- a/sticker/lib/util.py +++ b/sticker/lib/util.py @@ -16,6 +16,7 @@ from functools import partial from io import BytesIO import os.path +import subprocess import json import tempfile import mimetypes @@ -55,7 +56,6 @@ def video_to_gif(data: bytes, mime: str) -> bytes: temp.write(data) temp.flush() with tempfile.NamedTemporaryFile(suffix=ext) as temp_fixed: - import subprocess print(".", end="", flush=True) result = subprocess.run(["ffmpeg", "-y", "-i", temp.name, "-codec", "copy", temp_fixed.name], capture_output=True) @@ -74,6 +74,19 @@ def video_to_gif(data: bytes, mime: str) -> bytes: return gif.read() +def opermize_gif(data: bytes) -> bytes: + with tempfile.NamedTemporaryFile() as gif: + gif.write(data) + gif.flush() + # use gifsicle to optimize gif + result = subprocess.run(["gifsicle", "--batch", "--optimize=3", "--colors=256", gif.name], + capture_output=True) + if result.returncode != 0: + raise RuntimeError(f"Run gifsicle failed with code {result.returncode}, Error occurred:\n{result.stderr}") + gif.seek(0) + return gif.read() + + def _convert_image(data: bytes, mimetype: str) -> (bytes, int, int): image: Image.Image = Image.open(BytesIO(data)) new_file = BytesIO() @@ -140,8 +153,11 @@ def _convert_sticker(data: bytes) -> (bytes, str, int, int): data = gif.read() mimetype = "image/gif" rlt = _convert_image(data, mimetype) - suffix = mimetypes.guess_extension(mimetype) - return rlt[0], mimetype, rlt[1], rlt[2] + data = rlt[0] + if mimetype == "image/gif": + print(".", end="", flush=True) + data = opermize_gif(data) + return data, mimetype, rlt[1], rlt[2] def convert_sticker(data: bytes) -> (bytes, str, int, int):