Files

146 lines
3.3 KiB
Go

package convert
import (
"compress/gzip"
"fmt"
"image/png"
"io"
"os"
"os/exec"
"path/filepath"
"trbot/plugins/sticker_download/config"
"golang.org/x/image/webp"
)
// use golang.org/x/image/webp and image/png
func WebPToPNG(webpPath, pngPath string) error {
// 打开 WebP 文件
webpFile, err := os.Open(webpPath)
if err != nil {
return fmt.Errorf("打开 WebP 文件失败: %w", err)
}
defer webpFile.Close()
// 解码 WebP 图片
img, err := webp.Decode(webpFile)
if err != nil {
return fmt.Errorf("解码 WebP 失败: %w", err)
}
// 创建 PNG 文件
pngFile, err := os.Create(pngPath)
if err != nil {
return fmt.Errorf("创建 PNG 文件失败: %w", err)
}
defer pngFile.Close()
// 编码 PNG
err = png.Encode(pngFile, img)
if err != nil {
return fmt.Errorf("编码 PNG 失败: %w", err)
}
return nil
}
// use ffmpeg
func WebMToGif(webmPath, gifPath string) error {
return exec.Command(config.Config.FFmpegPath, "-i", webmPath, gifPath).Run()
}
// use lottie-converter, gifski and compress/gzip
func TGSToGif(fileID, tgsPath, gifPath string) error {
var tempDir = filepath.Join(config.TempDir, fileID)
var fps string = "30"
if config.Config.TGSConvertFPS != 0 {
fps = fmt.Sprintf("%d", config.Config.TGSConvertFPS)
}
// 创建临时目录
err := os.MkdirAll(tempDir, 0755)
if err != nil {
return fmt.Errorf("failed to create temp dir: %w", err)
}
defer os.RemoveAll(tempDir)
// 若为 .tgs 文件,解压为 .json
lottiePath := filepath.Join(tempDir, "animation.json")
inFile, err := os.Open(tgsPath)
if err != nil {
return fmt.Errorf("failed to open tgs file: %w", err)
}
defer inFile.Close()
gzReader, err := gzip.NewReader(inFile)
if err != nil {
return fmt.Errorf("failed to create gzip reader: %w", err)
}
defer gzReader.Close()
outFile, err := os.Create(lottiePath)
if err != nil {
return fmt.Errorf("failed to create json file: %w", err)
}
defer outFile.Close()
if _, err := io.Copy(outFile, gzReader); err != nil {
return fmt.Errorf("failed to decompress tgs: %w", err)
}
// 执行 lottie_to_png
err = exec.Command(config.Config.LottieToPNGPath,
"--width", "512",
"--height", "512",
"--fps", fps,
"--threads", "1",
"--output", tempDir,
lottiePath,
).Run()
if err != nil {
return fmt.Errorf("lottie_to_png failed: %w", err)
}
// 查找 PNG 文件
files, err := filepath.Glob(filepath.Join(tempDir, "*.png"))
if err != nil || len(files) == 0 {
return fmt.Errorf("no PNG files found: %w", err)
}
// 排序文件(按名称)
// 可以用 sort.Strings(files) 如果你需要强制排序
// 调用 gifski 生成 GIF
args := append([]string{
"--quiet",
"-o", gifPath,
"--fps", fps,
"--height", "512",
"--width", "512",
"--quality", "90",
}, files...)
err = exec.Command(config.Config.GifskiPath, args...).Run()
if err != nil {
return fmt.Errorf("gifski failed: %w", err)
}
return nil
}
// use ffmpeg
func MP4ToGif(mp4Path, gifPath string) error {
return exec.Command(config.Config.FFmpegPath, "-i", mp4Path, gifPath).Run()
}
// func MP4ToWebM(MP4Path, webmPath string) error {
// return exec.Command(config.Config.FFmpegPath,
// "-i", MP4Path,
// "-vf", "scale='if(gt(iw,ih),512,-2)':'if(gt(ih,iw),512,-2)',fps=30",
// "-c:v", "libvpx-vp9",
// "-crf", "40",
// "-b:v", "0",
// "-an",
// "-limit_filesize", "262144",
// webmPath,
// ).Run()
// }