// video infrastructure for people who ship

Upload once.
Stream everywhere.

TRANSCODMAX turns any source video into an adaptive HLS ladder — 360p / 720p / 1080p renditions behind a single master.m3u8 — ready for any player, on any connection. Dashboard or REST API. Your call.

client@transcodmax:~

                    

3-rung

360p → 1080p ladder

2 GB

max source size

6s

segments, keyframe-aligned

H.264

main profile · veryfast · AAC

60/min

API rate limit per token

$ pipeline_status

workers idle · ready for input

No jobs have hit this deployment yet. The first upload gets probed, encoded into up to 3 renditions and published behind a master playlist — live counters for ingested jobs, delivered ladders and processed footage appear here as soon as the pipeline runs.

Be job #1 »

// the pipeline

Three stages. No hand-waving.

01

Ingest

Push a source through the dashboard or POST /api/v1/jobs. Uploads are validated by sniffed mimetype — not file extension — and capped at 2048 MB. Sources land on a private disk, immutable from the moment they arrive.

→ 202 Accepted
{ "id": 42, "status": "queued" }

02

Transcode

A supervised worker probes the source with ffprobe, then runs an x264 encode per rendition — veryfast preset, main profile, keyframes forced onto segment boundaries so players switch bitrates cleanly. Progress streams to the job record from 0 to 100. Sources are never upscaled: a 720p master gets a 720p ceiling.

status   processing
progress ██████████░░░░░░ 63%

03

Deliver

One master.m3u8 advertises every variant with BANDWIDTH and RESOLUTION; each rendition ships its own VOD playlist and 6-second .ts segments. Serve from local storage in dev, or point the output disk at S3/R2 behind a CDN — output is write-once, so long cache TTLs are free.

#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=3220801,
  RESOLUTION=1280x720
720p/index.m3u8

// the ladder

Every job, the same contract.

Current encode targets, straight from the platform config. Renditions taller than the source are skipped — the ladder adapts down, never fakes up.

Rendition Video Audio Codec Container
360p 800kbps · 360p AAC 96kbps stereo H.264 main / veryfast HLS VOD · 6s .ts
720p 2800kbps · 720p AAC 128kbps stereo H.264 main / veryfast HLS VOD · 6s .ts
1080p 5000kbps · 1080p AAC 192kbps stereo H.264 main / veryfast HLS VOD · 6s .ts

// playback

Standard HLS. Plays on everything.

Output is plain HLS v3 — MPEG-TS segments and VOD playlists. No SDK, no proprietary manifest, no player lock-in. Hand the master URL to whatever you already ship with.

Safari / iOS / tvOS

Native. Point <video src> at master.m3u8 and AVPlayer handles bitrate switching itself.

hls.js / video.js / Plyr

Chrome, Firefox, Edge via Media Source Extensions. Our own job pages use hls.js — nothing special about the manifest.

ExoPlayer / Media3

Android's default player consumes the master playlist directly; adaptive track selection works out of the box.

Smart TVs & set-tops

H.264 main profile + AAC is the lowest common denominator on purpose — Roku, Tizen, webOS and Chromecast all decode it in hardware.

$ embed_minimal

<video id="v" controls playsinline></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<script>
  const v = document.getElementById('v');
  const src = '.../transcodes/42/master.m3u8';
  if (Hls.isSupported()) {
    const h = new Hls(); h.loadSource(src); h.attachMedia(v);
  } else {
    v.src = src; // Safari: native HLS
  }
</script>

$ what_you_get

transcodes/42/
├── master.m3u8
├── 360p/
│   ├── index.m3u8
│   └── segment_000.ts … segment_NNN.ts
├── 720p/
│   ├── index.m3u8
│   └── segment_000.ts … segment_NNN.ts
├── 1080p/
│   ├── index.m3u8
│   └── segment_000.ts … segment_NNN.ts

Every file is immutable once written. Put a CDN in front with a year-long TTL — a completed job never changes, so there's nothing to invalidate.

// built for

Anywhere a video needs to become a stream.

Course & LMS platforms

Lecture uploads arrive as 4 GB screen recordings. Hand them to the API on upload, store the playlist URL on the lesson, and students on hotel wifi still get the 360p rung instead of a spinner.

UGC & community apps

Phone footage comes in every codec, rotation and resolution. ffprobe normalises it; the ladder never upscales, so a vertical 720p clip stays honest. Poll GET /jobs/{id} and flip the post to "ready" at 100%.

Internal video & archives

Town-halls, trainings, product demos. Keep the ProRes master on the private source disk, serve the ladder from object storage, and stop emailing 2 GB .mov files around.

// spec sheet

The numbers, as configured on this deployment.

Input Any real video mimetype (sniffed) · up to 2 GB
Source analysis ffprobe · streams + format · stored on the job record
Video codec H.264 / libx264 · main profile · preset veryfast
Rate control ABR per rung · maxrate 107% · bufsize 2× bitrate
Audio AAC-LC stereo · 96k / 128k / 192k
Ladder 360p @ 800k · 720p @ 2800k · 1080p @ 5000k
Upscaling Never — rungs taller than the source are dropped
Segments 6s MPEG-TS · forced keyframe on every boundary · scene-cut off
Playlists HLS v3 VOD · master advertises BANDWIDTH + RESOLUTION per variant
Job limits Single attempt · 2h hard timeout per job · progress 0–100 live
Storage Private source disk · public output disk (local, S3 or R2)
API Bearer token · 60 req/min · JSON · 202 on accept, 422 on bad input

// the api

Three endpoints. Bearer token. Done.

POST /api/v1/jobs

Multipart upload (video=@file). Returns 202 with the queued job.

GET /api/v1/jobs

Paginated list of your jobs, newest first. Strictly scoped to your account.

GET /api/v1/jobs/{id}

Poll a single job for status, progress and the playlist URL.

401 unknown token · 403 account_pending / not your job · 422 not a video or over 2048 MB

$ sample_session

$ curl -H "Authorization: Bearer sk_live_..." \
       -F "video=@launch-teaser.mov" \
       https://transcodmax.on-forge.com/api/v1/jobs

HTTP/1.1 202 Accepted
{
  "data": {
    "id": 42,
    "status": "queued",
    "progress": 0,
    "original": "launch-teaser.mov",
    "playlist_url": null,
    "error": null
  }
}

$ curl -H "Authorization: Bearer sk_live_..." \
       https://transcodmax.on-forge.com/api/v1/jobs/42

HTTP/1.1 200 OK
{
  "data": {
    "id": 42,
    "status": "completed",
    "progress": 100,
    "playlist_url": ".../transcodes/42/master.m3u8"
  }
}

// getting access

Operator-approved onboarding.

Register, and your account starts in pending state — you can log in and explore, but transcoding stays locked until an operator activates the account. Approval issues your sk_live_ API token and unlocks uploads instantly.

Waiting on activation? Write to support@trancodmax.com.

Create an account »
What formats can I upload?

Anything with a real video mimetype — mp4, mov, mkv, webm, avi, mpeg and friends. Content is sniffed server-side; renaming a .zip to .mp4 gets you a 422.

Do you upscale low-res sources?

Never. Renditions taller than your source are dropped from the ladder. A 480p source produces a single honest 360p rung, not a blurry fake 1080p.

Where does my output live?

On the platform's output disk — local storage in development, S3/R2 behind a CDN in production. Playlists and segments are write-once and never mutated.

What happens when an encode fails?

The job is marked failed and the raw ffmpeg stderr is captured on the record — visible on the job page and in the API — so you can see exactly what the encoder choked on.

// ready when you are

Feed the pipeline_