MCPcopy Create free account
hub / github.com/TeleBoxOrg/TeleBox_Plugins / extractTgsFirstFrame

Function extractTgsFirstFrame

xmsl/xmsl.ts:101–140  ·  view source on GitHub ↗

* 从 TGS (Lottie) 动画渲染第一帧 PNG * 需要 rlottie-python 和 ffmpeg

(tgsBuffer: Buffer)

Source from the content-addressed store, hash-verified

99/**
100 * 从 TGS (Lottie) 动画渲染第一帧 PNG
101 * 需要 rlottie-python 和 ffmpeg
102 */
103async function extractTgsFirstFrame(tgsBuffer: Buffer): Promise<Buffer | null> {
104 const uniqueId = Date.now().toString() + '_' + Math.random().toString(36).slice(2);
105 const tgsPath = path.join(XMSL_TEMP_DIR, `sticker_${uniqueId}.tgs`);
106 const gifPath = path.join(XMSL_TEMP_DIR, `sticker_${uniqueId}.gif`);
107 const pngPath = path.join(XMSL_TEMP_DIR, `sticker_${uniqueId}.png`);
108
109 try {
110 fs.writeFileSync(tgsPath, tgsBuffer);
111
112 // 使用 rlottie-python 渲染 TGS 到 GIF
113 const pythonScript = `
114import sys
115from rlottie_python import LottieAnimation
116anim = LottieAnimation.from_tgs(sys.argv[1])
117anim.save_animation(sys.argv[2])
118`;
119 await execFileAsync('python3', ['-c', pythonScript, tgsPath, gifPath]);
120
121 // 从 GIF 提取第一帧
122 await execFileAsync('ffmpeg', [
123 '-i', gifPath,
124 '-vf', 'select=eq(n\\,0)',
125 '-vframes', '1',
126 '-y',
127 pngPath
128 ]);
129
130 if (fs.existsSync(pngPath)) {
131 return fs.readFileSync(pngPath);
132 }
133 return null;
134 } catch (error) {
135 console.error('[xmsl] TGS 第一帧提取失败:', error);
136 return null;
137 } finally {
138 try { fs.unlinkSync(tgsPath); } catch {}
139 try { fs.unlinkSync(gifPath); } catch {}
140 try { fs.unlinkSync(pngPath); } catch {}
141 }
142}
143

Callers 1

extractMediaInfoMethod · 0.85

Calls 2

execFileAsyncFunction · 0.85
errorMethod · 0.80

Tested by

no test coverage detected