Skip to content

Commit

Permalink
Merge pull request #2 from Ovler-Young/gif-compression
Browse files Browse the repository at this point in the history
add gif compression
  • Loading branch information
Ovler-Young authored Mar 6, 2024
2 parents bfe44d6 + db730f5 commit 9269edc
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 5 deletions.
7 changes: 3 additions & 4 deletions efb_wechat_slave/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from .__version__ import __version__
from .chats import ChatManager
from .slave_message import SlaveMessageManager
from .utils import ExperimentalFlagsManager
from .utils import ExperimentalFlagsManager, gif_conversion
from .vendor import wxpy
from .vendor.wxpy import ResponseError
from .vendor.wxpy.utils import PuidMap
Expand Down Expand Up @@ -436,9 +436,6 @@ def send_message(self, msg: Message) -> Message:
self.logger.debug(
'[%s] Image converted from %s to GIF', msg.uid, msg.mime)
file.close()
if f.seek(0, 2) > self.MAX_FILE_SIZE:
raise EFBMessageError(
self._("Image size is too large. (IS02)"))
f.seek(0)
r.append(self._bot_send_image(chat, f.name, f))
finally:
Expand All @@ -464,6 +461,8 @@ def send_message(self, msg: Message) -> Message:
if not file.closed:
file.close()
else:
if msg.mime == "image/gif" and file.seek(0, 2) > 1048576:
file = gif_conversion(file)
try:
if file.seek(0, 2) > self.MAX_FILE_SIZE:
raise EFBMessageError(
Expand Down
61 changes: 60 additions & 1 deletion efb_wechat_slave/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
import base64
import io
import os
import subprocess
import json
from typing import Dict, Any, TYPE_CHECKING, List
from tempfile import NamedTemporaryFile
from typing import Dict, Any, TYPE_CHECKING, List, IO


from ehforwarderbot.types import MessageID
from .vendor.itchat import utils as itchat_utils
Expand Down Expand Up @@ -221,3 +224,59 @@ def print_st():
res += base64.b64encode(file.getvalue()).decode()
res += print_st()
return res


if os.name == "nt":
# Workaround for Windows which cannot open the same file as "read" twice.
# Using stdin/stdout pipe for IO with ffmpeg.
# Said to be only working with a few encodings. It seems that Telegram GIF
# (MP4, h264, soundless) luckily felt in that range.
#
# See: https://etm.1a23.studio/issues/90

def gif_conversion(file: IO[bytes]) -> IO[bytes]:
"""Convert Telegram GIF to real GIF, the NT way."""
file.seek(0)
new_file_size = os.path.getsize(file.name)
print(f"file_size: {new_file_size/1024}KB")
if new_file_size > 1024 * 1024:
# try to use gifsicle lossy compression
compress_file = NamedTemporaryFile(suffix='.gif')
subprocess.run(["gifsicle", "--resize-method=catrom", "--lossy=100", "-O2", "-o", compress_file.name, file.name], check=True)
new_file_size = os.path.getsize(compress_file.name)
if new_file_size > 1024 * 1024:
scales = [512, 480, 400, 360, 300, 256, 250, 200, 150, 100]
for scale in scales:
subprocess.run(["gifsicle", "--resize-method=catrom", "--resize-fit", f"{scale}x{scale}", "--lossy=100", "-O2", "-o", compress_file.name, file.name], check=True)
new_file_size = os.path.getsize(compress_file.name)
print(f"new_file_size: {new_file_size/1024}KB after resize to {scale}x{scale}")
if new_file_size < 1024 * 1024:
break
file.close()
file = compress_file
file.seek(0)
return file

else:
def gif_conversion(file: IO[bytes]) -> IO[bytes]:
"""Convert Telegram GIF to real GIF, the non-NT way."""
file.seek(0)
new_file_size = os.path.getsize(file.name)
print(f"file_size: {new_file_size/1024}KB")
if new_file_size > 1024 * 1024:
# try to use gifsicle lossy compression
compress_file = NamedTemporaryFile(suffix='.gif')
subprocess.run(["gifsicle", "--resize-method=catrom", "--lossy=100", "-O2", "-o", compress_file.name, file.name], check=True)
new_file_size = os.path.getsize(compress_file.name)
if new_file_size > 1024 * 1024:
scales = [512, 480, 400, 360, 300, 256, 250, 200, 150, 100]
for scale in scales:
subprocess.run(["gifsicle", "--resize-method=catrom", "--resize-fit", f"{scale}x{scale}", "--lossy=100", "-O2", "-o", compress_file.name, file.name], check=True)
new_file_size = os.path.getsize(compress_file.name)
print(f"new_file_size: {new_file_size/1024}KB after resize to {scale}x{scale}")
if new_file_size < 1024 * 1024:
break
file.close()
file = compress_file
file.seek(0)
return file

0 comments on commit 9269edc

Please sign in to comment.