From 959512ae103bf5b09c0974f27b0c6bce4a9bc2c8 Mon Sep 17 00:00:00 2001 From: Sumner Evans Date: Mon, 8 Jul 2024 16:54:29 -0600 Subject: [PATCH] lottie: add convert functions Signed-off-by: Sumner Evans --- ffmpeg/convert.go | 2 +- lottie/convert.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 lottie/convert.go diff --git a/ffmpeg/convert.go b/ffmpeg/convert.go index 4152f79..abf4733 100644 --- a/ffmpeg/convert.go +++ b/ffmpeg/convert.go @@ -68,7 +68,7 @@ func ConvertPath(ctx context.Context, inputFile string, outputExtension string, cmd.Stderr = logWriter err := cmd.Run() if err != nil { - return "", fmt.Errorf("ffmpeg error: %+v", err) + return "", fmt.Errorf("ffmpeg error: %w", err) } if removeInput { diff --git a/lottie/convert.go b/lottie/convert.go new file mode 100644 index 0000000..e14ee30 --- /dev/null +++ b/lottie/convert.go @@ -0,0 +1,104 @@ +// Copyright (c) 2024 Sumner Evans +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package lottie + +import ( + "bytes" + "context" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/rs/zerolog" + "go.mau.fi/util/exzerolog" +) + +var lottieconverterPath string + +func init() { + lottieconverterPath, _ = exec.LookPath("lottieconverter") +} + +// Supported returns whether lottieconverter is available on the system. +// +// lottieconverter is considered to be available if a binary called +// lottieconverter is found in $PATH, or if [SetPath] has been called +// explicitly with a non-empty path. +func Supported() bool { + return lottieconverterPath != "" +} + +// SetPath overrides the path to the lottieconverter binary. +func SetPath(path string) { + lottieconverterPath = path +} + +// ConvertPath converts a lottie file on disk using lottieconverter. The +// filename will be the same as the input file, but with the extension changed +// to the format specified. +// +// Args: +// - inputFile: the full path to the file. +// - format: the format to convert to. Either "gif" or "png". +// - width: the width of the output file. +// - height: the height of the output file. +// - extraArgs: additional arguments to pass to lottieconverter. +// +// Returns: the path to the converted file. +func ConvertPath(ctx context.Context, inputFile, format string, width, height int, removeInput bool, extraArgs ...string) (outputFile string, err error) { + outputFile = strings.TrimSuffix(strings.TrimSuffix(inputFile, filepath.Ext(inputFile)), "*") + "." + format + args := []string{inputFile, outputFile, format, fmt.Sprintf("%dx%d", width, height)} + args = append(args, extraArgs...) + + cmd := exec.CommandContext(ctx, lottieconverterPath, args...) + ctxLog := zerolog.Ctx(ctx).With().Str("command", "lottieconverter").Logger() + logWriter := exzerolog.NewLogWriter(ctxLog).WithLevel(zerolog.WarnLevel) + cmd.Stdout = logWriter + cmd.Stderr = logWriter + + if err = cmd.Run(); err != nil { + return "", fmt.Errorf("lottieconverter error: %w", err) + } + + if removeInput { + _ = os.Remove(inputFile) + } + + return outputFile, nil +} + +// ConvertBytes converts lottie data to an [image.Image] using lottieconverter. +// +// Args: +// - data: the lottie data. +// - format: the format to convert to. Either "gif" or "png". +// - width: the width of the output file. +// - height: the height of the output file. +// - extraArgs: additional arguments to pass to lottieconverter. +// +// Returns: the path to the converted file. +func ConvertBytes(ctx context.Context, data []byte, format string, width, height int, extraArgs ...string) (img []byte, err error) { + args := []string{"-", "-", format, fmt.Sprintf("%dx%d", width, height)} + args = append(args, extraArgs...) + + var output bytes.Buffer + + cmd := exec.CommandContext(ctx, lottieconverterPath, args...) + ctxLog := zerolog.Ctx(ctx).With().Str("command", "lottieconverter").Logger() + logWriter := exzerolog.NewLogWriter(ctxLog).WithLevel(zerolog.WarnLevel) + cmd.Stdin = bytes.NewReader(data) + cmd.Stdout = &output + cmd.Stderr = logWriter + + if err = cmd.Run(); err != nil { + return nil, fmt.Errorf("lottieconverter error: %w", err) + } + + return output.Bytes(), nil +}