Every frame
accounted for.

Tonemap is the media API between your render farm and the review room. Submit an EXR sequence; get back colour-managed proxies, a thumbnail, a contact sheet and a QC report — through your OCIO config, not ours.

Request an inviteRead the APIprivate alpha · invite-only
Key lightSpecular ridgeWindow spillPracticalShadow basin
Contour, every stop
Datum — 18 % grey
Above display white
Fig. 1 — a frame, surveyed. Scene-linear luminance, lit from the north-west. Move across it.computed, not a customer’s picture · contour interval 1 stop
InEXR sequences · ProRes · DNxHR
OutH.264 · JPG · JSON
ColourOpenColorIO, your config, pinned by hash
Talks toREST · Python SDK · signed webhooks
02What comes back

One request in.
Four artifacts and a verdict out.

Proxy

H.264 at the size and rate you ask for. Plays in a browser, RV, ShotGrid, ftrack, Kitsu.

mp4 · 1920 × 1080 · 24 fps

Thumbnail

A poster frame — the one you name, not the first one.

jpg · frame 1050

Contact sheet

The whole range at a glance, columns by rows.

jpg · 5 × 4

Filmstrip

One strip for a scrubber, with the frame offsets as JSON beside it.

jpg · json · 100 frames

QC report

The verdict, machine-readable: every check, what it measured, and the frames it names.

json

Webhook

Signed, retried with back-off, replayable by event id. Your tracker hears about it before anyone asks.

media_job.completed
03Colour

Your OCIO config. Not our opinion of it.

display whiteclipped at 1.0the shoulderthe toe
Fig. 2 — scene light has no ceiling; a display does. A view transform folds nearly four stops of highlight into the shoulder instead of clipping them. Which transform is your decision.

Every job names its input colour space, display and view. Tonemap resolves them against the config you registered, pins it by hash, and reports the config and LUT hashes beside the output — what was applied, not what was asked for.

Input
ACEScg
View
ACES 1.0 – SDR Video
Display
sRGB
Config
ocio_aces_1_3_salt · sha256 9f2c41…e41a
Tools
OCIO · OIIO · FFmpeg, versions pinned in the worker image
04QC

Found at 03:12 by a machine. Not at 10:00 in dailies.

Tonemap walks the range before it encodes a frame. Holes, duplicates, unreadable files and black frames are pinned to the frame number and written into the report, and the job’s events carry the count.

Fig. 3 — what the QC pass looks for. A hundred frames of one shot: two never arrived, one arrived black.
  • 01Missing frames
  • 02Duplicate frame numbers
  • 03Unreadable frames
  • 04Resolution mismatch
  • 05Black frames
  • 06Output duration mismatch
05API

Small, boring, scriptable.

REST, a typed Python SDK, idempotency keys, signed webhooks. It goes in the farm’s post-job hook and nobody thinks about it again.

tonemap-api.fly.dev/v1
from tonemap import (
    ArtifactType, ColorRequest, MediaJobCreate, OutputRequest,
    SourceAssetCreate, SourceType, TonemapClient,
)

with TonemapClient("https://tonemap-api.fly.dev", os.environ["TONEMAP_API_KEY"]) as client:
    asset = client.create_source_asset(SourceAssetCreate(
        source_type=SourceType.SEQUENCE,
        frame_pattern="sq010_sh020_comp_v003.%04d.exr",
        frame_start=1001, frame_end=1100,
    ))

    job = client.create_media_job(MediaJobCreate(
        source_asset_id=asset.id,
        idempotency_key="salt-sq010-sh020-comp-v003",
        color=ColorRequest(
            mode="ocio", ocio_config_id="ocio_aces_1_3_salt",
            input_color_space="ACEScg", display="sRGB", view="ACES 1.0 - SDR Video",
        ),
        outputs=(
            OutputRequest(type=ArtifactType.PROXY, container="mp4", codec="h264"),
            OutputRequest(type=ArtifactType.THUMBNAIL, frame=1050),
            OutputRequest(type=ArtifactType.CONTACT_SHEET, columns=5, rows=4),
            OutputRequest(type=ArtifactType.QC_REPORT),
        ),
    ))

    done = client.wait_for_media_job(job.id)   # or don’t — take the webhook
06Custody

Custody with an expiry date.

Tonemap is not where your masters live. It holds media for as long as processing needs it, and every API response says what is held and until when.

Worker intermediatesscratch frames, partial encodes

on completion

Source mediayour EXRs and masters

7 days

Artifactsproxies, sheets, reports

30 days

Job and event recordsmetadata only, no pictures

kept →
  • Isolated per studio — every query and every storage path is scoped to one tenant.
  • Signed, short-lived URLs for every upload and download.
  • HMAC-signed webhooks with a timestamp and an event id.
  • An audit log of every key used and every download URL issued.
07Scope

Not a review tool. It stays out of the room.

No notes, playlists, approvals or sync sessions. Tonemap feeds the tools that already do that well, and is judged on one thing: the picture that arrives is the picture you rendered.

ShotGridftrackKitsuRVcineSyncFrame.io
08Alpha

By invitation, one pipeline at a time.

Tell us what your farm writes and what your review tool reads. We set up your studio with you and send an invite bound to your address.

No newsletter. One reply, from a person who has shipped shots.