mirror of
https://github.com/vibegif/vibegif.lol.git
synced 2026-04-07 02:12:12 +00:00
Feat: semi-transparent mode with animated webp
This commit is contained in:
42
src/main.js
42
src/main.js
@@ -2,6 +2,8 @@ import { getApiKey, setApiKey, hasApiKey } from './core/storage.js';
|
|||||||
import { buildFirstMessage, buildNextMessage } from './core/messages.js';
|
import { buildFirstMessage, buildNextMessage } from './core/messages.js';
|
||||||
import { generateFrame } from './services/openrouter.js';
|
import { generateFrame } from './services/openrouter.js';
|
||||||
import { assembleGif } from './services/gif.js';
|
import { assembleGif } from './services/gif.js';
|
||||||
|
import { removeBackgroundFrames } from './services/background.js';
|
||||||
|
import { assembleAnimatedWebp } from './services/webp.js';
|
||||||
import {
|
import {
|
||||||
ELEMENT_IDS,
|
ELEMENT_IDS,
|
||||||
grabElements,
|
grabElements,
|
||||||
@@ -62,6 +64,9 @@ async function handleGenerate() {
|
|||||||
const maxSize = Math.max(32, Math.min(1024, Number.parseInt(el.inpMaxSize?.value || '256', 10) || 256));
|
const maxSize = Math.max(32, Math.min(1024, Number.parseInt(el.inpMaxSize?.value || '256', 10) || 256));
|
||||||
const imageSize = '1K';
|
const imageSize = '1K';
|
||||||
const aspectRatio = el.selRatio?.value || '1:1';
|
const aspectRatio = el.selRatio?.value || '1:1';
|
||||||
|
const semiTransparent = !!el.chkSemiTransparent?.checked;
|
||||||
|
|
||||||
|
const generationMaxPct = semiTransparent ? 55 : 100;
|
||||||
|
|
||||||
setGenerating(el, true);
|
setGenerating(el, true);
|
||||||
resetProgress(el);
|
resetProgress(el);
|
||||||
@@ -86,10 +91,10 @@ async function handleGenerate() {
|
|||||||
allFrames.push(first.base64);
|
allFrames.push(first.base64);
|
||||||
history.push(firstMsg, first.assistantMsg);
|
history.push(firstMsg, first.assistantMsg);
|
||||||
addFramePreview(el, first.base64, 0);
|
addFramePreview(el, first.base64, 0);
|
||||||
setProgress(el, Math.round(100 / frameCount), `frame 1 of ${frameCount} done`);
|
setProgress(el, Math.round((1 / frameCount) * generationMaxPct), `frame 1 of ${frameCount} done`);
|
||||||
|
|
||||||
for (let i = 2; i <= frameCount; i++) {
|
for (let i = 2; i <= frameCount; i++) {
|
||||||
setProgress(el, Math.round(((i - 1) / frameCount) * 100), `generating frame ${i} of ${frameCount}...`);
|
setProgress(el, Math.round(((i - 1) / frameCount) * generationMaxPct), `generating frame ${i} of ${frameCount}...`);
|
||||||
|
|
||||||
const nextUserMsg = buildNextMessage(i, frameCount);
|
const nextUserMsg = buildNextMessage(i, frameCount);
|
||||||
const startIdx = Math.max(1, history.length - WINDOW * 2);
|
const startIdx = Math.max(1, history.length - WINDOW * 2);
|
||||||
@@ -106,14 +111,35 @@ async function handleGenerate() {
|
|||||||
allFrames.push(next.base64);
|
allFrames.push(next.base64);
|
||||||
history.push(nextUserMsg, next.assistantMsg);
|
history.push(nextUserMsg, next.assistantMsg);
|
||||||
addFramePreview(el, next.base64, i - 1);
|
addFramePreview(el, next.base64, i - 1);
|
||||||
setProgress(el, Math.round((i / frameCount) * 100), `frame ${i} of ${frameCount} done`);
|
setProgress(el, Math.round((i / frameCount) * generationMaxPct), `frame ${i} of ${frameCount} done`);
|
||||||
}
|
}
|
||||||
|
|
||||||
setProgress(el, 100, 'assembling gif...');
|
if (!semiTransparent) {
|
||||||
const blob = await assembleGif(allFrames, fps, maxSize);
|
setProgress(el, 100, 'assembling gif...');
|
||||||
currentGifUrl = URL.createObjectURL(blob);
|
const blob = await assembleGif(allFrames, fps, maxSize);
|
||||||
showResult(el, currentGifUrl);
|
currentGifUrl = URL.createObjectURL(blob);
|
||||||
setProgress(el, 100, 'done! 🎉');
|
showResult(el, currentGifUrl, 'vibegif.gif');
|
||||||
|
setProgress(el, 100, 'done! 🎉');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setProgress(el, 56, 'starting background removal...');
|
||||||
|
const transparentFrames = await removeBackgroundFrames(allFrames, {
|
||||||
|
onProgress: ({ pct, text }) => {
|
||||||
|
const mapped = Math.round(55 + (Math.max(0, Math.min(100, pct)) * 0.30));
|
||||||
|
setProgress(el, mapped, text || 'removing backgrounds...');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setProgress(el, 86, 'assembling animated webp...');
|
||||||
|
const webpBlob = await assembleAnimatedWebp(transparentFrames, fps, maxSize, (pct, text) => {
|
||||||
|
const mapped = Math.round(85 + (Math.max(0, Math.min(100, pct)) * 0.15));
|
||||||
|
setProgress(el, mapped, text || 'assembling animated webp...');
|
||||||
|
});
|
||||||
|
|
||||||
|
currentGifUrl = URL.createObjectURL(webpBlob);
|
||||||
|
showResult(el, currentGifUrl, 'vibegif.webp');
|
||||||
|
setProgress(el, 100, 'done! transparent animated webp ready ✨');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const msg = err?.message || String(err);
|
const msg = err?.message || String(err);
|
||||||
setProgress(el, 0, `error: ${msg}`);
|
setProgress(el, 0, `error: ${msg}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user