perf: optimize gif via gifsicle

This commit is contained in:
xz-dev 2024-07-16 21:56:00 +08:00
parent e38090e952
commit 47a98ba81b
No known key found for this signature in database
GPG Key ID: A20912F811313E36
1 changed files with 19 additions and 3 deletions

View File

@ -16,6 +16,7 @@
from functools import partial from functools import partial
from io import BytesIO from io import BytesIO
import os.path import os.path
import subprocess
import json import json
import tempfile import tempfile
import mimetypes import mimetypes
@ -55,7 +56,6 @@ def video_to_gif(data: bytes, mime: str) -> bytes:
temp.write(data) temp.write(data)
temp.flush() temp.flush()
with tempfile.NamedTemporaryFile(suffix=ext) as temp_fixed: with tempfile.NamedTemporaryFile(suffix=ext) as temp_fixed:
import subprocess
print(".", end="", flush=True) print(".", end="", flush=True)
result = subprocess.run(["ffmpeg", "-y", "-i", temp.name, "-codec", "copy", temp_fixed.name], result = subprocess.run(["ffmpeg", "-y", "-i", temp.name, "-codec", "copy", temp_fixed.name],
capture_output=True) capture_output=True)
@ -74,6 +74,19 @@ def video_to_gif(data: bytes, mime: str) -> bytes:
return gif.read() 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): def _convert_image(data: bytes, mimetype: str) -> (bytes, int, int):
image: Image.Image = Image.open(BytesIO(data)) image: Image.Image = Image.open(BytesIO(data))
new_file = BytesIO() new_file = BytesIO()
@ -140,8 +153,11 @@ def _convert_sticker(data: bytes) -> (bytes, str, int, int):
data = gif.read() data = gif.read()
mimetype = "image/gif" mimetype = "image/gif"
rlt = _convert_image(data, mimetype) rlt = _convert_image(data, mimetype)
suffix = mimetypes.guess_extension(mimetype) data = rlt[0]
return rlt[0], mimetype, rlt[1], rlt[2] 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): def convert_sticker(data: bytes) -> (bytes, str, int, int):