Media
Image compression, video support and optimization pipeline
Current state
Images upload directly to S3 via the backend — no compression, no resizing, no format optimization, no video support. (Orphaned-object cleanup and thumbnails are also launch-checklist items.)
Image optimization
Client-side compression (before upload) with browser-image-compression: resize to max 1920px width, ~80% quality, WebP — target <500KB per image (down from 3–10MB originals).
Server-side processing (after upload, V2) with Sharp: thumbnails (200×200, 400×400), WebP + AVIF variants, strip EXIF (except for verification — keep GPS/date for scam checks).
CDN: serve via CloudFront or Cloudflare; consider Cloudflare Images or imgproxy for on-the-fly resize.
Video support
Constraints: max 30 seconds (product demo clips), max 50MB after compression; accept MP4/WebM/MOV; output MP4 (H.264) for universal playback.
Client-side compression: FFmpeg.wasm (recommended over MediaRecorder — full codec control; ~3MB WASM download on first use; show a progress bar on low-end devices):
-c:v libx264 -crf 28 -preset fast
-vf scale='min(1280,iw)':'-2'
-c:a aac -b:a 128k
-movflags +faststart
-t 30Upload flow:
Playback: native <video> with lazy loading, poster thumbnail, no autoplay, progressive download (HLS/DASH is overkill for 30s clips).
Data model
Short term, the deal images JSON array can hold both with a prefix convention (video:https://s3.../clip.mp4). Cleaner V2 model:
model DealMedia {
id Int @id @default(autoincrement())
dealId Int
deal Deal @relation(fields: [dealId], references: [id])
type MediaType // IMAGE or VIDEO
url String
thumbnail String? // video thumbnail
order Int @default(0)
}
enum MediaType {
IMAGE
VIDEO
}Tasks
Images (V1): browser-image-compression; compression step + progress in the ImageUpload shared component.
Video (V1): @ffmpeg/ffmpeg; compression utility; upload component with validation; multipart S3 upload; server-side thumbnail (ffmpeg); player component on the deal page; deal form accepts video.
Optimization (V2): Sharp thumbnails; WebP/AVIF variants; CDN; lazy loading in deal lists.