Self-hostable, open-source media review platform. A collaborative alternative to Frame.io.
FreeFrame gives production houses and creative teams a self-hosted platform for reviewing video, image, and audio assets with frame-accurate commenting, annotations, and approval workflows. Your media stays on your infrastructure.
Frame-accurate review: timecoded comment threads, guest replies, resolved ranges, and SMPTE timecode — on your own infrastructure.
- Video review with HLS adaptive streaming and frame-accurate timecoded comments
- Export comments to your NLE — DaVinci Resolve (marker EDL), Final Cut Pro (FCPXML), Premiere Pro (XML), or CSV
- Image and audio review with annotations and waveform visualization
- Drawing annotations on any frame using canvas tools
- Threaded comments with mentions, reactions, and attachments
- Approval workflows with per-reviewer status tracking
- Version compare — put any two versions side-by-side or under a wipe slider, with per-version comments and annotations
- Folder organization within projects
- Team collaboration with role-based permissions (org, team, project levels)
- Share links for external reviewers (password-protected, expiring)
- Guest commenting via share links (no account required)
- Due date tracking with email reminders
- Real-time updates via Server-Sent Events
- White-label it completely — your workspace name, logos, favicon and accent colour across the app, share links and emails; the "Powered by FreeFrame" badge switches off
- Self-hosted with Docker Compose — runs on any server or cloud VM
Put two cuts or revisions on screen at once and see exactly what changed. Video plays in frame-accurate sync with per-side audio and offset trim for re-edited cuts; images compare side-by-side or under a draggable wipe. Each version keeps its own comment thread and annotations, and the whole view is shareable by URL.
| Images side-by-side | Wipe slider |
|---|---|
![]() |
![]() |
Export a version's timecoded comments as timeline markers your editor can import — DaVinci Resolve (marker EDL), Final Cut Pro (FCPXML), Premiere Pro (XML), or CSV — so notes land on the exact frame back in the timeline.
See Export comments to an NLE for the export workflow, format choices, and frame-rate troubleshooting.
Send a link; clients review and comment without signing up. You stay in control of every link: comments/downloads permissions, passphrase, expiration date, watermarking, and appearance.
| Client view (no login) | Your share-link controls |
|---|---|
![]() |
![]() |
Set your workspace name, logos and accent colour once, and the whole platform follows — sign-in screen, sidebar, browser tab, share links, and the emails your clients receive. Switch off the "Powered by FreeFrame" badge (left on in the shots below) and nothing identifies the software your studio runs on.
A live preview shows the app, the sign-in screen and an email side by side with the controls, so you can see what a change does before saving it.
| Live preview of the branded app | The controls |
|---|---|
![]() |
![]() |
Prerequisites: Docker and Docker Compose
git clone https://github.com/Techiebutler/freeframe.git
cd freeframe
cp .env.example .env
docker compose -f docker-compose.dev.yml up --buildOpen http://localhost:3000 to access FreeFrame. The first user to sign up becomes the super admin.
Services running in dev:
| Service | URL |
|---|---|
| Frontend | http://localhost:3000 |
| API | http://localhost:8000 |
| API Docs | http://localhost:8000/docs |
| MinIO Console | http://localhost:9001 |
By default the dev stack is reachable only from the host machine (localhost). To open FreeFrame from a phone or another computer on the same network, point a few URLs at your machine's LAN IP — find it with ipconfig getifaddr en0 (macOS) or hostname -I (Linux) — then recreate the containers.
In .env (replace 192.168.1.50 with your IP):
NEXT_PUBLIC_API_URL=http://192.168.1.50:8000 # web → API (baked into the browser bundle)
FRONTEND_URL=http://192.168.1.50:3000 # links in invite/magic-code emails
CORS_ALLOW_ORIGINS=* # API allows the LAN browser origin
S3_PUBLIC_ENDPOINT=http://192.168.1.50:9000 # presigned upload/download URLs
MINIO_CORS_ALLOW_ORIGIN=* # MinIO allows the LAN browser origindocker compose -f docker-compose.dev.yml up -d --force-recreateThen browse to http://192.168.1.50:3000 from any device on the network. Server-side settings (DATABASE_URL, S3_ENDPOINT, …) stay on their docker-internal hostnames — only the browser-facing URLs above change.
The
*wildcards are LAN-testing conveniences — don't use them in production. See docs/deployment.md for a locked-down setup.
Production self-hosters should run a released version, not main:
| Ref | What it is | Use it if… |
|---|---|---|
stable |
The latest release we've validated — a bad release is never promoted here. | Production (safe default): git clone -b stable …, then git pull to update. |
latest |
The newest published release (moves on every release). | You want new features sooner and can tolerate the occasional regression. |
v1.3.1 (any vX.Y.Z) |
An immutable, pinned release. | You want to pin an exact version: git checkout v1.3.1. |
main |
Active development; may be unreleased or unstable. | You're developing or contributing to FreeFrame. |
Release notes are on the Releases page. Maintainers: see docs/RELEASING.md.
git clone -b stable https://github.com/Techiebutler/freeframe.git
cd freeframe
cp .env.example .env.prod
# Edit .env.prod — set your credentials, S3, email config
# For SSL: also set DOMAIN and ACME_EMAIL (Traefik auto-provisions Let's Encrypt certs)
docker compose --env-file .env.prod -f docker-compose.prod.yml up -d --buildFor the full guide including SSL setup, bring-your-own infrastructure (external database, Redis, S3, SMTP), scaling, and troubleshooting, see:
┌──────────────┐
│ Traefik │
│ :80/:443 │
└──────┬───────┘
│
┌───────────┴───────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Next.js │ │ FastAPI │
│ Frontend │ │ Backend │
└─────────────┘ └──────┬───────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────────┐
│ PostgreSQL │ │ Redis │ │ S3 Storage │
│ │ │ │ │ (AWS/R2/MinIO) │
└───────────┘ └─────┬─────┘ └───────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Celery │ │ Celery │ │ Celery │
│ Transcoder │ │ Email │ │ Maintenance │
└─────────────┘ └─────────────┘ └─────────────┘
▲
┌─────────────┐
│ Celery Beat │
└─────────────┘
| Component | Technology |
|---|---|
| Frontend | Next.js 14, React 18, Tailwind CSS, Zustand |
| Backend | FastAPI, SQLAlchemy, Pydantic |
| Database | PostgreSQL 15 |
| Queue | Celery + Redis |
| Transcoding | FFmpeg (multi-bitrate HLS) |
| Storage | Any S3-compatible (AWS, R2, B2, MinIO) |
| Proxy | Traefik (auto SSL via Let's Encrypt) |
| Auth | JWT + magic code email login |
| Guide | Description |
|---|---|
| Production Deployment | SSL, bring-your-own infra, scaling, troubleshooting |
| Architecture | System design, data flow, media pipeline, permissions |
| Export comments to an NLE | Export review notes for Resolve, Final Cut Pro, Premiere Pro, or CSV |
| Contributing | Dev setup, testing, code style, PR process |
| Environment Variables | Full config reference with comments |
We welcome contributions of every kind — not just code. Testing a release against your NLE and reporting what you find, improving docs, filing detailed bug reports, and suggesting workflow features from real production experience all move FreeFrame forward.
- Read the Contributing Guide for dev setup and conventions
- Grab a
good first issueto make your first PR - Ask questions or propose ideas in Discussions
We aim to respond to new issues and PRs within 48 hours.
MIT License — see LICENSE for details.
A project by Techiebutler
Have questions? Need help?
Email: support@techiebutler.com
Star the repo if FreeFrame is useful to you!









