Problem: Docker container failed to start with REGENERATE_GIFS=true
because scripts directory was not copied to production image and tsx
was not available at runtime.
Error:
Cannot find module '/app/packages/backend/scripts/regenerate-all-gifs.ts'
Root cause:
1. Dockerfile only copied dist/ and prisma/ directories, not scripts/
2. tsx was in devDependencies, not available in production
Solution:
1. Add COPY scripts directory in Dockerfile (line 69)
2. Move tsx from devDependencies to dependencies in package.json
3. Update pnpm-lock.yaml to reflect dependency change
Changes:
- Dockerfile: Added COPY --from=backend-builder scripts directory
- package.json: Moved tsx@^4.7.0 to dependencies
- pnpm-lock.yaml: Updated lockfile
This allows the REGENERATE_GIFS environment variable to work correctly
in production, enabling automatic GIF regeneration on container startup.
Co-Authored-By: Auggie
Backend changes:
- Add ffmpeg to Docker image for video processing
- Create gifGenerator utility with high-quality palette-based GIF generation
- Update Prisma schema: Add GIF to MediaKind enum
- Auto-generate 300px GIF preview (10fps, 3sec) on video upload
- Add POST /api/terms/:id/media/:mediaId/regenerate-gif endpoint for admins
- Update delete endpoint to cascade delete GIFs when video is deleted
- GIF generation uses ffmpeg with palette optimization for quality
Frontend changes:
- Update MediaKind enum to include GIF
- Display animated GIF previews in dictionary word cards
- Show 'No preview' icon for videos without GIF
- Add 'Regenerate GIF' button in admin video upload UI
- Display both video and GIF side-by-side in admin panel
- Visual indicator when GIF preview is available
Features:
- Automatic GIF generation on video upload (non-blocking)
- Manual GIF regeneration from admin panel
- GIF preview in dictionary listing for better UX
- Fallback to video icon when no GIF available
- Proper cleanup: GIFs deleted when parent video is deleted
Technical details:
- GIFs stored in /uploads/gifs/
- Uses two-pass ffmpeg encoding with palette for quality
- Configurable fps, width, duration, start time
- Error handling: video upload succeeds even if GIF fails
Co-Authored-By: Auggie