sysrot-hub
Version:
CLI de nueva generaciΓ³n para proyectos Next.js 14+ con IA multi-modelo, Web3 integration, internacionalizaciΓ³n completa y roadmap realista 2025-2026
982 lines (839 loc) β’ 26.4 kB
Markdown
# πΊ Video Streaming Platform
A comprehensive video streaming and media platform with multi-channel support, video transcoding, analytics, and monetization features. Built for content creators and viewers with enterprise-level capabilities.
## π Quick Start
### Prerequisites
- Node.js 18+
- PostgreSQL database
- Video storage service (Cloudinary, AWS S3, etc.)
- FFmpeg for video processing (optional)
### Setup
1. **Install dependencies**
```bash
npm install
```
2. **Configure environment variables**
```bash
# Add to your .env.local
DATABASE_URL="postgresql://user:password@localhost:5432/videosdb"
NEXTAUTH_SECRET="your-secret-key"
NEXTAUTH_URL="http://localhost:3000"
# Video storage and processing
CLOUDINARY_CLOUD_NAME="your-cloud-name"
CLOUDINARY_API_KEY="your-api-key"
CLOUDINARY_API_SECRET="your-api-secret"
# Optional: Video transcoding
FFMPEG_PATH="/usr/local/bin/ffmpeg"
VIDEO_PROCESSING_WEBHOOK="http://localhost:3000/api/webhooks/video-processing"
# Optional: Analytics
GOOGLE_ANALYTICS_ID="GA-MEASUREMENT-ID"
```
3. **Setup database and seed**
```bash
npm run setup:videos
```
4. **Start development server**
```bash
npm run dev
```
5. **Access video platform**
Navigate to `http://localhost:3000/videos`
## π Test Credentials
| Email | Password | Channel | Subscribers | Content Focus |
|-------|----------|---------|-------------|---------------|
| techguru@creators.com | video123 | Tech Tutorials Pro | 125K | Programming & Web Dev |
| gamequeen@creators.com | video123 | Gaming Central Hub | 89K | Gaming & Esports |
| cookmaster@creators.com | video123 | Chef Secrets Kitchen | 45K | Cooking & Recipes |
| fitnesscoach@creators.com | video123 | Fitness Revolution | 67K | Workouts & Wellness |
| musicproducer@creators.com | video123 | Beats Studio Official | 34K | Music Production |
| artcreator@creators.com | video123 | Art Masterclass Studio | 28K | Digital Art |
| viewer1@watchers.com | video123 | - | - | Active Video Viewer |
| viewer2@watchers.com | video123 | - | - | Video Consumer |
## β¨ Features
### πΊ **Multi-Channel Platform**
- **Channel Creation**: Create unlimited channels with custom branding
- **Channel Verification**: Verified badge system for trusted creators
- **Channel Analytics**: Comprehensive analytics and insights
- **Channel Monetization**: Revenue tracking and payment integration
### π₯ **Advanced Video Management**
- **Video Upload**: Support for multiple video formats and sizes
- **Video Processing**: Automatic transcoding to multiple qualities (360p-1080p)
- **Video Metadata**: Rich metadata support with tags, categories, descriptions
- **Video Scheduling**: Schedule videos for future publication
### π **Video Transcoding System**
- **Multi-Quality Support**: 360p, 480p, 720p, 1080p, 1440p, 2160p
- **Adaptive Streaming**: Automatic quality selection based on bandwidth
- **Processing Status**: Real-time processing progress tracking
- **Quality Optimization**: Optimized bitrates for each resolution
### π₯ **Community Features**
- **Subscription System**: Follow favorite channels with notifications
- **Like/Dislike System**: Video engagement and feedback
- **Comment System**: Threaded comments with moderation tools
- **Watch History**: Personalized viewing history and progress tracking
### π **Playlist Management**
- **Custom Playlists**: Create and organize video collections
- **Collaborative Playlists**: Allow multiple users to contribute
- **Auto-Generated Playlists**: Algorithm-based recommendations
- **Playlist Analytics**: Track playlist performance and engagement
### π **Advanced Analytics**
- **Video Analytics**: Views, watch time, engagement metrics
- **Channel Analytics**: Subscriber growth, revenue tracking
- **Audience Insights**: Demographics, traffic sources, device types
- **Performance Reports**: Detailed reports with exportable data
### π΄ **Live Streaming**
- **RTMP Support**: Standard streaming protocol integration
- **HLS Delivery**: HTTP Live Streaming for broad compatibility
- **Live Chat**: Real-time chat with moderation features
- **Stream Recording**: Automatic VOD creation from live streams
### π‘οΈ **Content Moderation**
- **Report System**: Community-driven content reporting
- **Automated Moderation**: AI-powered content filtering
- **Manual Review**: Admin review workflow for reported content
- **Age Restrictions**: Content rating and access controls
## ποΈ Architecture
### Database Models
The system includes 15 comprehensive models:
```prisma
// Core video streaming models
model VideoChannel {
id String @id @default(cuid())
name String
handle String @unique
category ChannelCategory
isVerified Boolean
isMonetized Boolean
subscriberCount Int
videos Video[]
subscribers ChannelSubscription[]
analytics ChannelAnalytics[]
}
model Video {
id String @id @default(cuid())
title String
slug String @unique
videoUrl String
duration Int
status VideoStatus
visibility VideoVisibility
qualities VideoQuality[]
comments VideoComment[]
analytics VideoAnalytics[]
watchHistory WatchHistory[]
}
model VideoQuality {
id String @id @default(cuid())
quality String // 360p, 720p, 1080p, etc.
videoUrl String
fileSize Int
bitrate Int
processingStatus String
}
```
### API Structure
```
/api/channels/
βββ index.ts # Channel CRUD and subscriptions
βββ [channelId]/
β βββ videos.ts # Channel video management
β βββ analytics.ts # Channel analytics
β βββ collaborators.ts # Channel collaboration
/api/videos/
βββ index.ts # Video CRUD and interactions
βββ [videoId]/
β βββ comments.ts # Video comments
β βββ analytics.ts # Video analytics
β βββ qualities.ts # Video quality management
/api/playlists/
βββ index.ts # Playlist management
```
## π‘ API Reference
### Channels API (`/api/channels`)
#### List Channels
```javascript
GET /api/channels?category=GAMING&verified=true&sortBy=subscriberCount
Response:
{
"channels": [
{
"id": "gaming-central",
"name": "Gaming Central Hub",
"handle": "gamingcentral",
"category": "GAMING",
"isVerified": true,
"subscriberCount": 89000,
"isSubscribed": false,
"stats": {
"totalVideos": 45,
"totalViews": 1800000,
"recentVideos": 3
}
}
],
"pagination": { "page": 1, "total": 12, "pages": 1 }
}
```
#### Create Channel
```javascript
POST /api/channels
{
"name": "My Gaming Channel",
"description": "Epic gaming content and tutorials",
"handle": "mygaming",
"category": "GAMING",
"avatar": "https://example.com/avatar.jpg",
"banner": "https://example.com/banner.jpg"
}
Response:
{
"channel": {
"id": "new-channel-id",
"name": "My Gaming Channel",
"handle": "mygaming",
"subscriberCount": 1
},
"message": "Channel created successfully"
}
```
#### Subscribe to Channel
```javascript
POST /api/channels?action=subscribe
{
"channelId": "gaming-central",
"enableNotifications": true
}
Response:
{
"subscription": {
"channelId": "gaming-central",
"userId": "user-id",
"isNotificationsEnabled": true
},
"message": "Successfully subscribed to channel"
}
```
### Videos API (`/api/videos`)
#### List Videos
```javascript
GET /api/videos?category=TUTORIAL&sortBy=viewCount&limit=10
Response:
{
"videos": [
{
"id": "next-js-tutorial",
"title": "Complete Next.js 14 Tutorial",
"slug": "complete-nextjs-14-tutorial",
"duration": 3420,
"viewCount": 45600,
"likeCount": 2340,
"channel": {
"name": "Tech Tutorials Pro",
"handle": "techtutorials",
"isVerified": true
},
"qualities": [
{
"quality": "1080p",
"videoUrl": "https://video.com/1080p.mp4"
}
],
"userInteraction": {
"hasLiked": false,
"watchProgress": 1200,
"isCompleted": false
}
}
]
}
```
#### Upload Video
```javascript
POST /api/videos
{
"title": "How to Build a React App",
"description": "Complete React tutorial from beginner to advanced",
"channelId": "tech-channel-id",
"videoUrl": "https://storage.com/video.mp4",
"duration": 2400,
"fileSize": 180000000,
"category": "TUTORIAL",
"tags": ["react", "javascript", "tutorial"],
"visibility": "PUBLIC",
"thumbnail": "https://storage.com/thumb.jpg"
}
Response:
{
"video": {
"id": "new-video-id",
"title": "How to Build a React App",
"slug": "how-to-build-react-app",
"status": "PROCESSING",
"uploadProgress": 100
},
"message": "Video uploaded successfully"
}
```
#### Like/Dislike Video
```javascript
POST /api/videos?action=like
{
"videoId": "next-js-tutorial",
"isLike": true
}
Response:
{
"action": "created",
"message": "Video liked"
}
```
#### Add Comment
```javascript
POST /api/videos?action=comment
{
"videoId": "next-js-tutorial",
"content": "Great tutorial! Really helped me understand Next.js",
"parentId": "parent-comment-id" // Optional for replies
}
Response:
{
"comment": {
"id": "comment-id",
"content": "Great tutorial!",
"author": {
"name": "John Doe",
"image": "https://avatar.com/john.jpg"
},
"createdAt": "2024-01-15T14:30:00Z"
},
"message": "Comment added successfully"
}
```
#### Record Watch Progress
```javascript
POST /api/videos?action=watch
{
"videoId": "next-js-tutorial",
"watchDuration": 1200,
"lastPosition": 1200,
"quality": "720p",
"deviceType": "desktop"
}
Response:
{
"watchHistory": {
"watchedAt": "2024-01-15T15:00:00Z",
"lastPosition": 1200,
"isCompleted": false
},
"message": "Watch progress recorded"
}
```
## π¨ Frontend Integration
### Video Player Component
```jsx
import { useState, useRef, useEffect } from 'react';
function VideoPlayer({ video, onProgressUpdate }) {
const videoRef = useRef(null);
const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(0);
const [quality, setQuality] = useState('720p');
const handleTimeUpdate = () => {
const current = videoRef.current.currentTime;
setCurrentTime(current);
// Record watch progress every 30 seconds
if (Math.floor(current) % 30 === 0) {
onProgressUpdate({
watchDuration: current,
lastPosition: current,
quality,
deviceType: 'desktop'
});
}
};
const getVideoSource = (quality) => {
const videoQuality = video.qualities.find(q => q.quality === quality);
return videoQuality?.videoUrl || video.videoUrl;
};
return (
<div className="video-player">
<video
ref={videoRef}
src={getVideoSource(quality)}
onTimeUpdate={handleTimeUpdate}
onLoadedMetadata={() => setDuration(videoRef.current.duration)}
controls
className="w-full aspect-video"
>
Your browser does not support the video tag.
</video>
<div className="video-controls">
<div className="progress-bar">
<div
className="progress-fill"
style={{ width: `${(currentTime / duration) * 100}%` }}
/>
</div>
<div className="quality-selector">
<select
value={quality}
onChange={(e) => setQuality(e.target.value)}
>
{video.qualities.map(q => (
<option key={q.quality} value={q.quality}>
{q.quality}
</option>
))}
</select>
</div>
</div>
</div>
);
}
```
### Channel Dashboard
```jsx
function ChannelDashboard({ channelId }) {
const [analytics, setAnalytics] = useState(null);
const [videos, setVideos] = useState([]);
useEffect(() => {
async function fetchChannelData() {
const [analyticsRes, videosRes] = await Promise.all([
fetch(`/api/channels/${channelId}/analytics`),
fetch(`/api/videos?channelId=${channelId}`)
]);
setAnalytics(await analyticsRes.json());
setVideos(await videosRes.json());
}
fetchChannelData();
}, [channelId]);
return (
<div className="channel-dashboard">
<div className="stats-grid">
<div className="stat-card">
<h3>Subscribers</h3>
<p className="text-3xl font-bold">{analytics?.subscriberCount}</p>
</div>
<div className="stat-card">
<h3>Total Views</h3>
<p className="text-3xl font-bold">{analytics?.totalViews}</p>
</div>
<div className="stat-card">
<h3>Watch Time</h3>
<p className="text-3xl font-bold">{analytics?.totalWatchTime}h</p>
</div>
<div className="stat-card">
<h3>Revenue</h3>
<p className="text-3xl font-bold">${analytics?.revenue}</p>
</div>
</div>
<div className="recent-videos">
<h2>Recent Videos</h2>
<div className="video-grid">
{videos.map(video => (
<VideoCard key={video.id} video={video} />
))}
</div>
</div>
</div>
);
}
```
### Video Upload Component
```jsx
function VideoUpload({ channelId, onUploadComplete }) {
const [uploading, setUploading] = useState(false);
const [progress, setProgress] = useState(0);
const [videoData, setVideoData] = useState({
title: '',
description: '',
category: 'GENERAL',
tags: [],
visibility: 'PRIVATE'
});
const handleUpload = async (file) => {
setUploading(true);
// First upload video file
const formData = new FormData();
formData.append('file', file);
const uploadRes = await fetch('/api/upload/video', {
method: 'POST',
body: formData,
onUploadProgress: (progressEvent) => {
const progress = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
setProgress(progress);
}
});
const { videoUrl, duration, fileSize } = await uploadRes.json();
// Create video record
const createRes = await fetch('/api/videos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...videoData,
channelId,
videoUrl,
duration,
fileSize
})
});
const video = await createRes.json();
setUploading(false);
onUploadComplete(video);
};
return (
<form className="video-upload">
<div className="upload-area">
<input
type="file"
accept="video/*"
onChange={(e) => handleUpload(e.target.files[0])}
disabled={uploading}
/>
{uploading && (
<div className="upload-progress">
<div className="progress-bar">
<div
className="progress-fill"
style={{ width: `${progress}%` }}
/>
</div>
<p>Uploading... {progress}%</p>
</div>
)}
</div>
<div className="video-metadata">
<input
type="text"
placeholder="Video title"
value={videoData.title}
onChange={(e) => setVideoData({
...videoData,
title: e.target.value
})}
/>
<textarea
placeholder="Video description"
value={videoData.description}
onChange={(e) => setVideoData({
...videoData,
description: e.target.value
})}
/>
<select
value={videoData.category}
onChange={(e) => setVideoData({
...videoData,
category: e.target.value
})}
>
<option value="GENERAL">General</option>
<option value="TUTORIAL">Tutorial</option>
<option value="GAMING">Gaming</option>
<option value="MUSIC">Music</option>
</select>
</div>
</form>
);
}
```
## π Analytics Dashboard
### View Analytics Chart
```jsx
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip } from 'recharts';
function ViewAnalyticsChart({ videoId }) {
const [analyticsData, setAnalyticsData] = useState([]);
useEffect(() => {
fetch(`/api/videos/${videoId}/analytics`)
.then(res => res.json())
.then(data => setAnalyticsData(data.analytics));
}, [videoId]);
return (
<div className="analytics-chart">
<h3>Views Over Time</h3>
<LineChart width={800} height={400} data={analyticsData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" />
<YAxis />
<Tooltip />
<Line
type="monotone"
dataKey="views"
stroke="#8884d8"
strokeWidth={2}
/>
<Line
type="monotone"
dataKey="uniqueViews"
stroke="#82ca9d"
strokeWidth={2}
/>
</LineChart>
</div>
);
}
```
### Engagement Metrics
```jsx
function EngagementMetrics({ video }) {
const engagementRate = ((video.likeCount + video.dislikeCount + video.commentCount) / video.viewCount * 100).toFixed(2);
const likeRatio = (video.likeCount / (video.likeCount + video.dislikeCount) * 100).toFixed(1);
return (
<div className="engagement-metrics">
<div className="metric">
<h4>Engagement Rate</h4>
<p className="text-2xl font-bold">{engagementRate}%</p>
</div>
<div className="metric">
<h4>Like Ratio</h4>
<p className="text-2xl font-bold">{likeRatio}%</p>
</div>
<div className="metric">
<h4>Average View Duration</h4>
<p className="text-2xl font-bold">{video.averageViewDuration}s</p>
</div>
<div className="engagement-breakdown">
<div className="bar-chart">
<div className="bar likes" style={{ width: `${(video.likeCount / video.viewCount) * 100}%` }}>
π {video.likeCount}
</div>
<div className="bar comments" style={{ width: `${(video.commentCount / video.viewCount) * 100}%` }}>
π¬ {video.commentCount}
</div>
<div className="bar shares" style={{ width: `${(video.shareCount / video.viewCount) * 100}%` }}>
π€ {video.shareCount}
</div>
</div>
</div>
</div>
);
}
```
## π§ Advanced Configuration
### Video Processing Pipeline
```javascript
// Video processing workflow
const videoProcessingPipeline = {
upload: {
maxFileSize: '2GB',
supportedFormats: ['mp4', 'mov', 'avi', 'mkv', 'webm'],
chunkSize: '10MB'
},
transcoding: {
qualities: [
{ name: '360p', resolution: '640x360', bitrate: '800k' },
{ name: '480p', resolution: '854x480', bitrate: '1200k' },
{ name: '720p', resolution: '1280x720', bitrate: '2500k' },
{ name: '1080p', resolution: '1920x1080', bitrate: '4500k' }
],
thumbnails: {
count: 3,
times: ['10%', '50%', '90%'],
resolution: '1280x720'
}
},
delivery: {
cdn: 'cloudflare',
adaptiveStreaming: true,
hls: true,
dash: true
}
};
```
### Monetization Settings
```javascript
const monetizationConfig = {
adPlacements: ['preroll', 'midroll', 'postroll'],
minimumWatchTime: 30, // seconds before counting monetized view
revenueShare: {
creator: 70,
platform: 30
},
eligibility: {
minimumSubscribers: 1000,
minimumWatchHours: 4000,
contentGuidelines: true,
monetizationAgreement: true
},
payoutThreshold: 100, // minimum earnings before payout
payoutSchedule: 'monthly'
};
```
## π Deployment
### Environment Variables
```bash
# Production settings
NODE_ENV=production
DATABASE_URL="postgresql://..."
NEXTAUTH_SECRET="secure-secret"
NEXTAUTH_URL="https://yourdomain.com"
# Video storage and CDN
CLOUDINARY_CLOUD_NAME="your-cloud"
CLOUDINARY_API_KEY="your-key"
CLOUDINARY_API_SECRET="your-secret"
CDN_URL="https://cdn.yourdomain.com"
# Video processing
FFMPEG_PATH="/usr/bin/ffmpeg"
VIDEO_PROCESSING_WEBHOOK="https://yourdomain.com/api/webhooks/video"
MAX_UPLOAD_SIZE="2GB"
# Live streaming
RTMP_SERVER="rtmp://live.yourdomain.com/live"
HLS_ENDPOINT="https://hls.yourdomain.com"
# Analytics and monitoring
GOOGLE_ANALYTICS_ID="GA-MEASUREMENT-ID"
SENTRY_DSN="https://sentry.io/..."
# Monetization
STRIPE_PUBLISHABLE_KEY="pk_live_..."
STRIPE_SECRET_KEY="sk_live_..."
PAYPAL_CLIENT_ID="your-paypal-client-id"
```
### Performance Optimization
```javascript
// Video delivery optimization
const deliveryOptimization = {
// CDN configuration
cdn: {
provider: 'cloudflare',
regions: ['global'],
caching: {
videos: '30d',
thumbnails: '7d',
metadata: '1h'
}
},
// Adaptive bitrate streaming
adaptiveStreaming: {
enabled: true,
bufferLength: 30, // seconds
qualityLevels: ['360p', '480p', '720p', '1080p'],
autoSwitch: true
},
// Progressive loading
progressiveLoading: {
enabled: true,
chunkSize: '1MB',
preloadNext: true
}
};
```
## π Security & Privacy
### Content Protection
```javascript
const contentProtection = {
// DRM for premium content
drm: {
enabled: false, // Can be enabled for premium tiers
providers: ['widevine', 'playready', 'fairplay']
},
// Geo-blocking
geoBlocking: {
enabled: true,
blockedCountries: [],
allowedCountries: ['*']
},
// Domain restriction
domainRestriction: {
enabled: false,
allowedDomains: ['yourdomain.com']
},
// Watermarking
watermark: {
enabled: false,
position: 'bottom-right',
opacity: 0.3
}
};
```
### Privacy Controls
```javascript
const privacyControls = {
visibility: {
public: 'Anyone can view',
unlisted: 'Only people with link can view',
private: 'Only you can view',
scheduled: 'Will be public at scheduled time'
},
ageRestriction: {
enabled: true,
minimumAge: 13,
explicitContent: false
},
dataRetention: {
analytics: '2 years',
watchHistory: '3 years',
comments: 'indefinite',
uploadedContent: 'indefinite'
}
};
```
## π± Mobile Support
### Progressive Web App
```json
{
"name": "Video Streaming Platform",
"short_name": "VideoHub",
"description": "Professional video streaming platform",
"start_url": "/videos",
"display": "standalone",
"background_color": "#000000",
"theme_color": "#FF0000",
"icons": [
{
"src": "/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png"
}
]
}
```
### Mobile-Optimized Player
```jsx
function MobileVideoPlayer({ video }) {
const [isFullscreen, setIsFullscreen] = useState(false);
const [showControls, setShowControls] = useState(true);
return (
<div className={`mobile-player ${isFullscreen ? 'fullscreen' : ''}`}>
<video
controls={showControls}
playsInline
preload="metadata"
onTouchStart={() => setShowControls(!showControls)}
>
<source src={video.videoUrl} type="video/mp4" />
</video>
<div className="mobile-controls">
<button onClick={() => setIsFullscreen(!isFullscreen)}>
{isFullscreen ? 'β' : 'βΆ'}
</button>
</div>
</div>
);
}
```
## π Resources
- [Video Streaming Best Practices](https://developer.mozilla.org/en-US/docs/Web/Guide/Audio_and_video_delivery)
- [HLS Streaming Guide](https://developer.apple.com/streaming/)
- [DASH Streaming Specification](https://dashif.org/)
- [Content Creator Guidelines](https://support.google.com/youtube/topic/9282364)
- [Video SEO Best Practices](https://developers.google.com/search/docs/advanced/guidelines/video)
## π€ Contributing
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Add comprehensive tests for video functionality
4. Update documentation
5. Submit a pull request
## π License
This video streaming platform is part of the sysrot-hub template and follows the same license terms.
---
## π― Next Steps
Consider implementing these advanced features:
1. **Live Streaming** - RTMP/HLS live broadcasting
2. **AI-Powered Recommendations** - Machine learning content discovery
3. **Advanced Analytics** - Heat maps, retention curves, A/B testing
4. **Content Delivery Network** - Global video distribution
5. **Mobile Apps** - Native iOS and Android applications
6. **VR/360Β° Video Support** - Immersive video experiences
7. **Advanced Monetization** - Subscriptions, pay-per-view, donations
8. **Content Creator Tools** - Video editor, thumbnail generator
9. **Enterprise Features** - White-label solutions, API marketplace
10. **Blockchain Integration** - NFT videos, creator tokens
The video streaming platform provides a solid foundation for building the next generation of video content platforms with all the features content creators and viewers expect from modern video services.