# AIOZ Stream — Media (Video)

SDK package: @aiozstream/nodejs-client

## Setup

```typescript
import StreamClient from '@aiozstream/nodejs-client'

const client = new StreamClient({
  publicKey: process.env.AIOZ_PUBLIC_KEY,
  secretKey: process.env.AIOZ_SECRET_KEY
})
```

---

## Create Video Object

POST https://api.aiozstream.network/api/media/create

```typescript
const video = await client.video.create({
  title: 'My Video',
  type: 'video',              // required, must be 'video'
  description: 'optional',
  isPublic: true,
  tags: ['tag1'],
  metadata: [{ key: 'genre', value: 'tech' }],
  qualities: [
    {
      resolution: '720p',     // '240p'|'360p'|'480p'|'720p'|'1080p'|'1440p'|'2160p'|'4320p'
      type: 'hls',            // 'hls' | 'dash'
      containerType: 'mpegts', // hls: 'mpegts'|'mp4'; dash: 'fmp4'
      videoConfig: {
        codec: 'h264',        // 'h264' | 'h265'
        bitrate: 3000000,
        index: 0
      },
      audioConfig: {
        codec: 'aac',
        bitrate: 128000,
        channels: '2',
        sampleRate: 44100,
        language: 'en',
        index: 0
      }
    }
  ]
})
const videoId = video.data.id
```

Video resolution bitrate limits:
- 240p → max 700,000 bps
- 360p → max 1,200,000 bps
- 480p → max 2,000,000 bps
- 720p → max 4,000,000 bps
- 1080p → max 6,000,000 bps
- 1440p → max 12,000,000 bps
- 2160p → max 30,000,000 bps
- 4320p → max 60,000,000 bps

---

## Upload Video File

```typescript
// Upload file in parts (handles chunking automatically)
await client.video.uploadPart(videoId, './path/to/video.mp4')

// Mark upload as complete
const result = await client.video.uploadVideoComplete(videoId)
console.log(result.data.status) // 'encoding' -> eventually 'done'
```

---

## Full Upload Flow

```typescript
// 1. Create video object
const video = await client.video.create({ title: 'My Video', type: 'video' })
const videoId = video.data.id

// 2. Upload file
await client.video.uploadPart(videoId, './video.mp4')

// 3. Finalize
await client.video.uploadVideoComplete(videoId)

// 4. Poll for encoding completion
let status = 'encoding'
while (status !== 'done' && status !== 'failed') {
  await new Promise(r => setTimeout(r, 5000))
  const detail = await client.video.getDetail(videoId)
  status = detail.data.status
}

// 5. Get playback URL
const detail = await client.video.getDetail(videoId)
console.log(detail.data.assets.hlsUrl)   // HLS playback
console.log(detail.data.assets.dashUrl)  // DASH playback
console.log(detail.data.assets.mp4Url)   // MP4 download
```

---

## Get Video Detail

GET https://api.aiozstream.network/api/media/{id}

```typescript
const video = await client.video.getDetail(videoId)
// video.data.assets.hlsUrl, dashUrl, mp4Url, thumbnailUrl
// video.data.status: 'created'|'encoding'|'done'|'failed'
// video.data.duration (seconds), video.data.size (bytes)
```

---

## List Videos

POST https://api.aiozstream.network/api/media

```typescript
const result = await client.video.getVideoList({
  offset: 0,
  limit: 25,
  sortBy: 'created_at',
  orderBy: 'desc',
  search: 'keyword'
})
console.log(result.data.videos)
console.log(result.data.total)
```

---

## Update Video

PATCH https://api.aiozstream.network/api/media/{id}

```typescript
await client.video.update(videoId, {
  title: 'New Title',
  description: 'Updated description',
  isPublic: false,
  tags: ['updated'],
  metadata: [{ key: 'key', value: 'value' }]
})
```

---

## Delete Video

DELETE https://api.aiozstream.network/api/media/{id}

```typescript
await client.video.delete(videoId)
```

---

## Upload Thumbnail

POST https://api.aiozstream.network/api/media/{id}/thumbnail

```typescript
await client.video.uploadThumbnail(videoId, './thumbnail.jpg')
```

---

## Delete Thumbnail

DELETE https://api.aiozstream.network/api/media/{id}/thumbnail

```typescript
await client.video.deleteThumbnail(videoId)
```

---

## Get Transcoding Cost

GET https://api.aiozstream.network/api/media/cost

```typescript
const cost = await client.video.getCost()
```
