Add support for converting video stickers to images

This commit is contained in:
Tulir Asokan
2022-08-14 00:46:02 +03:00
parent 1216607763
commit c54ae9548f
7 changed files with 89 additions and 7 deletions
+4 -1
View File
@@ -6,7 +6,7 @@ Minimum Conduit version remains at 0.4.0.
### Added
* Added provisioning API for resolving Telegram identifiers (like usernames).
* Added basic bridging of Telegram custom emojis to Matrix.
* Added support for bridging Telegram custom emojis to Matrix.
* Added option to not bridge chats with lots of members.
* Added option to include captions in the same message as the media to
implement [MSC2530]. Sending captions the same way is also supported and
@@ -33,6 +33,9 @@ Minimum Conduit version remains at 0.4.0.
### Improved
* Improved handling the bridge user leaving chats on Telegram, and new users
being added on Telegram.
* Improved animated sticker conversion options: added support for animated webp
and added option to convert video stickers (webm) to the specified image
format.
* Audio and video metadata is now bridged properly to Telegram.
* Added database index on Telegram usernames (used when bridging username
@-mentions in messages).
+5
View File
@@ -145,9 +145,14 @@ class Config(BaseBridgeConfig):
copy("bridge.parallel_file_transfer")
copy("bridge.federate_rooms")
copy("bridge.animated_sticker.target")
copy("bridge.animated_sticker.convert_from_webm")
copy("bridge.animated_sticker.args.width")
copy("bridge.animated_sticker.args.height")
copy("bridge.animated_sticker.args.fps")
copy("bridge.animated_emoji.target")
copy("bridge.animated_emoji.args.width")
copy("bridge.animated_emoji.args.height")
copy("bridge.animated_emoji.args.fps")
copy("bridge.private_chat_portal_meta")
copy("bridge.delivery_receipts")
copy("bridge.delivery_error_reports")
+11
View File
@@ -230,11 +230,22 @@ bridge:
# 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
# Should video stickers be converted to the specified format as well?
convert_from_webm: false
# Arguments for converter. All converters take width and height.
args:
width: 256
height: 256
fps: 25 # only for webm, webp and gif (2, 5, 10, 20 or 25 recommended)
# Settings for converting animated emoji.
# Same as animated_sticker, but webm is not supported as the target
# (because inline images can only contain images, not videos).
animated_emoji:
target: webp
args:
width: 64
height: 64
fps: 25
# End-to-bridge encryption support options.
#
# See https://docs.mau.fi/bridges/general/end-to-bridge-encryption.html for more info.
@@ -413,13 +413,15 @@ class TelegramMessageConverter:
thumb_loc = None
thumb_size = None
parallel_id = source.tgid if self.config["bridge.parallel_file_transfer"] else None
tgs_convert = self.config["bridge.animated_sticker"]
file = await util.transfer_file_to_matrix(
source.client,
intent,
document,
thumb_loc,
is_sticker=attrs.is_sticker,
tgs_convert=self.config["bridge.animated_sticker"],
tgs_convert=tgs_convert,
webm_convert=tgs_convert["target"] if tgs_convert["convert_from_webm"] else None,
filename=attrs.name,
parallel_id=parallel_id,
encrypt=self.portal.encrypted,
+13 -4
View File
@@ -52,6 +52,7 @@ from ..tgclient import MautrixTelegramClient
from ..util import sane_mimetypes
from .parallel_file_transfer import parallel_transfer_to_matrix
from .tgs_converter import convert_tgs_to
from .webm_converter import convert_webm_to
try:
from PIL import Image
@@ -228,10 +229,8 @@ 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"}
tgs_args = source.config["bridge.animated_emoji"]
webm_convert = tgs_args["target"]
transfer_sema = asyncio.Semaphore(5)
@@ -243,6 +242,7 @@ async def transfer_custom_emojis_to_matrix(
document,
is_sticker=True,
tgs_convert=tgs_args,
webm_convert=webm_convert,
filename=f"emoji-{document.id}",
# Emojis are used as inline images and can't be encrypted
encrypt=False,
@@ -261,6 +261,7 @@ async def transfer_file_to_matrix(
*,
is_sticker: bool = False,
tgs_convert: dict | None = None,
webm_convert: str | None = None,
filename: str | None = None,
encrypt: bool = False,
parallel_id: int | None = None,
@@ -290,6 +291,7 @@ async def transfer_file_to_matrix(
thumbnail,
is_sticker,
tgs_convert,
webm_convert,
filename,
encrypt,
parallel_id,
@@ -305,6 +307,7 @@ async def _unlocked_transfer_file_to_matrix(
thumbnail: TypeThumbnail,
is_sticker: bool,
tgs_convert: dict | None,
webm_convert: str | None,
filename: str | None,
encrypt: bool,
parallel_id: int | None,
@@ -348,6 +351,12 @@ async def _unlocked_transfer_file_to_matrix(
width, height = converted_anim.width, converted_anim.height
image_converted = mime_type != "application/gzip"
thumbnail = None
elif is_sticker and webm_convert and webm_convert != "webm" and mime_type == "video/webm":
converted_anim = await convert_webm_to(file, webm_convert)
mime_type = converted_anim.mime
file = converted_anim.data
image_converted = mime_type != "video/webm"
thumbnail = None
decryption_info = None
upload_mime_type = mime_type
+1 -1
View File
@@ -99,7 +99,7 @@ if lottieconverter:
converters["png"] = tgs_to_png
converters["gif"] = tgs_to_gif
if lottieconverter and ffmpeg:
if lottieconverter and ffmpeg.ffmpeg_path:
async def tgs_to_webm(
file: bytes, width: int, height: int, fps: int = 30, **_: Any
+52
View File
@@ -0,0 +1,52 @@
# mautrix-telegram - A Matrix-Telegram puppeting bridge
# Copyright (C) 2022 Tulir Asokan
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from __future__ import annotations
import logging
from mautrix.util import ffmpeg
from .tgs_converter import ConvertedSticker
log: logging.Logger = logging.getLogger("mau.util.webm")
converter_args = {
"gif": {
"output_args": ("-vf", "split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse"),
},
"png": {
"input_args": ("-ss", "0"),
"output_args": ("-frames:v", "1"),
},
"webp": {},
}
async def convert_webm_to(file: bytes, convert_to: str) -> ConvertedSticker:
if convert_to in ("png", "gif", "webp"):
try:
converted_data = await ffmpeg.convert_bytes(
data=file,
output_extension=f".{convert_to}",
**converter_args[convert_to],
)
return ConvertedSticker(f"image/{convert_to}", converted_data)
except ffmpeg.ConverterError as e:
log.error(str(e))
elif convert_to != "disable":
log.warning(f"Unable to convert webm animated sticker, type {convert_to} not supported")
return ConvertedSticker("video/webm", file)