Files
mautrix-telegram/pkg/connector/media/sticker.go
T
Tulir Asokan 48d91fdf76 media/sticker: fix lottie mime type
It's always gunzipped, so should never send the application/x-tgsticker mime.
Also, video/lottie+json was recently registered with IANA, so use that instead
of the old image/lottie+json: <https://www.iana.org/assignments/media-types/video/lottie+json>
2025-04-24 15:56:44 +03:00

119 lines
3.6 KiB
Go

// mautrix-telegram - A Matrix-Telegram puppeting bridge.
// Copyright (C) 2025 Sumner Evans
//
// 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/>.
package media
import (
"bytes"
"context"
"fmt"
"io"
"os"
"path/filepath"
"strconv"
"github.com/rs/zerolog"
"go.mau.fi/util/ffmpeg"
"go.mau.fi/util/lottie"
"go.mau.fi/util/random"
)
type AnimatedStickerConfig struct {
Target string `yaml:"target"`
ConvertFromWebm bool `yaml:"convert_from_webm"`
Args struct {
Width int `yaml:"width"`
Height int `yaml:"height"`
FPS int `yaml:"fps"`
} `yaml:"args"`
}
type ConvertedSticker struct {
DataWriter io.Reader
MIMEType string
ThumbnailData []byte
ThumbnailMIMEType string
Width int
Height int
Size int
}
func (c AnimatedStickerConfig) convert(ctx context.Context, data []byte) ConvertedSticker {
input := bytes.NewBuffer(data)
if c.Target == "disable" {
return ConvertedSticker{DataWriter: input, MIMEType: "video/lottie+json"}
}
log := zerolog.Ctx(ctx).With().Str("animated_sticker_target", c.Target).Logger()
if !lottie.Supported() {
log.Warn().Msg("lottie not supported, cannot convert animated stickers")
return ConvertedSticker{DataWriter: input, MIMEType: "video/lottie+json"}
} else if (c.Target == "webp" || c.Target == "webm") && !ffmpeg.Supported() {
log.Warn().Msg("ffmpeg not supported, cannot convert animated stickers")
return ConvertedSticker{DataWriter: input, MIMEType: "video/lottie+json"}
}
dataWriter := new(bytes.Buffer)
var thumbnailData []byte
var mimeType, thumbnailMIMEType string
var err error
switch c.Target {
case "png":
mimeType = "image/png"
err = lottie.Convert(ctx, input, "", dataWriter, c.Target, c.Args.Width, c.Args.Height, "1")
case "gif":
mimeType = "image/gif"
err = lottie.Convert(ctx, input, "", dataWriter, c.Target, c.Args.Width, c.Args.Height, strconv.Itoa(c.Args.FPS))
case "webm", "webp":
tmpFile := filepath.Join(os.TempDir(), fmt.Sprintf("mautrix-telegram-lottieconverter-%s.%s", random.String(10), c.Target))
defer func() {
_ = os.Remove(tmpFile)
}()
thumbnailMIMEType = "image/png"
mimeType = "image/" + c.Target
thumbnailData, err = lottie.FFmpegConvert(ctx, input, tmpFile, c.Args.Width, c.Args.Height, c.Args.FPS)
if err != nil {
break
}
var convertedData []byte
convertedData, err = os.ReadFile(tmpFile)
dataWriter = bytes.NewBuffer(convertedData)
default:
err = fmt.Errorf("unsupported target format %s", c.Target)
}
if err != nil {
log.Err(err).
Str("target", c.Target).
Msg("failed to convert animated sticker to target format")
// Fallback to original data
return ConvertedSticker{DataWriter: input, MIMEType: "video/lottie+json"}
}
return ConvertedSticker{
DataWriter: dataWriter,
MIMEType: mimeType,
ThumbnailData: thumbnailData,
ThumbnailMIMEType: thumbnailMIMEType,
Width: c.Args.Width,
Height: c.Args.Height,
Size: dataWriter.Len(),
}
}