Add GIF regeneration and diagnostic scripts
Added utility scripts for GIF management: 1. regenerate-all-gifs.ts: - Regenerates GIF previews for all existing videos - Deletes old GIFs before creating new ones - Provides progress feedback and summary statistics - Useful for bulk GIF generation after deployment 2. check-gifs.ts: - Quick diagnostic to list all GIF records in database - Shows term names and GIF URLs - Useful for verifying GIF generation 3. insert-gif-test.ts: - Test script to verify GIF enum value works in database - Creates, verifies, and cleans up test GIF record - Includes Prisma query logging for debugging Usage: cd packages/backend npx tsx scripts/regenerate-all-gifs.ts npx tsx scripts/check-gifs.ts npx tsx scripts/insert-gif-test.ts Co-Authored-By: Auggie
This commit is contained in:
20
packages/backend/scripts/check-gifs.ts
Normal file
20
packages/backend/scripts/check-gifs.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
|
async function checkGifs() {
|
||||||
|
const gifs = await prisma.termMedia.findMany({
|
||||||
|
where: { kind: 'GIF' },
|
||||||
|
include: { term: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Found ${gifs.length} GIF records in database:`);
|
||||||
|
gifs.forEach(gif => {
|
||||||
|
console.log(`- ${gif.term.wordText}: ${gif.url}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
await prisma.$disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
checkGifs();
|
||||||
|
|
||||||
53
packages/backend/scripts/insert-gif-test.ts
Normal file
53
packages/backend/scripts/insert-gif-test.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { PrismaClient, MediaKind } from '@prisma/client';
|
||||||
|
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
log: ['query', 'info', 'warn', 'error'],
|
||||||
|
});
|
||||||
|
|
||||||
|
async function testInsert() {
|
||||||
|
console.log('Testing GIF insert...\n');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get first video
|
||||||
|
const video = await prisma.termMedia.findFirst({
|
||||||
|
where: { kind: MediaKind.VIDEO },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!video) {
|
||||||
|
console.log('No video found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Found video: ${video.url}`);
|
||||||
|
console.log(`Term ID: ${video.termId}\n`);
|
||||||
|
|
||||||
|
// Try to insert GIF
|
||||||
|
const gif = await prisma.termMedia.create({
|
||||||
|
data: {
|
||||||
|
termId: video.termId,
|
||||||
|
kind: MediaKind.GIF,
|
||||||
|
url: '/uploads/gifs/test.gif',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('✅ GIF created:', gif);
|
||||||
|
|
||||||
|
// Verify it exists
|
||||||
|
const check = await prisma.termMedia.findUnique({
|
||||||
|
where: { id: gif.id },
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('\n✅ Verification:', check);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
await prisma.termMedia.delete({ where: { id: gif.id } });
|
||||||
|
console.log('\n✅ Cleaned up test record');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error:', error);
|
||||||
|
} finally {
|
||||||
|
await prisma.$disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testInsert();
|
||||||
|
|
||||||
104
packages/backend/scripts/regenerate-all-gifs.ts
Normal file
104
packages/backend/scripts/regenerate-all-gifs.ts
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import { PrismaClient, MediaKind } from '@prisma/client';
|
||||||
|
import { generateGifFromVideo } from '../src/utils/gifGenerator.js';
|
||||||
|
import path from 'path';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
Reference in New Issue
Block a user