38 lines
1.9 KiB
JavaScript
38 lines
1.9 KiB
JavaScript
// Holt ein Standbild aus dem Hero-Video von Luximmo: Es steht als Hintergrundbild der Sektion,
|
||
// bis das Video läuft (und für immer bei „Bewegung reduzieren“ oder Datensparen). ffmpeg gibt es
|
||
// hier nicht, Chromium spielt WebM ab und zeichnet das Bild in ein Canvas.
|
||
//
|
||
// Aufruf: node scripts/build-luximmo-poster.mjs <hero.webm> <Ziel.png> [Sekunde]
|
||
import { readFileSync, writeFileSync } from 'node:fs';
|
||
import { chromium } from 'playwright';
|
||
|
||
const [quelle, ziel, sekunde = '0.4'] = process.argv.slice(2);
|
||
if (!quelle || !ziel) {
|
||
console.error('Aufruf: node scripts/build-luximmo-poster.mjs <hero.webm> <Ziel.png> [Sekunde]');
|
||
process.exit(1);
|
||
}
|
||
|
||
const browser = await chromium.launch();
|
||
try {
|
||
const page = await browser.newPage();
|
||
await page.setContent('<video muted playsinline></video>');
|
||
const daten = readFileSync(quelle).toString('base64');
|
||
const png = await page.evaluate(async ([b64, t]) => {
|
||
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
||
const video = document.querySelector('video');
|
||
video.src = URL.createObjectURL(new Blob([bytes], { type: 'video/webm' }));
|
||
await new Promise((ok, fehler) => { video.onloadeddata = ok; video.onerror = () => fehler(new Error('Video lässt sich nicht lesen')); });
|
||
video.currentTime = Math.min(Number(t), Math.max(0, video.duration - 0.1));
|
||
await new Promise((ok) => { video.onseeked = ok; });
|
||
const canvas = document.createElement('canvas');
|
||
canvas.width = video.videoWidth;
|
||
canvas.height = video.videoHeight;
|
||
canvas.getContext('2d').drawImage(video, 0, 0);
|
||
return { url: canvas.toDataURL('image/png'), breite: video.videoWidth, hoehe: video.videoHeight, dauer: video.duration };
|
||
}, [daten, sekunde]);
|
||
writeFileSync(ziel, Buffer.from(png.url.split(',')[1], 'base64'));
|
||
console.log(`Standbild ${png.breite} × ${png.hoehe} (Video ${png.dauer.toFixed(1)} s) → ${ziel}`);
|
||
} finally {
|
||
await browser.close();
|
||
}
|