Help us shape the future of Go! Take the 2026 Go Developer Survey

outtake

command module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2026 License: AGPL-3.0 Imports: 3 Imported by: 0

README

Outtake

Outtake

A web app that cuts video clips, GIFs, and screenshots from your Plex libraries.

Test Lint Docker Hub pulls GHCR License

Table of Contents

What it does

  • Sign in with Plex (or paste a token).
  • Browse libraries, search titles, and open an item.
  • Mark start and end from live Plex playback, or type the times yourself.
  • Export a video clip, GIF, or screenshot, then preview and download it.
  • Manage named clip profiles (CRF, encoder preset, audio bitrate, max resolution) and optionally Trim black bars or Web-safe color on each export.

The server listens on port 8080 by default.

Requirements

  • A Plex account and a Plex Media Server that Outtake can reach.
  • Read access to the media files Plex reports (on the host, or mounted into Docker).
  • Docker images ship static ffmpeg and ffprobe.
  • A host binary needs ffmpeg and ffprobe on PATH (or set OUTTAKE_FFMPEG_PATH and OUTTAKE_FFPROBE_PATH).

Install

Two deploy modes: Docker Compose is the local filesystem + SQLite path. Kubernetes is for clusters. You point NFS (or an existing claim) at Plex media. Clips and metadata do not live on that share.

Docker Compose

Images are published as ghcr.io/papagolabs/outtake and papagolabs/outtake. This matches examples/docker/docker-compose.yaml:

