video sticker preview img
This commit is contained in:
@@ -6,6 +6,7 @@ import path from "path";
|
|||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
import { execFile as _execFile } from "child_process";
|
import { execFile as _execFile } from "child_process";
|
||||||
import { promisify } from "util";
|
import { promisify } from "util";
|
||||||
|
import crypto from "crypto";
|
||||||
|
|
||||||
const execFile = promisify(_execFile);
|
const execFile = promisify(_execFile);
|
||||||
|
|
||||||
@@ -281,19 +282,53 @@ export default (router, tpl) => {
|
|||||||
return res.reply({ code: 400, body: JSON.stringify({ success: false, message: 'thumb_url must be a local /s/emojis/ path' }) });
|
return res.reply({ code: 400, body: JSON.stringify({ success: false, message: 'thumb_url must be a local /s/emojis/ path' }) });
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
let finalThumbUrl = thumbUrl;
|
||||||
|
|
||||||
|
// For .webm stickers: extract first frame -> save as WebP so tabs always show a static image
|
||||||
|
if (thumbUrl.endsWith('.webm')) {
|
||||||
try {
|
try {
|
||||||
await db`UPDATE sticker_packs SET thumb_url = ${thumbUrl} WHERE id = ${id}`;
|
const webmPath = path.join(cfg.paths.emojis, path.basename(thumbUrl));
|
||||||
|
const randSuffix = crypto.randomBytes(24).toString('hex');
|
||||||
|
const tmpPng = path.join(cfg.paths.emojis, randSuffix + '_tmp.png');
|
||||||
|
const webpPath = path.join(cfg.paths.emojis, randSuffix + '_thumb.webp');
|
||||||
|
|
||||||
|
// Step 1: ffmpeg extracts first frame to a temp PNG file
|
||||||
|
await execFile('ffmpeg', [
|
||||||
|
'-y', '-i', webmPath,
|
||||||
|
'-vframes', '1',
|
||||||
|
tmpPng
|
||||||
|
], { maxBuffer: 20 * 1024 * 1024 });
|
||||||
|
|
||||||
|
// Step 2: ImageMagick converts PNG -> WebP
|
||||||
|
try {
|
||||||
|
await execFile('magick', [tmpPng, '-quality', '85', webpPath], { env: magickEnv });
|
||||||
|
} finally {
|
||||||
|
await fs.unlink(tmpPng).catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
const stat = await fs.stat(webpPath).catch(() => null);
|
||||||
|
if (stat && stat.size > 0) {
|
||||||
|
finalThumbUrl = '/s/emojis/' + randSuffix + '_thumb.webp';
|
||||||
|
console.log('[SET THUMB] Generated WebP thumbnail from .webm: ' + finalThumbUrl);
|
||||||
|
}
|
||||||
|
} catch (thumbErr) {
|
||||||
|
console.warn('[SET THUMB] Could not generate WebP from .webm:', thumbErr.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await db`UPDATE sticker_packs SET thumb_url = ${finalThumbUrl} WHERE id = ${id}`;
|
||||||
} catch (colErr) {
|
} catch (colErr) {
|
||||||
// Column might not exist yet — add it and retry once
|
// Column might not exist yet — add it and retry once
|
||||||
if (colErr.message && colErr.message.includes('thumb_url')) {
|
if (colErr.message && colErr.message.includes('thumb_url')) {
|
||||||
await db`ALTER TABLE public.sticker_packs ADD COLUMN IF NOT EXISTS thumb_url text`;
|
await db`ALTER TABLE public.sticker_packs ADD COLUMN IF NOT EXISTS thumb_url text`;
|
||||||
await db`UPDATE sticker_packs SET thumb_url = ${thumbUrl} WHERE id = ${id}`;
|
await db`UPDATE sticker_packs SET thumb_url = ${finalThumbUrl} WHERE id = ${id}`;
|
||||||
} else {
|
} else {
|
||||||
throw colErr;
|
throw colErr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await db`NOTIFY emojis_updated, '{}'`;
|
await db`NOTIFY emojis_updated, '{}'`;
|
||||||
return res.reply({ headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ success: true }) });
|
return res.reply({ headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ success: true, thumb_url: finalThumbUrl }) });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
return res.reply({ code: 500, body: JSON.stringify({ success: false, message: "Database error" }) });
|
return res.reply({ code: 500, body: JSON.stringify({ success: false, message: "Database error" }) });
|
||||||
|
|||||||
@@ -420,9 +420,9 @@
|
|||||||
.then(function(r) { return r.json(); })
|
.then(function(r) { return r.json(); })
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
// Update local pack data so re-render shows correct current icon
|
// Use the URL the server actually stored (may be a generated WebP for .webm stickers)
|
||||||
var pack = (window.emojiAdmin.packs || []).find(function(p) { return p.id === packId; });
|
var pack = (window.emojiAdmin.packs || []).find(function(p) { return p.id === packId; });
|
||||||
if (pack) pack.thumb_url = thumbUrl;
|
if (pack) pack.thumb_url = data.thumb_url || thumbUrl;
|
||||||
// Re-render only this pack's grid — grid stays open
|
// Re-render only this pack's grid — grid stays open
|
||||||
renderPackGrid(packId);
|
renderPackGrid(packId);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user