Create GIF clips from your Plex media library. Self-hosted, single-container. Optional integrations.
- Browse & Search - Navigate your Plex libraries or search by title
- Subtitle Navigation - Click subtitle lines to jump to that moment
- Clip Start & Duration - Choose where the clip begins and how long it runs, with frame preview
- GIF Generation - Create GIFs with optional subtitle burn-in or custom text
- Gallery - View, download, and manage your created GIFs
- GIPHY Upload - Upload GIFs directly to GIPHY (optional)
docker run -d -p 8000:8000 -v ./data:/data --name clipmark ghcr.io/reggio-digital/clipmark:latestOpen http://localhost:8000 and connect your Plex account.
Note: Plex Media Server must be reachable from the container.
services:
clipmark:
image: ghcr.io/reggio-digital/clipmark:latest
container_name: clipmark
ports:
- "8000:8000"
volumes:
- ./data:/data
restart: unless-stoppeddocker run -d \
-p 8000:8000 \
-v ./data:/data \
--name clipmark \
ghcr.io/reggio-digital/clipmark:latest- Docker
- Plex Media Server (accessible from the container)
Environment variables (all optional):
| Variable | Default | Description |
|---|---|---|
DATA_DIR |
/data |
Persistent storage path |
MAX_CONCURRENT_JOBS |
1 |
Parallel FFmpeg jobs |
MAX_QUEUED_JOBS |
10 |
Max pending jobs |
MAX_QUEUED_JOBS_PER_USER |
3 |
Max pending jobs per user |
MAX_GIF_DURATION_SECONDS |
15 |
Max GIF length |
MAX_PREVIEW_DURATION_SECONDS |
10 |
Max preview length |
MAX_WIDTH |
480 |
Max output width (pixels) |
MAX_FPS |
10 |
Max frame rate |
FRAME_CACHE_TTL_MINUTES |
30 |
Frame cache lifetime |
PREVIEW_CACHE_TTL_MINUTES |
30 |
Preview cache lifetime |
FAILED_WORKSPACE_TTL_HOURS |
24 |
Failed job cleanup delay |
FFMPEG_TIMEOUT_SECONDS |
300 |
FFmpeg process timeout |
Output defaults are 480px width and 10 FPS. Environment variables define upper limits, not per-GIF defaults.
These are managed via the admin UI and stored in data/config.json:
| Setting | Default | Description |
|---|---|---|
gifsicle_enabled |
true |
Enable gifsicle GIF compression |
gifsicle_lossy |
100 |
Lossy compression level (0-200) |
public_sharing_enabled |
false |
Allow public GIF sharing via link |
giphy_global_enabled |
true |
Allow users to upload to GIPHY |
max_gif_duration_seconds |
15 |
Default max GIF duration |
max_width |
480 |
Default max output width |
max_fps |
10 |
Default max frame rate |
browse_page_size |
48 |
Items per page when browsing |
Mount /data as a volume. Contains:
/data/
├── config.json # Plex token (treat as secret)
├── clipmark.db # SQLite database
├── cache/
│ ├── frames/ # Extracted video frames
│ ├── previews/ # GIF previews
│ ├── thumbnails/ # Media thumbnails
│ └── subtitles/ # Parsed subtitle data
├── work/ # Job workspaces (auto-cleaned)
└── output/ # Generated GIFs
Clipmark can upload your GIFs directly to GIPHY. To enable this:
- Create a free account at developers.giphy.com
- Create an app to get an API key
- Go to Settings in Clipmark and enter your API key
Once configured, a GIPHY upload button appears on completed GIFs in the gallery. Uploaded GIFs follow GIPHY's standard review and visibility rules.
Clipmark uses gifsicle to reduce GIF file sizes by 20-40%. This is enabled by default and can be configured in Settings:
- Enable/disable — Toggle optimization on or off
- Lossy compression — Adjust quality vs size (0-200, default 100)
Higher lossy values = more compression = smaller files but more artifacts.
Clipmark detects subtitles associated with Plex items (sidecar or embedded). If no subtitles appear for your media:
- Check Plex first — Open the media in Plex and verify subtitles are available there
- Search in Plex — Plex can search for and download subtitles directly from the media detail page
- Add external subtitles — Place
.srtfiles alongside your media files with matching names (e.g.,Movie.mp4→Movie.srtorMovie.en.srt), then refresh the library in Plex - Embedded subtitles — These are automatically detected if present in the media file
Supported formats for burn-in:
- SRT, ASS/SSA, WebVTT — Full support (text-based)
- PGS, DVD subtitles — Detected but cannot be burned into GIFs (image-based bitmap subtitles)
If your media only has PGS/DVD bitmap subtitles, convert to SRT (via OCR tools) or use custom text overlay instead.
Tip: Bazarr can automatically find and download subtitles across your entire library. It's a great companion if you want subtitles available without manually searching in Plex for each title.
First-time setup:
# Frontend
cd frontend && npm install
# Backend
cd backend && python3 -m venv venv && ./venv/bin/pip install -r requirements.txtThen from the frontend/ directory:
npm run devThis starts both the backend (port 8000) and frontend dev server (port 5173) with hot reload. You can also run npm run dev from the project root, which delegates to the frontend script.
docker build -t clipmark .- Frontend: React, TypeScript, Vite, Tailwind CSS
- Backend: Python, FastAPI, SQLAlchemy, SQLite
- Plex: python-plexapi
- Media: FFmpeg, gifsicle
- Plex token stored server-side, never sent to browser
- If exposing to the internet, use a reverse proxy with HTTPS
MIT — see LICENSE for details.


