Skip to content

Commit

Permalink
Merge pull request #2 from Ovler-Young/compress-gif-for-wechat
Browse files Browse the repository at this point in the history
Fix some transparency issue ontelegram stickers
  • Loading branch information
Ovler-Young authored Mar 6, 2024
2 parents 0850aeb + 49140d5 commit cbe43ec
Showing 1 changed file with 64 additions and 13 deletions.
77 changes: 64 additions & 13 deletions efb_telegram_master/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,22 @@ def chat_id_str_to_id(s: EFBChannelChatIDStr) -> Tuple[ModuleID, ChatID, Optiona
group_id = ChatID(ids[2])
return channel_id, chat_uid, group_id

def _png_gif_prepare(image):
""" Fork of lottie.exporters.gif.export_gif
Adapted from eltiempoes/python-lottie
https://github.com/eltiempoes/python-lottie/blob/a9f8be4858adb7eb0bc0e406a870b19c309c8a36/lib/lottie/exporters/gif.py#L10
License:
AGPL 3.0 (Python Lottie)
"""
if image.mode not in ["RGBA", "RGBa"]:
image = image.convert("RGBA")
alpha = image.getchannel("A")
image = image.convert(image.mode[:-1]) \
.convert('P', palette=Image.ADAPTIVE, colors=255) # changed
mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0)
image.paste(255, mask=mask)
image.info['transparency'] = 255 # added
return image

def export_gif(animation, fp, dpi=96, skip_frames=5):
""" Fork of lottie.exporters.gif.export_gif
Expand All @@ -172,7 +188,7 @@ def export_gif(animation, fp, dpi=96, skip_frames=5):
# Import only upon calling the method due to added binary dependencies
# (libcairo)
from lottie.exporters.cairo import export_png
from lottie.exporters.gif import _png_gif_prepare
# from lottie.exporters.gif import _png_gif_prepare # The code here have some problem, so I copy the function abo ve

start = int(animation.in_point)
end = int(animation.out_point)
Expand All @@ -183,7 +199,7 @@ def export_gif(animation, fp, dpi=96, skip_frames=5):
file.seek(0)
frames.append(_png_gif_prepare(Image.open(file)))

duration = 1000 / animation.frame_rate * (1 + skip_frames) / 2
duration = 1000 / animation.frame_rate * (1 + skip_frames) # why /2 before?
frames[0].save(
fp,
format='GIF',
Expand All @@ -207,7 +223,7 @@ def convert_tgs_to_gif(tgs_file: BinaryIO, gif_file: BinaryIO) -> bool:
# heavy_strip(animation)
# heavy_strip(animation)
# animation.tgs_sanitize()
export_gif(animation, gif_file, skip_frames=5, dpi=48)
export_gif(animation, gif_file, skip_frames=5, dpi=48) # skip_frames = 5 means select one frame in every 5 frames
return True
except Exception:
logging.exception("Error occurred while converting TGS to GIF.")
Expand Down Expand Up @@ -258,12 +274,28 @@ def gif_conversion(file: IO[bytes], channel_id: str) -> IO[bytes]:

# Set input/output of ffmpeg to stream
stream = ffmpeg.input("pipe:")
if channel_id.startswith("blueset.wechat") and metadata.get('width', 0) > 600:
# Workaround: Compress GIF for slave channel `blueset.wechat`
# TODO: Move this logic to `blueset.wechat` in the future
stream = stream.filter("scale", 600, -2)
if metadata['streams'][0]['codec_name'] == 'vp9':
stream = ffmpeg.input(file.name, vcodec='libvpx-vp9')
split = (
stream
.split()
)
stream_paletteuse = (
ffmpeg
.filter(
[
split[0],
split[1]
.filter(
filter_name='palettegen',
reserve_transparent='on',
)
],
filter_name='paletteuse',
)
)
# Need to specify file format here as no extension hint presents.
args = stream.output("pipe:", format="gif").compile()
args = stream_paletteuse.output("pipe:", format="gif").compile()
file.seek(0)

# subprocess.Popen would still try to access the file handle instead of
Expand Down Expand Up @@ -294,11 +326,30 @@ def gif_conversion(file: IO[bytes], channel_id: str) -> IO[bytes]:
file.seek(0)
metadata = ffmpeg.probe(file.name)
stream = ffmpeg.input(file.name)
if channel_id.startswith("blueset.wechat") and metadata.get('width', 0) > 600:
# Workaround: Compress GIF for slave channel `blueset.wechat`
# TODO: Move this logic to `blueset.wechat` in the future
stream = stream.filter("scale", 600, -2)
stream.output(gif_file.name).overwrite_output().run()
# 检查视频编码类型是否为VP9
if metadata['streams'][0]['codec_name'] == 'vp9':
stream = ffmpeg.input(file.name, vcodec='libvpx-vp9') # 只有这个能保持透明背景
split = (
stream
.split()
)
stream_paletteuse = (
ffmpeg
.filter(
[
split[0],
split[1]
.filter(
filter_name='palettegen',
reserve_transparent='on',
)
],
filter_name='paletteuse',
)
)
stream_paletteuse.output(gif_file.name).overwrite_output().run()
new_file_size = os.path.getsize(gif_file.name)
print(f"file_size: {new_file_size/1024}KB")
file.close()
gif_file.seek(0)
return gif_file

0 comments on commit cbe43ec

Please sign in to comment.