Video Streaming

HLS adaptive bitrate streaming with multi-quality transcoding.

Transcode Pipeline

After a video upload is confirmed, MediaKit automatically:

  1. Probes the source file for resolution, duration, codec info
  2. Determines which quality tiers fit (no upscaling — a 480p source won't get a 1080p rendition)
  3. Runs FFmpeg to create HLS segments for each quality
  4. Generates a master playlist (master.m3u8) that references all qualities
  5. Generates sprite sheet for hover previews
  6. Extracts a thumbnail from the middle of the video
  7. Updates the asset status to "ready"

Quality Tiers

LabelResolutionBitrateCodec
360p640×360800 kbpsH.264
480p854×4801400 kbpsH.264
720p1280×7202800 kbpsH.264
1080p1920×10805000 kbpsH.264

Playback Info

bash
curl /api/mediakit/videos/1/playback
Response
{
  "data": {
    "id": 1,
    "title": "My Video",
    "hls_url": "https://r2.../videos/1/master.m3u8",
    "mp4_url": "https://r2.../uploads/abc/video.mp4",
    "thumbnail_url": "https://r2.../videos/1/thumbnail.jpg",
    "sprite_url": "https://r2.../videos/1/sprites/sprite.jpg",
    "sprite_vtt_url": "https://r2.../videos/1/sprites/sprite.vtt",
    "duration": 120.5,
    "width": 1920,
    "height": 1080,
    "aspect_ratio": "16:9",
    "transcode_status": "ready",
    "qualities": [
      { "label": "360p", "width": 640, "height": 360, "bitrate": 800000 },
      { "label": "720p", "width": 1280, "height": 720, "bitrate": 2800000 },
      { "label": "1080p", "width": 1920, "height": 1080, "bitrate": 5000000 }
    ],
    "chapters": [
      { "title": "Introduction", "start_time": 0 },
      { "title": "Main Content", "start_time": 15 }
    ]
  }
}

Transcode Progress (SSE)

Monitor transcode progress in real-time via Server-Sent Events:

javascript
const evtSource = new EventSource(
  "/api/mediakit/videos/1/progress"
);

evtSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log(`Progress: ${data.percent}%`);
  // data.percent, data.stage, data.eta
};

evtSource.addEventListener("done", () => {
  evtSource.close();
  console.log("Transcode complete!");
});

Playing HLS in the Browser

Use HLS.js for non-Safari browsers:

html
<video id="player" controls></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script>
  const video = document.getElementById('player');
  const hlsUrl = 'https://your-api.com/api/mediakit/videos/1/playback';

  fetch(hlsUrl)
    .then(r => r.json())
    .then(({ data }) => {
      if (Hls.isSupported()) {
        const hls = new Hls();
        hls.loadSource(data.hls_url);
        hls.attachMedia(video);
      } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
        video.src = data.hls_url; // Safari native HLS
      }
    });
</script>

Retranscode

bash
curl -X POST /api/mediakit/videos/1/retranscode \
  -H "Authorization: Bearer TOKEN"

Re-enqueues the transcode job. Useful if a video failed due to temporary issues.

Sprite Hover Previews

MediaKit generates a sprite sheet (horizontal strip of frames) and a WebVTT file that maps timestamps to sprite regions. Video players like Plyr.io can use this for thumbnail previews when hovering over the progress bar.

The sprite URL and VTT URL are included in the playback response.