From c43057ec774b5ec64217ad5e6ae3e85594b86cde Mon Sep 17 00:00:00 2001 From: sebastjanartic <45803536-sebastjanartic@users.noreply.replit.com> Date: Sun, 31 Aug 2025 21:06:44 +0000 Subject: [PATCH] Use actual video thumbnails for social media sharing Integrates node-fetch and sharp to download and overlay branding on actual video thumbnails from Bunny.net for social media sharing. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ab9cd02a-d0b2-4288-9ceb-1964d0059648 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/ab9cd02a-d0b2-4288-9ceb-1964d0059648/xVB32z7 --- server/routes.ts | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/server/routes.ts b/server/routes.ts index eabe22b..56d5e08 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -15,6 +15,7 @@ import path from "path"; import fs from "fs"; import session from "express-session"; import sharp from "sharp"; +import fetch from "node-fetch"; // Extend express session declare module "express-session" { @@ -766,7 +767,49 @@ export async function registerRoutes(app: Express): Promise { return res.status(404).send('Video not found'); } - // Ustvarimo social media thumbnail sliko z video informacijami + // Najprej poskušamo uporabiti dejanski video thumbnail iz Bunny.net + if (video.thumbnailUrl) { + try { + // Prenesemo dejanski thumbnail iz Bunny.net + const response = await fetch(video.thumbnailUrl); + if (response.ok) { + const thumbnailBuffer = await response.arrayBuffer(); + + // Povečamo thumbnail na social media velikost (1200x630) z dodano go4.video branding overlay + const overlayedBuffer = await sharp(Buffer.from(thumbnailBuffer)) + .resize(1200, 630, { fit: 'cover', position: 'center' }) + .composite([ + // Dodamo temno overlay za boljši kontrast teksta + { + input: Buffer.from( + ` + + + + go4.video + Professional Video Platform + + + ${Math.floor(video.duration / 60)}:${(video.duration % 60).toString().padStart(2, '0')} + ` + ), + top: 0, + left: 0, + } + ]) + .png({ quality: 90, compressionLevel: 6 }) + .toBuffer(); + + res.setHeader('Content-Type', 'image/png'); + res.setHeader('Cache-Control', 'public, max-age=3600'); // Cache za 1 uro + return res.send(overlayedBuffer); + } + } catch (fetchError) { + console.log('Failed to fetch real thumbnail, falling back to generated:', fetchError); + } + } + + // Fallback: ustvarimo generirani thumbnail z video informacijami const width = 1200; const height = 630; // Facebook/Twitter optimalne dimenzije