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

80 lines
3.4 KiB
Markdown

# 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**:
```bash
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).