Extracts JPEG frames from video files using ffmpeg and publishes them to Redis.
Video File → ffmpeg (-re) → Go Worker → Redis
- ffmpeg: Reads video file in real-time, outputs JPEG frames to stdout
- Go worker: Parses JPEG boundaries (SOI/EOI markers), publishes latest frame to Redis
- Redis: Temporary cache with TTL, one key per stream
- Go 1.21+
- ffmpeg
- Redis 7
-
Copy environment file:
cp .env.example .env
-
Edit
.envwith your video path:VIDEO_PATH=/path/to/your/video.mp4 STREAM_ID=my-stream
-
Start Redis:
docker run -d --name redis -p 6379:6379 redis:7
-
Run the worker:
go run ./cmd/worker
| Variable | Default | Description |
|---|---|---|
VIDEO_PATH |
(required) | Path to video file |
STREAM_ID |
default |
Unique stream identifier |
REDIS_ADDR |
localhost:6379 |
Redis connection string |
FRAME_RATE |
1 |
Frames per second (use 0.0167 for 1 FPM) |
FRAME_TTL_SECONDS |
2× frame interval |
Redis key TTL |
FFMPEG_PATH |
ffmpeg |
Path to ffmpeg binary |
- Key:
stream:{id}:frame - Value: JPEG bytes
- TTL: Configured via
FRAME_TTL_SECONDS
To consume frames and save them to disk, you must run the worker in Queue Mode and start the consumer with the same STREAM_ID.
-
Start Worker (Queue Mode):
export REDIS_QUEUE_MODE=true export STREAM_ID=my-stream export VIDEO_PATH=video.mp4 go run ./cmd/worker
-
Start Consumer:
export STREAM_ID=my-stream go run ./cmd/consumer
Frames will be saved to ./captured_frames/ (configurable via OUTPUT_DIR).
# Check if frame exists
redis-cli EXISTS stream:my-stream:frame
# View JPEG header (should show: ff d8 = JPEG SOI marker)
redis-cli GET stream:my-stream:frame | xxd | head -1
# Check TTL
redis-cli TTL stream:my-stream:frame- 1 video file = 1 worker process
- Worker auto-restarts ffmpeg on failure
- Graceful shutdown on SIGINT/SIGTERM