Files
znakovni.hr/packages/backend/scripts/regenerate-all-gifs.ts
johnny2211 78a51f88dc Fix regenerate-all-gifs script for production environment
Problem: Script failed in production Docker container because it tried
to import from '../src/utils/gifGenerator.js' which doesn't exist in
production (only compiled dist/ directory exists).

Error:
  Cannot find module '/app/packages/backend/src/utils/gifGenerator.js'

Solution: Use dynamic import with path detection to support both
development and production environments.

Changes:
- Check if dist/utils/gifGenerator.js exists (production)
- Fall back to src/utils/gifGenerator.js (development)
- Use dynamic import with await to load the correct module

This allows the script to work in both:
- Development: npx tsx scripts/regenerate-all-gifs.ts
- Production: Docker container with REGENERATE_GIFS=true

Tested: Docker container now starts successfully and executes the
GIF regeneration script without errors.

Co-Authored-By: Auggie
2026-01-18 18:57:37 +01:00

111 lines
3.2 KiB
TypeScript

import { PrismaClient, MediaKind } from '@prisma/client';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Dynamic import to support both dev (src/) and production (dist/)
const gifGeneratorPath = fs.existsSync(path.join(__dirname, '../dist/utils/gifGenerator.js'))
? '../dist/utils/gifGenerator.js'
: '../src/utils/gifGenerator.js';
const { generateGifFromVideo } = await import(gifGeneratorPath);
const prisma = new PrismaClient();
async function regenerateAllGifs() {
console.log('🎬 Starting GIF regeneration for all videos...\n');
try {
// Get all video media
const videoMedia = await prisma.termMedia.findMany({
where: { kind: MediaKind.VIDEO },
include: { term: true },
});
console.log(`Found ${videoMedia.length} videos to process\n`);
let successCount = 0;
let failCount = 0;
for (const media of videoMedia) {
const videoFilename = path.basename(media.url);
const videoPath = path.join(__dirname, '..', 'uploads', 'videos', videoFilename);
// Check if video file exists
if (!fs.existsSync(videoPath)) {
console.log(`❌ Video file not found: ${videoFilename}`);
failCount++;
continue;
}
try {
// Generate GIF filename
const gifFilename = videoFilename.replace(/\.(mp4|webm|mov)$/i, '.gif');
const gifsDir = path.join(__dirname, '..', 'uploads', 'gifs');
const gifPath = path.join(gifsDir, gifFilename);
const gifRelativeUrl = `/uploads/gifs/${gifFilename}`;
// Ensure gifs directory exists
if (!fs.existsSync(gifsDir)) {
fs.mkdirSync(gifsDir, { recursive: true });
}
// Delete old GIF if exists
const existingGif = await prisma.termMedia.findFirst({
where: {
termId: media.termId,
kind: MediaKind.GIF,
url: gifRelativeUrl,
},
});
if (existingGif) {
await prisma.termMedia.delete({ where: { id: existingGif.id } });
if (fs.existsSync(gifPath)) {
fs.unlinkSync(gifPath);
}
}
// Generate GIF
console.log(`🎨 Generating GIF for: ${media.term.wordText} (${videoFilename})`);
await generateGifFromVideo(videoPath, gifPath, {
fps: 10,
width: 300,
duration: 3,
startTime: 0,
});
// Create GIF media record
await prisma.termMedia.create({
data: {
termId: media.termId,
kind: MediaKind.GIF,
url: gifRelativeUrl,
},
});
console.log(`✅ Success: ${media.term.wordText}\n`);
successCount++;
} catch (error: any) {
console.log(`❌ Failed: ${media.term.wordText} - ${error.message}\n`);
failCount++;
}
}
console.log('\n📊 Summary:');
console.log(`✅ Success: ${successCount}`);
console.log(`❌ Failed: ${failCount}`);
console.log(`📝 Total: ${videoMedia.length}`);
} catch (error) {
console.error('Error:', error);
} finally {
await prisma.$disconnect();
}
}
regenerateAllGifs();