Self-hosting OpenSeek

This page is for indexing media you already have and have the right to process. Nothing here needs or expects anyone else to supply media: you point the generator at a file on your own disk, and the service serves only what you generated.

What not to publish

The repository contains helpers that locate third-party stream sources. They are for the maintainers' own sourcing work, they are deliberately not part of what to share, and they are not needed for anything on this page. Keep your installation to the three programs below — the generator, the server and the registry — which is everything the self-host path requires.

Step by step

  1. Generate sheets and a WebVTT from a local file. This needs ffmpeg on your PATH and Pillow (pip install Pillow).

    python3 spritegen/spritegen.py --id MY_ID --title "My Film" \
      --in /path/to/file.mp4 --out store/MY_ID/ \
      --interval 10 --mode fast --workers 4 --sizes 320x180

    It writes JPEG sprite sheets of 320×180 tiles and a thumbnails.vtt beside them. --interval accepts 5, 10 or 30 seconds; 10 is the default and the one the registry expects for a good match. The run exits non-zero if it produced no frames, and it never writes an empty cue track.

  2. Serve the store locally. The server is standard library only.

    python3 server/server.py --store ./store --port 8080

    Look a title up by id and duration, then open the vtt_url from the response:

    curl 'http://127.0.0.1:8080/sprites?imdb_id=tt0111161&duration_ms=8280000'

    This local lookup takes no key. The response carries vtt_url alongside source_duration_ms and scale, and the sheets sit next to the cue track under /s/.

  3. Optional: run the shared registry. If several clients should see one catalogue, run the registry instead of the plain store. It is standard library plus sqlite3.

    python3 registry/init_db.py
    python3 registry/registry.py --port 8080

    init_db.py is idempotent: it applies the schema and then any migrations, so re-running it against an existing database is safe. Keys live in a keys table, and one is minted on the host with:

    python3 mint_key.py <name>

    The key is printed once and only a hash of it is stored, with a six-character prefix, so it cannot be displayed again. Mint a replacement and revoke the old one by prefix. X-API-Key is required on /v1/sprites, POST /v1/contribute and POST /v1/register.

    There is no route for asking the registry to index something. POST /v1/contribute is the only public write, and it takes previews you generated yourself from a file you have the right to process — the registry never downloads anything. If you want to queue your own generation work, insert rows into the jobs table on the registry host and let a worker lease them from there.

  4. Optional: point the player at your own origin. Both SDKs take the registry origin as their base, so pass your own host instead of the hosted one. A self-hosted registry speaks plain HTTP, so if you serve to browsers over HTTPS, put a reverse proxy in front of it and terminate TLS there.

  5. Optional: mirror to object storage or a CDN. Set the base the registry advertises:

    python3 registry/registry.py --port 8080 --cdn-base <your CDN base URL>
    # or
    OPENSEEK_CDN_BASE=<your CDN base URL> python3 registry/registry.py

    Only the advertised vtt_url changes. The store layout, the database rows and the merge path are untouched, and the cue payloads are sheet-relative, so they resolve against whichever base was handed out. The bytes are public, unsigned and do not expire, which is what makes mirroring them safe.

Limits

Elsewhere