42wim / matterbridge

bridge between mattermost, IRC, gitter, xmpp, slack, discord, telegram, rocketchat, twitch, ssh-chat, zulip, whatsapp, keybase, matrix, microsoft teams, nextcloud, mumble, vk and more with REST API (mattermost not required!)
Apache License 2.0
6.46k stars 608 forks source link

Allow converted animated telegram stickers to be smaller #1459

Open Funatiker opened 3 years ago

Funatiker commented 3 years ago

Is your feature request related to a problem? Please describe. If lottie_convert.py is present and set to be used, it is basically used at fully quality. This means that the tens of kilobytes sized gzipped lottie/JSON files turn to several megabytes sized webp files. This wastes quite a bit of mobile traffic, and storage space. Depending on the hardware, it also takes several seconds to render. This leads to stickers arriving in a different context in the conversation.

Describe the solution you'd like Currently lottie_convert.py is called with no parameters regarding quality: https://github.com/42wim/matterbridge/blob/0450482e6ebed8a379f2d43f0ee264ea0d130a31/bridge/helper/helper.go#L283 One could lower the size of the WebP files by skipping a few frames and lowering the quality.

# current setting: 4.2 MB WebP vs 20 kB tgs
$ lottie_convert.py --input-format lottie --output-format webp file_106_tgs.tgs file_106_tgs_orig.webp
# rendering a fourth of all frames, at 25% quality: 736 kB
$ lottie_convert.py --webp-skip-frames 4 --webp-quality 25 --input-format lottie --output-format webp file_106_tgs.tgs file_106_tgs_low.webp
# rendering a fifth of all frames, at 15% quality: 532 kB
$ lottie_convert.py --webp-skip-frames 5 --webp-quality 15 --input-format lottie --output-format webp file_106_tgs.tgs file_106_tgs_lower.webp
# rendering a sixth of all frames, at 10% quality: 424 kB
$ lottie_convert.py --webp-skip-frames 6 --webp-quality 10 --input-format lottie --output-format webp file_106_tgs.tgs file_106_tgs_lowest.webp

One could either change the current call of lottie_convert.py to one with a lower quality setting, or add a setting that allows picking changing the quality setting.

Describe alternatives you've considered Obviously, the converting animated vector graphics to a sequence of pixelated graphics is a workaround for clients that don't support animated vector formats. Theoretically, one could consider conversion to a classic video format. lottie_convert.py should support that (see https://mattbas.gitlab.io/python-lottie/script_lottie_convert.html ) my version 0.6.7 from pip didn't. But of course the best alternative (but not scope of this project) would be patching lottie/tgs support into the clients. Thus, sticking to the current variant but with lower quality settings seems to be the most pragmatic approach.

Additional context The input and the outputs of the quoted calls of lottie_convert.py can be found in this ZIP-file.

42wim commented 3 years ago

@Funatiker thanks for the suggestion, is this something you could work at?

Benau commented 2 years ago

Hello, I'm experienced many renendering bugs using (all latest using arch linux) lottie_convert.py with my sticker pack: pig.zip (for example, bad renendering of pig/5.tgs): test

So I've tried to build my own converter using https://github.com/Samsung/rlottie and imagemagick: https://gist.github.com/Benau/39355417005ca06d5d00b94ecc695e1d

It can produce correct output with so much faster rendering, and we can save more size using imagmagick optimization code / reduce color / framerate: output

Now, I wonder if matterbridge maintainer interested in using another external deps to convert? It seems that lottie is written in c++14 but c public api is available, so something like cgo should work, and imagemagick has go binding (or we can just save it in webp)

And by the way it seems that MediaConvertTgs="gif" fails at the moment

Benau commented 2 years ago

https://github.com/Benau/matterbridge/commit/85fb17ba8dbb53f3869305d43fb0eaae5a62e751 @42wim are you interested using rlottie + imagickmagic? basically it works, but can be polished (and it can easily fix this issue by just adding some more option to "shape" the gif) and it produces correct rendering for my sticker packs (which in the past using lottie_convert.py doesn't)

Benau commented 2 years ago

basically compile imagemagick with:

./configure --prefix=/usr --sysconfdir=/etc --enable-hdri -without-modules \
--without-perl --with-gcc-arch=generic --disable-openmp \
--with-bzlib=no \
--with-autotrace=no \
--with-djvu=no \
--with-dps=no \
--with-fftw=no \
--with-flif=no \
--with-fpx=no \
--with-fontconfig=no \
--with-freetype=no \
--with-gslib=no \
--with-gvc=no \
--with-heic=no \
--with-jbig=no \
--with-jpeg=no \
--with-jxl=no \
--with-lcms=no \
--with-lqr=no \
--with-lzma=no \
--with-magick-plus-plus=no \
--with-openexr=no \
--with-openjp2=no \
--with-pango=no \
--with-perl=no \
--with-png=yes \
--with-raqm=no \
--with-raw=no \
--with-rsvg=no \
--with-tiff=no \
--with-webp=yes \
--with-wmf=no \
--with-x=no \
--with-xml=no \
--with-zlib=yes \
--with-zstd=no

and then CGO_LDFLAGS="-static `pkg-config --libs MagickWand MagickCore` \ -lz -lpng -lwebpdemux -lwebpmux -lwebp -lm" go build -tags osusergo,netgo produces a statically linked binary in linux, not sure about the remaining oses...

Benau commented 2 years ago

i created few https://github.com/Benau/matterbridge/blob/master/imagewriter so we can generate png, gif, webp without imagemagick, so the only dependency is rlottie, and I think I can make a go package wrapping it (like the webpanimation), then we can build all platforms with go build

and by the way in the matrix channel the guy who contributed the original tgs converter loves this approach better because it reduces his pi usage

42wim commented 2 years ago

@benau thanks for your work and looking for a way to optimize.

I don't want to add CGO (by default) because that complicates things on other platforms (eg windows)

But if you make a PR that allows matterbridge to build with an optional build tag (so that people who want it can enable it on their own builds), I'm happy to merge this.

Benau commented 2 years ago

@42wim do you prefer to keep the old code or replace the current tgs conversion with cgo completely?

And I can help setting up cross-compiler github actions for popular platform by the way

42wim commented 2 years ago

@Benau like you did in your PR is perfect, keep the old code for the non-cgo builds. For github actions, if you could make a PR for cgo builds that doesn't complicate the current github actions too much, your help is welcome!