diff --git a/packages/backend/scripts/check-gifs.ts b/packages/backend/scripts/check-gifs.ts new file mode 100644 index 0000000..2a980d9 --- /dev/null +++ b/packages/backend/scripts/check-gifs.ts @@ -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(); + diff --git a/packages/backend/scripts/insert-gif-test.ts b/packages/backend/scripts/insert-gif-test.ts new file mode 100644 index 0000000..4bb2f85 --- /dev/null +++ b/packages/backend/scripts/insert-gif-test.ts @@ -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(); + diff --git a/packages/backend/scripts/regenerate-all-gifs.ts b/packages/backend/scripts/regenerate-all-gifs.ts new file mode 100644 index 0000000..a6029ff --- /dev/null +++ b/packages/backend/scripts/regenerate-all-gifs.ts @@ -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(); +