services:
  outtake:
    image: ghcr.io/papagolabs/outtake:latest
    container_name: outtake
    ports:
      - "8080:8080"
    volumes:
      - outtake-data:/data
      - ${OUTTAKE_MEDIA_PATH:-/path/to/your/media}:/media:ro
    environment:
      OUTTAKE_LOG_LEVEL: info
      OUTTAKE_LISTEN_ADDR: 0.0.0.0:8080
      OUTTAKE_PUBLIC_BASE_URL: ${OUTTAKE_PUBLIC_BASE_URL:-http://localhost:8080}
      OUTTAKE_PLEX_MEDIA_ROOT: ${OUTTAKE_PLEX_MEDIA_ROOT:-}
      OUTTAKE_LOCAL_MEDIA_ROOT: ${OUTTAKE_LOCAL_MEDIA_ROOT:-/media}
    restart: unless-stopped

volumes:
  outtake-data:

Point OUTTAKE_MEDIA_PATH at the directory that contains the files Plex plays, then start the stack:

export OUTTAKE_MEDIA_PATH=/path/to/your/media
docker compose up -d

Then open http://localhost:8080.

Compose defaults to filesystem blobs and SQLite. Clips land on OUTTAKE_STORAGE_PATH (the /data volume), not on the media bind. docker-compose.yml is the same local path when you build from source.

If Plex reports a different filesystem prefix than that mount, also set OUTTAKE_PLEX_MEDIA_ROOT (see Configuration).

Docker
docker run -d \
  --name outtake \
  -p 8080:8080 \
  -v outtake-data:/data \
  -v /path/to/your/media:/media:ro \
  -e OUTTAKE_LOCAL_MEDIA_ROOT=/media \
  -e OUTTAKE_PUBLIC_BASE_URL=http://localhost:8080 \
  ghcr.io/papagolabs/outtake:latest

The image entrypoint is /outtake. The default command is server start.

Binary

Tagged GitHub Releases are not published yet. When they are, unpack the outtake archive for your OS, install ffmpeg and ffprobe, and run:

./outtake server start

The server binds 0.0.0.0:8080 by default. Override with --listen or OUTTAKE_LISTEN_ADDR. On Linux, the database and exports default to ~/.local/share/outtake/.

Until a release exists, use Docker or Compose.

Local image from source

From a repository checkout, copy .env.example to .env, set OUTTAKE_MEDIA_PATH, and build:

cp .env.example .env
docker compose up --build

This uses build/docker/Dockerfile.dev and also bundles ffmpeg and ffprobe.

Kubernetes

There is no Helm repo or OCI chart. Cluster examples live under examples/kubernetes/.

Suggested stacks (Outtake + SeaweedFS + a database, NFS for Plex media only):

Set nfs.example.internal and /export/plex to your Plex media NFS. Clip blobs stay on S3. They do not live on the media NFS share. Replace the outtake-s3 keys (and the matching config.json identity) before apply:

kubectl apply -k examples/kubernetes/seaweedfs-cnpg

or

kubectl apply -k examples/kubernetes/seaweedfs-cockroach

An example Helm chart is in examples/kubernetes/helm/outtake. Values and optional chart backends are in that chart README. Do not helm repo add.

The only site input is Plex media: NFS in the suggested manifests, or media.nfs / media.existingClaim on the chart. Defaults match Compose (filesystem and sqlite) unless you enable a backend. The image is ghcr.io/papagolabs/outtake:latest (no tagged release yet).

Configuration

Outtake reads OUTTAKE_* environment variables. Compose files also use OUTTAKE_MEDIA_PATH for the host library bind (that name is not an application setting).

Docker images store the SQLite database and filesystem exports under /data (outtake.db and output/). The example compose file keeps that volume as outtake-data. Clip blobs use OUTTAKE_STORAGE_PATH (or S3 when OUTTAKE_STORAGE_BACKEND=s3). Clip metadata lives in the database (OUTTAKE_DATABASE_PATH or OUTTAKE_DATABASE_URL). OUTTAKE_LOCAL_MEDIA_ROOT and OUTTAKE_PLEX_MEDIA_ROOT are source media only, not the clip store, and not Kubernetes media NFS.

Variable Purpose Default
OUTTAKE_LISTEN_ADDR Address the web server binds 0.0.0.0:8080 (images use :8080)
OUTTAKE_PUBLIC_BASE_URL URL Plex should return to after sign-in derived from the listen address, or http://localhost:8080 in images
OUTTAKE_DATABASE_BACKEND sqlite or postgres sqlite
OUTTAKE_DATABASE_PATH SQLite database file ~/.local/share/outtake/outtake.db (images use /data/outtake.db)
OUTTAKE_DATABASE_URL Postgres/pgx DSN (when backend is postgres) unset
OUTTAKE_STORAGE_BACKEND filesystem or s3 filesystem
OUTTAKE_STORAGE_PATH Filesystem blobs, or S3 scratch, not Plex media / NFS ~/.local/share/outtake/output (images use /data/output)
OUTTAKE_S3_ENDPOINT S3-compatible API endpoint unset
OUTTAKE_S3_BUCKET S3 bucket unset
OUTTAKE_S3_REGION S3 region us-east-1
OUTTAKE_S3_ACCESS_KEY S3 access key unset
OUTTAKE_S3_SECRET_KEY S3 secret key unset
OUTTAKE_S3_USE_PATH_STYLE Path-style S3 URLs (typical for SeaweedFS / RustFS) true
OUTTAKE_LOCAL_MEDIA_ROOT Local directory that should contain Plex files (container mount is usually /media). Source media only unset (compose examples set /media)
OUTTAKE_PLEX_MEDIA_ROOT Prefix Plex reports for those files, replaced by OUTTAKE_LOCAL_MEDIA_ROOT. Source media only unset
OUTTAKE_FFMPEG_PATH ffmpeg binary ffmpeg (images use /usr/bin/ffmpeg)
OUTTAKE_FFPROBE_PATH ffprobe binary ffprobe (images use /usr/bin/ffprobe)
OUTTAKE_MAX_CLIP_DUR Maximum clip duration in seconds 600
OUTTAKE_CROP_BLACK_BARS Default for Trim black bars false
OUTTAKE_WEB_SAFE_COLOR Default for Web-safe color on video clips false
OUTTAKE_SESSION_POLL_SEC How often to poll live Plex playback 10
OUTTAKE_NUM_WORKERS Background clip workers 2
OUTTAKE_LOG_LEVEL debug, info, warn, or error info
OUTTAKE_PLEX_SERVER_URL Optional Plex Media Server URL unset
OUTTAKE_PLEX_TOKEN Optional Plex token (browser sign-in does not need this) unset
OUTTAKE_PLEX_CLIENT_ID Plex client identifier generated if unset

Plex gives Outtake absolute file paths. If those paths are not readable as-is (typical in Docker), set OUTTAKE_LOCAL_MEDIA_ROOT to the mount. When OUTTAKE_PLEX_MEDIA_ROOT is also set, that prefix is stripped and the remainder is joined under the local root. When only the local root is set, the Plex path is joined under that mount.

If you open Outtake from another host, set OUTTAKE_PUBLIC_BASE_URL to the URL you type in the browser so Plex sign-in can return.

First run

  1. Open http://localhost:8080. Unauthenticated visits redirect to Login.
  2. Choose Sign in with Plex. Outtake opens the Plex Auth App in a popup and shows Waiting for Plex authorization... until you approve it.
  3. Or paste a token into Plex Token and choose Sign In.
  4. If Outtake finds exactly one Media Server, it uses that server and continues to the dashboard. Otherwise it opens Select a Plex server. Choose Use this server, or enter a custom URL such as https://plex.example.com and choose Use this URL.

You can change servers later under Settings → Servers.

Make a clip

  1. Open Media Libraries (or Browse Media on the dashboard).
  2. Search, or browse a library, then Open a title. Folders and shows use Browse until you reach a playable item.
  3. On the item page, play the title in Plex if you want live markers. When Plex is playing, use Set start from Plex and Set end from Plex. You can also type Start and End yourself.
  4. Under New export, set Export as to Video clip, GIF, or Screenshot, pick a Profile, and optionally Trim black bars. For video clips, Web-safe color tone-maps HDR on the CPU so the file looks consistent in browsers. Leave it off if you will grade the clip yourself.
  5. Choose Preview to check the segment, then Save clip.

If something is already playing, the dashboard Live Sessions list includes Clip now.

Finished exports appear on the item and on Clips. When a job is completed and the file is on disk, use Download. Progress updates while a job is pending or processing.

Named encode settings live under Settings → Clip Profiles. Lower CRF is higher quality.

Troubleshooting

  • Login never finishes. Approve the Plex popup. If you reach Outtake through a hostname other than localhost, set OUTTAKE_PUBLIC_BASE_URL to that URL.
  • No Plex servers were discovered. Use Custom server URL on the servers page. Outtake must be able to reach that address.
  • No media found. Select a server first, then search or browse again.
  • Clips fail or files are missing. The path Plex reports must be readable. In Docker, mount the library and set OUTTAKE_PLEX_MEDIA_ROOT / OUTTAKE_LOCAL_MEDIA_ROOT so that path lands on /media. On Kubernetes, that mount is the NFS volume in the suggested manifests (or media.nfs / media.existingClaim on the example chart). Source media only. Clip blobs stay on OUTTAKE_STORAGE_PATH or S3, not on the media NFS share. Clip metadata is in the database.
  • Kubernetes apply fails. Set the NFS server and path to your Plex library. Replace the outtake-s3 keys before apply. For seaweedfs-cnpg, install the CloudNativePG operator first.
  • Wrong storage or database backend. Defaults are filesystem and sqlite. For S3, set OUTTAKE_STORAGE_BACKEND=s3 plus the OUTTAKE_S3_* keys. For postgres, set OUTTAKE_DATABASE_BACKEND=postgres and OUTTAKE_DATABASE_URL. The suggested Kubernetes stacks use S3 and postgres. On the example chart, enable at most one blob backend (backends.seaweedfs or backends.rustfs) and one database backend (backends.cockroach or backends.cnpg).
  • ffmpeg / ffprobe errors on a host binary. Install both tools and keep them on PATH, or set the path variables above. Docker images already include them.

License

Outtake is licensed under the GNU Affero General Public License v3.0.

Contributing

Development commands and repo conventions live in AGENTS.md.

Documentation

Overview

Package main hosts the outtake command, a web-based media clipper for Plex libraries. It enables users to create video clips, GIFs, and screenshots from their Plex media server through an intuitive HTMX-powered web interface.

Directories

Path Synopsis
internal
api
Package api names the wire types handlers still import.
Package api names the wire types handlers still import.
app
Package app provides the application composition root and lifecycle management.
Package app provides the application composition root and lifecycle management.
app/health
Package health provides health check logic for the outtake server.
Package health provides health check logic for the outtake server.
clip
Package clip holds the clip record, the render that produces it, and the encode policy that shapes both.
Package clip holds the clip record, the render that produces it, and the encode policy that shapes both.
clip/catalog
Package catalog holds the clip list query and the rules that filter and order jobs for it.
Package catalog holds the clip list query and the rules that filter and order jobs for it.
clip/preview
Package preview renders the short low quality segments a user watches before exporting a clip.
Package preview renders the short low quality segments a user watches before exporting a clip.
clip/profile
Package profile is the settings subdomain that owns the clip encode profiles: the built-in quality presets, the profiles a user stores against them, and the service that reads and edits those stored profiles.
Package profile is the settings subdomain that owns the clip encode profiles: the built-in quality presets, the profiles a user stores against them, and the service that reads and edits those stored profiles.
clip/queue
Package queue provides a simple job queue for processing media jobs.
Package queue provides a simple job queue for processing media jobs.
cmd
Package cmd provides the outtake CLI commands.
Package cmd provides the outtake CLI commands.
cmd/health
Package health provides the health check CLI command.
Package health provides the health check CLI command.
cmd/server
Package server provides server-related CLI commands.
Package server provides server-related CLI commands.
cmd/version
Package version provides the CLI command for displaying application version information.
Package version provides the CLI command for displaying application version information.
ffmpeg
Package ffmpeg drives the ffmpeg and ffprobe processes that turn a source into a clip, a GIF, a still, or a preview.
Package ffmpeg drives the ffmpeg and ffprobe processes that turn a source into a clip, a GIF, a still, or a preview.
ffmpeg/crop
Package crop parses ffmpeg cropdetect rectangles.
Package crop parses ffmpeg cropdetect rectangles.
ffmpeg/probe
Package probe reads what a source file actually is, using ffprobe.
Package probe reads what a source file actually is, using ffprobe.
ffmpeg/progress
Package progress reports ffmpeg encode completion from stderr.
Package progress reports ffmpeg encode completion from stderr.
ffmpeg/tonemap
Package tonemap builds the ffmpeg filter chain that maps an HDR source down to Rec.709 so a browser renders it the way it was graded.
Package tonemap builds the ffmpeg filter chain that maps an HDR source down to Rec.709 so a browser renders it the way it was graded.
logging
Package logging provides structured logging for outtake.
Package logging provides structured logging for outtake.
metadata
Package metadata provides application version and build information.
Package metadata provides application version and build information.
plex
Package plex provides a client for the Plex Media Server API.
Package plex provides a client for the Plex Media Server API.
plex/decode/key
Package key resolves Plex metadata identifiers from Plex metadata paths.
Package key resolves Plex metadata identifiers from Plex metadata paths.
plex/decode/plextv
Package plextv decodes plex.tv XML MediaContainer envelopes.
Package plextv decodes plex.tv XML MediaContainer envelopes.
plex/decode/pms
Package pms decodes documented Plex Media Server JSON envelopes.
Package pms decodes documented Plex Media Server JSON envelopes.
plex/identity
Package identity owns who the caller is and which Plex server answers for them.
Package identity owns who the caller is and which Plex server answers for them.
plex/library
Package library holds the media library domain that sits behind the HTTP adapter.
Package library holds the media library domain that sits behind the HTTP adapter.
plex/session
Package session monitors live playback sessions on a Plex Media Server.
Package session monitors live playback sessions on a Plex Media Server.
settings/config
Package config is the settings subdomain that loads the application configuration, from the config file, the environment, and the defaults it seeds when neither carries a value.
Package config is the settings subdomain that loads the application configuration, from the config file, the environment, and the defaults it seeds when neither carries a value.
settings/flags
Package flags defines every command-line flag the outtake CLI accepts, one file per command.
Package flags defines every command-line flag the outtake CLI accepts, one file per command.
store/blob
Package blob provides blob storage for media files.
Package blob provides blob storage for media files.
store/database
Package database provides SQLite and Postgres-protocol access for outtake.
Package database provides SQLite and Postgres-protocol access for outtake.
timecode
Package timecode formats and parses FFmpeg time durations.
Package timecode formats and parses FFmpeg time durations.
web
Package web assembles Outtake's inbound HTTP layer.
Package web assembles Outtake's inbound HTTP layer.
web/exportform
Package exportform decodes the New export form from a request or a query, for the media item page and the redirect a finished preview comes back through.
Package exportform decodes the New export form from a request or a query, for the media item page and the redirect a finished preview comes back through.
web/handlers/auth
Package auth serves the Plex sign-in routes.
Package auth serves the Plex sign-in routes.
web/handlers/clip
Package clip serves the clip routes: creating a clip, editing one, canceling one, deleting one, listing them, and handing a finished file back.
Package clip serves the clip routes: creating a clip, editing one, canceling one, deleting one, listing them, and handing a finished file back.
web/handlers/health
Package health serves the liveness endpoint.
Package health serves the liveness endpoint.
web/handlers/home
Package home serves the dashboard, login, playback, and appearance pages.
Package home serves the dashboard, login, playback, and appearance pages.
web/handlers/library
Package library serves the media library pages: the browse grid, a media item, and the library navigation.
Package library serves the media library pages: the browse grid, a media item, and the library navigation.
web/handlers/library/media
Package media serves the routes that read Plex media directly: the live session lookup and the media search.
Package media serves the routes that read Plex media directly: the live session lookup and the media search.
web/handlers/library/thumb
Package thumb serves the Plex thumbnail cache proxy, which answers a poster request from the local cache and otherwise fetches it from the selected server.
Package thumb serves the Plex thumbnail cache proxy, which answers a poster request from the local cache and otherwise fetches it from the selected server.
web/handlers/preview
Package preview serves the segment previews the export form shows: rendering one, reporting its progress, canceling it, and serving the file a finished render published.
Package preview serves the segment previews the export form shows: rendering one, reporting its progress, canceling it, and serving the file a finished render published.
web/handlers/profile
Package profile serves the clip profile settings page and the edits posted to it.
Package profile serves the clip profile settings page and the edits posted to it.
web/handlers/server
Package server serves the Plex server list and the selection posted to it.
Package server serves the Plex server list and the selection posted to it.
web/middleware
Package middleware provides HTTP middleware for the outtake API.
Package middleware provides HTTP middleware for the outtake API.
web/respond
Package respond holds how a handler answers a request.
Package respond holds how a handler answers a request.
web/routes
Package routes holds the vocabulary of the web surface: the paths it serves, the query parameters it reads, and how a link into it is built.
Package routes holds the vocabulary of the web surface: the paths it serves, the query parameters it reads, and how a link into it is built.
web/theme
Package theme catalogs selectable UI color palettes.
Package theme catalogs selectable UI color palettes.
web/utils
Package utils provides shared helpers for the Outtake web layer.
Package utils provides shared helpers for the Outtake web layer.
web/view
Package view holds shared HTML view models for Outtake pages and widgets.
Package view holds shared HTML view models for Outtake pages and widgets.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL