aethex.live/docs/PHASE_3_CREATOR_TOOLS.md

848 lines
20 KiB
Markdown

# Phase 3: Creator Tools & VOD - Complete Implementation Guide
**Duration**: Weeks 9-13 | **Complexity**: High | **Team Size**: 3 devs
## Executive Summary
Phase 3 empowers creators with professional tools for content management. VOD archival enables creators to build libraries of content. Clip creation allows viral moments to be shared. Advanced analytics help creators understand their audience.
---
## Phase 3 Goals
### Primary Goals
1. Automatic VOD archival from live streams
2. Clip creation and sharing system
3. Advanced creator analytics dashboard
4. Stream health monitoring
5. VOD library management and playback
### Success Criteria
- 📹 100+ VODs archived
- 🎬 50+ clips created and shared
- 📊 Analytics dashboard with 10+ metrics
- 📈 95% stream uptime with health metrics
- 🎥 <2 minute clip generation time
---
## Sprint Breakdown
### Sprint 3.1: VOD Archives
**Duration**: Days 1-5 | **Team**: 2 devs
#### User Story 3.1.1: Automatic Stream Recording
```
AS A creator
I WANT my streams automatically archived
SO THAT I don't lose content and can build a VOD library
```
**Tasks**:
- [ ] Enable stream recording on Cloudflare/Mux
- [ ] Store recordings in R2 storage
- [ ] Index VODs in database
- [ ] Create VOD metadata storage
- [ ] Auto-cleanup old test recordings
**Recording Configuration**:
```typescript
// config/streaming.ts
export const recordingConfig = {
enabled: true,
minDurationMinutes: 1, // Only record streams >1 min
deleteAfterDays: 365, // Keep for 1 year
allowUserDelete: true,
storage: {
provider: 'r2', // Cloudflare R2
bucket: 'aethex-vods',
prefix: '{channelId}/{streamId}/',
},
formats: ['hls', 'mp4'], // HLS for streaming, MP4 for download
}
```
**Database Schema**:
```prisma
model VOD {
id String @id @default(cuid())
streamId String @unique
stream Stream @relation(fields: [streamId], references: [id], onDelete: Cascade)
channelId String
channel Channel @relation(fields: [channelId], references: [id], onDelete: Cascade)
title String // From stream
description String?
thumbnail String?
// Storage paths
hlsUrl String // HLS stream URL
mp4Url String? // MP4 download link
// Duration & stats
duration Int // Minutes
fileSize Int // Bytes
resolution String @default("1080p") // Max resolution
// Metadata
viewCount Int @default(0)
likeCount Int @default(0)
clipCount Int @default(0)
// Visibility
isPublic Boolean @default(true)
isDeleted Boolean @default(false)
deletedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
clips Clip[]
}
model Clip {
id String @id @default(cuid())
vodId String
vod VOD @relation(fields: [vodId], references: [id], onDelete: Cascade)
creatorId String
creator User @relation(fields: [creatorId], references: [id], onDelete: Cascade)
title String
description String?
// Trim points (in seconds from start of VOD)
startTime Int
endTime Int
duration Int // endTime - startTime
// Clip URL and metadata
clipUrl String
thumbnail String?
// Engagement
viewCount Int @default(0)
likeCount Int @default(0)
shareCount Int @default(0)
// Status
status ClipStatus @default(PROCESSING) // PROCESSING, READY, FAILED
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum ClipStatus {
PROCESSING
READY
FAILED
DELETED
}
```
**API Routes**:
- `GET /api/channels/:id/vods` - List creator's VODs
- `GET /api/vods/:id` - Get VOD details
- `PUT /api/vods/:id` - Update VOD (title, description, visibility)
- `DELETE /api/vods/:id` - Delete VOD
- `GET /api/vods/:id/comments` - VOD comments (Phase 5)
**Background Jobs**:
- Record stream when LIVE status set
- Stop recording when stream ENDED
- Generate thumbnail at 25% mark
- Index VOD metadata
**Webhook from Cloudflare/Mux**:
```typescript
// pages/api/webhooks/recording-ready.ts
export async function POST(req) {
const event = req.body
if (event.type === 'video.ready') {
// Update VOD status to READY
await db.vod.update({
where: { streamId: event.streamId },
data: {
hlsUrl: event.hlsUrl,
mp4Url: event.downloadUrl,
duration: event.duration,
}
})
}
}
```
**Deliverables**:
- [ ] Recording enabled on all streams
- [ ] VODs indexed in database
- [ ] VOD list page functional
- [ ] Webhook processing
---
#### User Story 3.1.2: VOD Playback & Library
```
AS A viewer
I WANT to watch VODs
SO THAT I can catch up on streams I missed
```
**Tasks**:
- [ ] VOD library page (`/channel/{username}/vods`)
- [ ] VOD playback player (reuse HLS player)
- [ ] VOD comments (Phase 5)
- [ ] VOD download link (optional)
- [ ] Progress tracking (watch time)
**Page Structure**:
```
/channel/[username]/vods
├── VOD List
│ ├── Grid/List toggle
│ ├── Sort: newest, trending, watched
│ ├── Filter: date range
│ └── Search VODs
├── VOD Cards
│ ├── Thumbnail
│ ├── Title
│ ├── Duration
│ ├── View count
│ ├── Upload date
│ └── Like button
└── Pagination (12 per page)
```
**VOD Playback Page**:
```
/vods/[vodId]
├── Player (full width, sticky controls)
├── Sidebar:
│ ├── VOD Info (title, date, views)
│ ├── Creator Card + Follow
│ ├── Like/Share buttons
│ └── Comments (Phase 5)
└── Related VODs (same channel)
```
**Watch Progress Tracking**:
```prisma
model WatchProgress {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
vodId String
vod VOD @relation(fields: [vodId], references: [id], onDelete: Cascade)
lastPosition Int // Seconds watched
percentage Float // 0-100
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([userId, vodId])
}
```
**API Routes**:
- `GET /api/channels/:id/vods` - List VODs
- `GET /api/vods/:id` - Get VOD details
- `POST /api/watch-progress` - Save watch progress
- `GET /api/watch-progress` - Get user's watch history
**Components**:
```
components/vod/
├── VODLibrary.tsx
├── VODGrid.tsx
├── VODCard.tsx
├── VODPlayer.tsx
├── VODInfo.tsx
├── WatchProgressBar.tsx
└── RelatedVODs.tsx
```
**Deliverables**:
- [ ] VOD library page
- [ ] VOD playback working
- [ ] Watch progress tracking
- [ ] Search/filter working
---
#### User Story 3.1.3: Watch History & Recommendations
```
AS A viewer
I WANT to access my watch history
SO THAT I can resume videos and get recommendations
```
**Tasks**:
- [ ] Watch history page
- [ ] Resume button (jump to last position)
- [ ] Clear history option
- [ ] Recommended VODs from followed creators
- [ ] "Continue Watching" section
**Routes**:
- `GET /api/watch-history` - User's watch history
- `DELETE /api/watch-history/:vodId` - Remove from history
- `POST /api/watch-history/clear` - Clear all
**Deliverables**:
- [ ] Watch history page
- [ ] Resume functionality
- [ ] Continue watching section
---
### Sprint 3.2: Clip Creation
**Duration**: Days 6-10 | **Team**: 2 devs
#### User Story 3.2.1: In-Stream Clip Button
```
AS A viewer
I WANT to create clips while watching
SO THAT I can share viral moments with others
```
**Tasks**:
- [ ] Add clip button to stream player
- [ ] Auto-capture last 30 seconds (configurable)
- [ ] Show clip creation feedback
- [ ] Redirect to clip editor after creation
- [ ] Display creation status
**Clip Capture Logic**:
```typescript
// When user clicks clip button
const clipStream = async (streamId: string) => {
const now = Date.now()
// Clip last 30 seconds of HLS stream
const clipData = {
vodId: streamId, // Use stream as VOD
startTime: Math.max(0, currentPlaybackPosition - 30),
endTime: currentPlaybackPosition,
title: `Clip from ${creatorName}'s stream`,
}
// Queue clip generation job
await fetch('/api/clips', {
method: 'POST',
body: JSON.stringify(clipData)
})
}
```
**Deliverables**:
- [ ] Clip button visible on stream player
- [ ] Clip auto-capture working
- [ ] User feedback on clip creation
---
#### User Story 3.2.2: Clip Editor
```
AS A creator
I WANT to edit and publish clips
SO THAT I can curate my best moments
```
**Tasks**:
- [ ] Build clip editor page (`/clips/[clipId]/edit`)
- [ ] Timeline with trim handles
- [ ] Preview scrubber
- [ ] Title/description editor
- [ ] Thumbnail editor (select frame)
- [ ] One-click publish to Twitter/TikTok (Phase 3B)
**Page Structure**:
```
/clips/[clipId]/edit
├── Video Preview
│ ├── Timeline (full VOD)
│ ├── Clip section highlighted
│ ├── Trim handles (drag to adjust)
│ └── Play button
├── Edit Panel
│ ├── Title input
│ ├── Description textarea
│ ├── Thumbnail selector (frame picker)
│ ├── Tags input (Phase 2B)
│ └── Visibility toggle
└── Publish Action
├── Preview button
├── Save draft button
└── Publish button
```
**Components**:
```
components/clips/
├── ClipEditor.tsx
├── ClipTimeline.tsx
├── TrimHandles.tsx
├── FrameSelector.tsx
├── PreviewPlayer.tsx
└── PublishPanel.tsx
```
**API Routes**:
- `PUT /api/clips/:id` - Update clip metadata
- `POST /api/clips/:id/generate` - Generate clip video
- `POST /api/clips/:id/publish` - Publish clip
- `POST /api/clips/:id/thumbnail` - Update thumbnail
**Background Job**:
- FFmpeg or Cloudflare Stream API to cut video segment
- Generate MP4 and thumbnail
- Upload to R2
- Update clip status to READY
**Deliverables**:
- [ ] Clip editor page
- [ ] Trim functionality
- [ ] Preview working
- [ ] Publish button functional
---
#### User Story 3.2.3: Clip Sharing & Discovery
```
AS A creator
I WANT my clips shared widely
SO THAT I grow my audience
```
**Tasks**:
- [ ] Clip sharing page (`/clips/:id`)
- [ ] Social media share buttons
- [ ] Embed code for websites
- [ ] Clip analytics
- [ ] Trending clips section
**Clip Page Structure**:
```
/clips/[clipId]
├── Header: Clip title + creator
├── Video Player
├── Share Buttons (Twitter, TikTok, Discord, etc)
├── Embed Code (iframe)
├── Stats (views, likes, shares, datetime)
├── Creator Card + Channel Link
├── Comments (Phase 5)
└── Related Clips (trending from channel)
```
**Routes**:
- `GET /api/clips/trending` - Trending clips
- `GET /api/clips/:id/stats` - Clip analytics
- `GET /api/channels/:id/clips` - Creator's clips
- `POST /api/clips/:id/like` - Like clip (Phase 5)
**Deliverables**:
- [ ] Clip sharing page
- [ ] Share buttons working
- [ ] Trending clips showing
- [ ] Embed working
---
### Sprint 3.3: Advanced Analytics
**Duration**: Days 11-15 | **Team**: 2 devs
#### User Story 3.3.1: Analytics Dashboard
```
AS A creator
I WANT detailed analytics
SO THAT I can understand and grow my audience
```
**Tasks**:
- [ ] Build analytics dashboard (`/dashboard/analytics`)
- [ ] Implement data collection
- [ ] Graphs and charts
- [ ] Filter by date range
- [ ] Export analytics (CSV)
**Analytics Metrics**:
*Stream-level*:
- Stream duration
- Peak concurrent viewers
- Average viewers
- Total views
- Chat messages
- Follow gains
- Conversion rate (viewers followers)
*Channel-level*:
- Total hours streamed
- Total views (all time)
- Average peak viewers
- Growth (weekly/monthly)
- Most watched category
- Best performing streams
- Top clips
**Database Schema**:
```prisma
model StreamAnalytics {
id String @id @default(cuid())
streamId String @unique
stream Stream @relation(fields: [streamId], references: [id], onDelete: Cascade)
// Viewers
peakConcurrent Int
avgConcurrent Int
uniqueViewers Int
totalWatchMinutes Int
// Engagement
chatMessages Int
newFollowers Int
conversionRate Float // followers gained / unique viewers
// VOD
vodViews Int @default(0)
vodEngagement Float @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model ViewCountSnapshot {
id String @id @default(cuid())
streamId String
stream Stream @relation(fields: [streamId], references: [id], onDelete: Cascade)
viewCount Int
timestamp DateTime
@@index([streamId, timestamp])
}
```
**Chart Components** (using Recharts or Chart.js):
```
components/analytics/
├── AnalyticsDashboard.tsx
├── ViewersOverTime.tsx
├── PeakViewersChart.tsx
├── EngagementChart.tsx
├── TopStreamsTable.tsx
├── ChannelGrowthChart.tsx
└── ConversionRateMetric.tsx
```
**API Routes**:
- `GET /api/analytics/streams/:id` - Stream analytics
- `GET /api/analytics/channels/:id` - Channel analytics
- `GET /api/analytics/charts/viewers` - Viewer count time series
- `POST /api/analytics/export` - CSV export
**Data Collection**:
```typescript
// Collect viewer count every minute
setInterval(async () => {
const activeStreams = await db.stream.findMany({
where: { status: 'LIVE' }
})
for (let stream of activeStreams) {
await db.viewCountSnapshot.create({
data: {
streamId: stream.id,
viewCount: stream.viewerCount,
timestamp: new Date(),
}
})
}
}, 60000)
```
**Deliverables**:
- [ ] Analytics dashboard built
- [ ] Charts displaying correctly
- [ ] Data collection working
- [ ] Date range filtering
---
#### User Story 3.3.2: Stream Health Monitoring
```
AS A creator
I WANT to see stream health metrics
SO THAT I can fix quality issues during live streaming
```
**Tasks**:
- [ ] Display bitrate, FPS, resolution
- [ ] Connection quality indicator
- [ ] Bitrate graph
- [ ] Issue alerts (bitrate drop, connection loss)
- [ ] Guide to fix issues
**Metrics**:
```typescript
interface StreamHealth {
uptime: number // % uptime
bitrate: number // Kbps
fps: number // Frames per second
resolution: string // 1920x1080
latency: number // ms from ingest to edge
packetLoss: number // % packets lost
bufferingEvents: number // Number of times player buffered
}
```
**Dashboard Widget**:
```
Stream Health Status
├── Connection: Excellent (green indicator)
├── Bitrate: 5000 kbps (target 5500) [graph]
├── FPS: 60 [icon good]
├── Resolution: 1920x1080
├── Latency: 1.2s (acceptable range)
└── Alerts: None
```
**Real-time Updates** (via WebSocket):
```typescript
socket.on('stream:health-update', (health) => {
updateHealthMetrics(health)
})
```
**Deliverables**:
- [ ] Health metrics displayed correctly
- [ ] Real-time updates working
- [ ] Alerts triggering
- [ ] Helpful tooltips
---
#### User Story 3.3.3: VOD & Clip Analytics
```
AS A creator
I WANT to see how my VODs and clips perform
SO THAT I can create more of the best content
```
**Tasks**:
- [ ] VOD view count tracking
- [ ] Clip performance metrics
- [ ] Trending clips dashboard
- [ ] Best performing content
**Metrics**:
- VOD views, engagement, average watch time
- Clip views, likes, shares, embeds
- Which streams generate most clips
- Which clips drive most traffic back to channel
**API Routes**:
- `GET /api/vods/:id/analytics`
- `GET /api/clips/:id/analytics`
- `GET /api/channels/:id/top-vods`
- `GET /api/channels/:id/top-clips`
**Deliverables**:
- [ ] VOD analytics working
- [ ] Clip analytics showing
- [ ] Top content identified
---
### Sprint 3.4: Polish & Optimization
**Duration**: Days 16-20 | **Team**: 2 devs
#### Performance Optimization
- [ ] Optimize analytics queries (database indexes)
- [ ] Cache analytics data (Redis)
- [ ] Lazy load charts
- [ ] Implement pagination on clip lists
#### Mobile Responsiveness
- [ ] Mobile VOD player
- [ ] Mobile analytics dashboard
- [ ] Mobile clip editor
- [ ] Touch-friendly controls
#### Testing
- [ ] Unit tests for analytics calculations
- [ ] E2E tests: record stream VOD created viewable
- [ ] Clip creation and playback tests
- [ ] Analytics accuracy validation
---
## Database Schema - Phase 3 Updates
**New Models**:
```prisma
model VOD { /* ... */ }
model Clip { /* ... */ }
model StreamAnalytics { /* ... */ }
model ViewCountSnapshot { /* ... */ }
model WatchProgress { /* ... */ }
```
**Updated Models**:
```prisma
model Stream {
// Add VOD relation
vod VOD?
}
model Channel {
// Add VOD and clip relations
vods VOD[]
}
model User {
// Add clip relation
clips Clip[]
}
```
---
## API Routes - Phase 3 Additions
### VODs
- `GET /api/channels/:id/vods`
- `GET /api/vods/:id`
- `PUT /api/vods/:id`
- `DELETE /api/vods/:id`
- `POST /api/watch-progress`
- `GET /api/watch-progress`
### Clips
- `POST /api/clips` (create from stream/VOD)
- `GET /api/clips/:id`
- `PUT /api/clips/:id`
- `DELETE /api/clips/:id`
- `POST /api/clips/:id/generate`
- `GET /api/clips/trending`
- `GET /api/channels/:id/clips`
### Analytics
- `GET /api/analytics/streams/:id`
- `GET /api/analytics/channels/:id`
- `GET /api/analytics/charts/viewers`
- `POST /api/analytics/export`
---
## Components - Phase 3 Additions
### VOD
```
components/vod/
├── VODLibrary.tsx
├── VODCard.tsx
├── VODPlayer.tsx
└── WatchProgressBar.tsx
```
### Clips
```
components/clips/
├── ClipEditor.tsx
├── ClipTimeline.tsx
├── TrimHandles.tsx
├── ClipCard.tsx
└── TrendingClips.tsx
```
### Analytics
```
components/analytics/
├── AnalyticsDashboard.tsx
├── ViewersChart.tsx
├── EngagementChart.tsx
├── StreamHealth.tsx
└── TopContentTable.tsx
```
---
## Third-Party Services
### Video Processing
- **Cloudflare Stream or Mux**: Recording/clipping
- **FFmpeg** (self-hosted): Optional for additional processing
### Charts
- **Recharts** or **Chart.js**: Graphing library
### Storage
- **Cloudflare R2**: VOD and clip storage (already in Phase 1)
---
## Success Metrics
### VOD Metrics
- [ ] 100+ VODs created
- [ ] 50k+ total VOD views
- [ ] 10+ min average VOD watch time
- [ ] 30% VOD engagement rate
### Clip Metrics
- [ ] 50+ clips created
- [ ] 10k+ total clip views
- [ ] 5% of viewers create clips
- [ ] 100+ clips shared to social media
### Analytics Metrics
- [ ] 90%+ creators use analytics dashboard
- [ ] Charts load in <2s
- [ ] 0 analytics data loss
- [ ] Trending clips updated hourly
### Performance Metrics
- [ ] VOD playback <2s latency
- [ ] Clip generation <2 minutes
- [ ] Analytics queries <1s
- [ ] Database stays <100GB
---
---
## Phase 3 Timeline
| Week | Sprint | Focus |
|------|--------|-------|
| 9 | 3.1 | VOD archival & playback |
| 10 | 3.2 | Clip creation & editing |
| 11 | 3.3 | Advanced analytics |
| 12-13 | 3.4 | Polish & optimization |
---
## Phase 3 Completion Checklist
- [ ] VOD archival working automatically
- [ ] VOD playback page functional
- [ ] Clip creation from stream working
- [ ] Clip editor with trim working
- [ ] Clip sharing page built
- [ ] Analytics dashboard showing data
- [ ] Stream health metrics displaying
- [ ] Mobile responsive
- [ ] Performance optimized
- [ ] Tests passing
- [ ] Deployed to production
- [ ] 100+ VODs archived
- [ ] 50+ clips created
---
**Phase 3 Estimated Completion**: Week 13 (by April 18, 2025)
**Next Phase**: Phase 4 - Monetization (April 21, 2025)
See [PHASE_4_MONETIZATION.md](PHASE_4_MONETIZATION.md) for Phase 4 details.