80 lines
3.4 KiB
Markdown
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).
|