Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the forked code is already above, this line can be removed.


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?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The / 2 was brought over as a part of the original function. I’m not quite sure what it stands for though.

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()
)
Comment on lines +279 to +282
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be simplifed.

Suggested change
split = (
stream
.split()
)
split = stream.split()

stream_paletteuse = (
ffmpeg
.filter(
[
split[0],
split[1]
.filter(
filter_name='palettegen',
reserve_transparent='on',
)
],
filter_name='paletteuse',
)
)
Comment on lines +283 to +296
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be simplified:

Suggested change
stream_paletteuse = (
ffmpeg
.filter(
[
split[0],
split[1]
.filter(
filter_name='palettegen',
reserve_transparent='on',
)
],
filter_name='paletteuse',
)
)
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') # 只有这个能保持透明背景
Comment on lines +329 to +331
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep code comments in English.

split = (
stream
.split()
)
stream_paletteuse = (
ffmpeg
.filter(
[
split[0],
split[1]
.filter(
filter_name='palettegen',
reserve_transparent='on',
)
],
filter_name='paletteuse',
)
)
Comment on lines +332 to +349
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be simplified. See above.

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")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use logging for debug logs. Avoid using print directly.

file.close()
gif_file.seek(0)
return gif_file