> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sertifikasitrainer.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Alur video (Mux)

> Upload, transcode, signed playback, dan progress peserta.

Video kelas di-host di **Mux** dengan policy **signed** — browser tidak bisa play tanpa JWT dari API.

## Tipe video per lesson

| `videoType`    | Sumber                              | Playback                  |
| -------------- | ----------------------------------- | ------------------------- |
| `mux`          | Upload langsung / import URL ke Mux | Mux Player + signed token |
| `youtube`      | URL YouTube                         | Embed / link              |
| `google-drive` | Link Drive                          | External                  |
| `external`     | URL lain                            | External                  |

Production utama: **Mux** (kualitas, analytics, thumbnail).

## Alur upload Mux (admin)

```mermaid theme={null}
sequenceDiagram
  participant Admin as Admin UI
  participant API as KelasService
  participant Mux as Mux API
  participant DB as lessons table

  Admin->>API: POST create-mux-upload (lessonId)
  API->>Mux: createDirectUpload(corsOrigin)
  Mux-->>API: uploadId + uploadUrl
  API->>DB: muxUploadId, videoType=mux
  API-->>Admin: URL upload untuk browser
  Admin->>Mux: PUT file video (direct upload)
  Admin->>API: poll GET mux-status
  API->>Mux: getUploadStatus / getAsset
  Mux-->>API: assetId, playbackId, duration
  API->>DB: muxAssetId, muxPlaybackId, thumbnailUrl
```

### Alternatif: import dari URL

`POST import-mux-from-url` — Mux pull video dari URL publik (YouTube file, CDN, dll.) tanpa upload manual.

### Admin: daftar asset

`GET /api/kelas/mux/list-all` — semua asset di akun Mux (admin only).\
UI: `views/admin/MuxVideoList.tsx`

## Alur playback (peserta)

```mermaid theme={null}
sequenceDiagram
  participant P as Peserta
  participant Web as MuxPlayer
  participant API as KelasService
  participant Mux as stream.mux.com

  P->>Web: Buka lesson video
  Web->>API: GET /kelas/lessons/:id/playback-token
  API->>API: Cek enrollment → course access
  API->>API: signMuxJwt(playbackId, type=v)
  API-->>Web: token + thumbnailToken (TTL 1 jam)
  Web->>Mux: HLS ?token=JWT
  Mux-->>P: Stream video
  Web->>API: PATCH progress videoProgress
```

Frontend: `@mux/mux-player-react` di halaman kelas (`views/kelas/`).

### Signing keys

JWT ditandatangani dengan key di env:

* `MUX_SIGNING_KEY_ID` / `MUX_SIGNING_KEY_PRIVATE_KEY_PKCS8`
* Per lesson disimpan `muxSigningKeyId` (untuk rotasi key)

Kode: `apps/api/src/mux/mux-signing.ts`, `mux.service.ts`

## Status asset

| Status Mux              | Arti di UI                       |
| ----------------------- | -------------------------------- |
| `waiting` / `uploading` | Masih proses upload              |
| `preparing`             | Transcode                        |
| `ready`                 | Bisa play; `playbackId` tersedia |
| `errored`               | Upload gagal — cek Mux dashboard |

Polling: `getMuxStatus(lessonId)` di `KelasService`.

## Hapus video

`deleteMuxAsset` — hapus di Mux + reset field lesson ke `videoType: youtube`.

## Keamanan

<Warning>
  Tanpa enrollment **paid** ke course yang berisi lesson, API menolak:

  * detail course
  * playback token
  * update progress
</Warning>

## Setup Mux

Tutorial API key & signing: [Mux (eksternal)](/external/mux)

## File penting

| File                  | Isi                             |
| --------------------- | ------------------------------- |
| `kelas.service.ts`    | Upload, status, token, progress |
| `kelas.routes.ts`     | HTTP endpoints                  |
| `kelas.repository.ts` | Query course/chapter/lesson     |
| `mux.service.ts`      | Client Mux API                  |
