diff --git a/client/src/pages/video.tsx b/client/src/pages/video.tsx index b6dc500..6addfdd 100644 --- a/client/src/pages/video.tsx +++ b/client/src/pages/video.tsx @@ -93,10 +93,13 @@ export default function VideoPage() { const shareUrl = `${window.location.origin}/video/${video.id}`; + // Use server proxy endpoint for reliable thumbnail access in social sharing + const publicThumbnailUrl = `${window.location.origin}/thumbnail/${video.id}`; + // Open Graph tags for Facebook updateMeta('og:title', video.title); updateMeta('og:description', video.description || `Oglej si ta video na VideoStream`); - updateMeta('og:image', video.thumbnailUrl); + updateMeta('og:image', publicThumbnailUrl); updateMeta('og:image:width', '1200'); updateMeta('og:image:height', '630'); updateMeta('og:image:type', 'image/jpeg'); @@ -111,7 +114,7 @@ export default function VideoPage() { updateMeta('twitter:card', 'summary_large_image', false); updateMeta('twitter:title', video.title, false); updateMeta('twitter:description', video.description || `Oglej si ta video na VideoStream`, false); - updateMeta('twitter:image', video.thumbnailUrl, false); + updateMeta('twitter:image', publicThumbnailUrl, false); } }, [video]); diff --git a/server/bunny.ts b/server/bunny.ts index 3877b46..0a6ec37 100644 --- a/server/bunny.ts +++ b/server/bunny.ts @@ -73,6 +73,11 @@ export class BunnyService { return `https://${this.hostname}${path}?token=${token}&expires=${expireTimestamp}`; } + // Public method for generating signed URLs for sharing + generatePublicSignedUrl(path: string, expiryHours: number = 1): string { + return this.generateSignedUrl(path, expiryHours); + } + private bunnyVideoToVideo(bunnyVideo: BunnyVideo): Video { // Generate signed URLs for private video access const videoPath = `/${bunnyVideo.guid}/playlist.m3u8`; diff --git a/server/routes.ts b/server/routes.ts index d9e5699..bc73044 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -2,6 +2,7 @@ import type { Express } from "express"; import { createServer, type Server } from "http"; import { storage } from "./storage"; import { z } from "zod"; +import { BunnyService } from "./bunny"; export async function registerRoutes(app: Express): Promise { // Get videos with pagination and filtering @@ -117,26 +118,35 @@ export async function registerRoutes(app: Express): Promise { } }); - // Proxy endpoint for thumbnail images from Bunny.net + // Public thumbnail endpoint for social media sharing app.get("/thumbnail/:videoId", async (req, res) => { try { const { videoId } = req.params; - const hostname = process.env.BUNNY_HOSTNAME!; - const thumbnailUrl = `https://${hostname}/${videoId}/thumbnail.jpg`; - // Attempt to fetch and proxy the thumbnail - const response = await fetch(thumbnailUrl); + // Generate signed thumbnail URL using Bunny service + const bunnyService = new BunnyService(); + const thumbnailPath = `/${videoId}/thumbnail.jpg`; + const signedThumbnailUrl = bunnyService.generatePublicSignedUrl(thumbnailPath, 24); // 24 hour expiry for sharing + + // Fetch and proxy the thumbnail with proper headers for social media + const response = await fetch(signedThumbnailUrl); if (response.ok) { - res.set('Content-Type', response.headers.get('content-type') || 'image/jpeg'); + // Set appropriate headers for social media crawlers + res.set({ + 'Content-Type': 'image/jpeg', + 'Cache-Control': 'public, max-age=86400', // Cache for 24 hours + 'Access-Control-Allow-Origin': '*', // Allow cross-origin for social media + }); + const buffer = await response.arrayBuffer(); res.send(Buffer.from(buffer)); } else { - // Fallback to a music-themed placeholder - res.redirect(`https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&h=450`); + // Fallback to a high-quality video placeholder + res.redirect(`https://images.unsplash.com/photo-1536240478700-b869070f9279?ixlib=rb-4.0.3&auto=format&fit=crop&w=1200&h=630`); } } catch (error) { console.error("Error proxying thumbnail:", error); - res.redirect(`https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&h=450`); + res.redirect(`https://images.unsplash.com/photo-1536240478700-b869070f9279?ixlib=rb-4.0.3&auto=format&fit=crop&w=1200&h=630`); } });