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..8300a55 --- /dev/null +++ b/lottie/convert.go @@ -0,0 +1,90 @@ +// 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 ( + "context" + "fmt" + "io" + "os/exec" + + "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 +} + +// Convert converts lottie data an image or image(s) using lottieconverter. +// +// Args: +// - inputFilename: the filename the lottie file to convert. +// - inputReader: an io.Reader containing the lottie data to convert. +// - outputFilename: the filename to write the output to. +// - outputWriter: an io.Writer to write the output to. +// - format: the output format. Can be one of: png, gif, or pngs. +// - width: the width of the output image(s). +// - height: the height of the output image(s). +// - extraArgs: additional arguments to pass to lottieconverter. +// +// The inputFilename and inputReader parameters are mutually exclusive. +// The outputFilename and outputWriter parameters are mutually exclusive. +func Convert(ctx context.Context, inputFilename string, inputReader io.Reader, outputFilename string, outputWriter io.Writer, format string, width, height int, extraArgs ...string) error { + // Verify the input parameters and calculate the actual filenames that will + // be used when shelling out to lottieconverter. + // + // We are panicking here because it's a programming error to call this + // function with invalid parameters. + in := inputFilename + out := outputFilename + if inputFilename == "" && inputReader == nil { + panic("lottie.Convert: either inputFile or inputReader must be provided") + } else if outputFilename == "" && outputWriter == nil { + panic("lottie.Convert: either outputFile or outputWriter must be provided") + } else if inputReader != nil { + if inputFilename != "" { + panic("lottie.Convert: only one of inputFile or inputReader can be provided") + } + in = "-" + } else if outputWriter != nil { + if outputFilename != "" { + panic("lottie.Convert: only one of outputFile or outputWriter can be provided") + } + out = "-" + } + + args := []string{in, out, format, fmt.Sprintf("%dx%d", width, height)} + args = append(args, extraArgs...) + + cmd := exec.CommandContext(ctx, lottieconverterPath, args...) + cmd.Stdin = inputReader + cmd.Stdout = outputWriter + log := zerolog.Ctx(ctx).With().Str("command", "lottieconverter").Logger() + cmd.Stderr = exzerolog.NewLogWriter(log).WithLevel(zerolog.WarnLevel) + + if err := cmd.Run(); err != nil { + return fmt.Errorf("lottieconverter error: %w", err) + } + return nil +}