mono/packages/ui/docs/m3u8.md
2026-02-08 15:09:32 +01:00

3.4 KiB

HLS (m3u8) Implementation Plan

Objective

Transition internal video processing and serving from single MP4 files to HLS (HTTP Live Streaming) to improve playback performance, seekability, and support adaptive bitrate streaming.

Technical Changes

1. Video Processing (Worker)

File: server/src/products/videos/worker.ts

Current: Generates single jobId.mp4. New: Generate HLS playlist and segments.

FFmpeg Command:

ffmpeg -i input.mp4 \
  -b:v 1M \
  -g 60 \
  -hls_time 2 \
  -hls_list_size 0 \
  -hls_segment_size 500000 \
  output.m3u8

Storage Structure: Instead of flat files in videos/, use a directory per job:

videos/
  ├── [jobId]/
  │   ├── playlist.m3u8
  │   ├── output0.ts
  │   ├── output1.ts
  │   └── ...

2. API Endpoints (Product)

File: server/src/products/videos/routes.ts & index.ts

Create new endpoints to serve HLS assets. We need to serve both the playlist (.m3u8) and the segment files (.ts).

Endpoints:

  1. Playlist: GET /api/videos/jobs/:id/hls/playlist.m3u8

    • Handler: Looks up directory videos/:id/, serves playlist.m3u8.
    • Content-Type: application/vnd.apple.mpegurl or application/x-mpegURL.
  2. Segments: GET /api/videos/jobs/:id/hls/:segment

    • Handler: Looks up directory videos/:id/, serves requested .ts file.
    • Content-Type: video/MP2T.

Note: The playlist generated by ffmpeg usually contains relative paths (e.g., output0.ts). If the browser loads the playlist from .../hls/playlist.m3u8, it will resolve segments relative to that base, .../hls/output0.ts, which fits the proposed endpoint structure perfectly.

3. Frontend (Playground & Components)

File: src/pages/VideoPlayerPlaygroundIntern.tsx

  • Update pollJob or handleUpload completion logic.
  • Instead of setting videoUrl to the MP4 download link, set it to the HLS playlist endpoint:
    • http://localhost:3333/api/videos/jobs/[jobId]/hls/playlist.m3u8
  • Pass type application/x-mpegurl (or application/vnd.apple.mpegurl) to VideoCard.

File: src/components/VideoCard.tsx

  • Ensure Vidstack / MediaPlayer handles the HLS mime type correctly. Vidstack has built-in HLS support (often requires hls.js but it's usually bundled or easily added).
  • Verify src prop handling for HLS.

4. Database / Metadata

  • Update resultUrl in the job completion data (in pg-boss or returned to frontend) to point to the .m3u8 file.
  • Supabase pictures table: Update image_url to store the HLS playlist URL instead of the MP4 download URL.

Migration Strategy

  1. Implement new Worker logic: Create a new job name or update existing video-processing to output HLS.
  2. Implement new Endpoints: Add HLS routes to VideosProduct.
  3. Update Frontend: Point playground to new endpoints.
  4. Verify: Test playback.
  5. Cleanup: Remove MP4 download endpoint and old worker logic once verified.

Outstanding Questions

  • Storage Cleanup: Deleting a video now means deleting a directory. Ensure handleDelete is updated.
  • Legacy Content: Old MP4s will stop working if we aggressively remove the old endpoint.
    • Decision: Keep the old download endpoint for backward compatibility if needed, or migration script to convert old videos (out of scope for now).