From a5fe05cff24a4496aebd777d66c3a94b7eda934d Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 12 Aug 2022 22:07:52 +0300 Subject: [PATCH] Add support for converting animated stickers to webp --- mautrix_telegram/example-config.yaml | 3 ++- mautrix_telegram/formatter/from_telegram.py | 2 +- mautrix_telegram/util/file_transfer.py | 7 +++++- mautrix_telegram/util/tgs_converter.py | 26 +++++++++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/mautrix_telegram/example-config.yaml b/mautrix_telegram/example-config.yaml index 688e3fb0..b6f1c291 100644 --- a/mautrix_telegram/example-config.yaml +++ b/mautrix_telegram/example-config.yaml @@ -228,12 +228,13 @@ bridge: # png - converts to non-animated png (fastest), # gif - converts to animated gif # webm - converts to webm video, requires ffmpeg executable with vp9 codec and webm container support + # webp - converts to animated webp, requires ffmpeg executable with webp codec/container support target: gif # Arguments for converter. All converters take width and height. args: width: 256 height: 256 - fps: 25 # only for webm and gif (2, 5, 10, 20 or 25 recommended) + fps: 25 # only for webm, webp and gif (2, 5, 10, 20 or 25 recommended) # End-to-bridge encryption support options. # # See https://docs.mau.fi/bridges/general/end-to-bridge-encryption.html for more info. diff --git a/mautrix_telegram/formatter/from_telegram.py b/mautrix_telegram/formatter/from_telegram.py index 48711583..57c3746d 100644 --- a/mautrix_telegram/formatter/from_telegram.py +++ b/mautrix_telegram/formatter/from_telegram.py @@ -280,7 +280,7 @@ async def _telegram_entities_to_matrix( html.append(entity_text) elif entity_type == ReuploadedCustomEmoji: html.append( - f'' ) elif entity_type in ( diff --git a/mautrix_telegram/util/file_transfer.py b/mautrix_telegram/util/file_transfer.py index aef55145..f9a42c5a 100644 --- a/mautrix_telegram/util/file_transfer.py +++ b/mautrix_telegram/util/file_transfer.py @@ -228,13 +228,18 @@ async def transfer_custom_emojis_to_matrix( GetCustomEmojiDocumentsRequest(document_id=not_existing_ids) ) + tgs_args = source.config["bridge.animated_sticker"] + if tgs_args["target"] == "webm": + # Inline images can't be videos, let's hope animated webp is supported + tgs_args = {**tgs_args, "target": "webp"} + async def transfer(document: Document) -> None: file_map[document.id] = await transfer_file_to_matrix( source.client, source.bridge.az.intent, document, is_sticker=True, - tgs_convert={"target": "png", "args": {"width": 256, "height": 256}}, + tgs_convert=tgs_args, filename=f"emoji-{document.id}", # Emojis are used as inline images and can't be encrypted encrypt=False, diff --git a/mautrix_telegram/util/tgs_converter.py b/mautrix_telegram/util/tgs_converter.py index 5c0cd3b1..dc48c508 100644 --- a/mautrix_telegram/util/tgs_converter.py +++ b/mautrix_telegram/util/tgs_converter.py @@ -126,7 +126,33 @@ if lottieconverter and ffmpeg: log.error(str(e)) return ConvertedSticker("application/gzip", file) + async def tgs_to_webp( + file: bytes, width: int, height: int, fps: int = 30, **_: Any + ) -> ConvertedSticker: + with tempfile.TemporaryDirectory(prefix="tgs_") as tmpdir: + file_template = tmpdir + "/out_" + try: + await _run_lottieconverter( + args=("-", file_template, "pngs", f"{width}x{height}", str(fps)), + input_data=file, + ) + first_frame_name = min(os.listdir(tmpdir)) + with open(f"{tmpdir}/{first_frame_name}", "rb") as first_frame_file: + first_frame_data = first_frame_file.read() + webp_data = await ffmpeg.convert_path( + input_args=("-framerate", str(fps), "-pattern_type", "glob"), + input_file=f"{file_template}*.png", + output_args=("-c:v", "libwebp_anim", "-pix_fmt", "yuva420p", "-f", "webp"), + output_path_override="-", + output_extension=None, + ) + return ConvertedSticker("image/webp", webp_data, "image/png", first_frame_data) + except ffmpeg.ConverterError as e: + log.error(str(e)) + return ConvertedSticker("application/gzip", file) + converters["webm"] = tgs_to_webm + converters["webp"] = tgs_to_webp async def convert_tgs_to(