StreamCaster is a professional-grade UDP-to-RTMP streaming system that enables dynamic video switching without interrupting live streams. Perfect for content creators, live streaming setups, and broadcast applications.
🚀 Now with automated CI/CD deployment! Push to main branch and watch your changes deploy automatically to AWS Lightsail. Enhanced with concurrency control and Terraform state lock protection. Last updated: 2025-06-06 18:28 JST
- 🎥 Dynamic Video Switching - Change videos seamlessly during live streams
- ☁️ Google Drive Integration - Stream videos directly from Google Drive folders
- 🌐 Web-based Control Panel - Intuitive browser interface for stream management
- 📡 Multiple Platform Support - Stream to Twitch, YouTube, Facebook Live, and custom RTMP servers
- 🔄 Zero-Downtime Switching - Switch videos without dropping the RTMP connection
- 📊 Real-time Monitoring - Live status updates, resource monitoring, and health checks
- 🐳 Docker-based Architecture - Containerized for easy deployment and scaling
- 🧪 Comprehensive Testing - Full test suite with CI/CD pipeline
- 📚 RESTful API - Complete API for programmatic control
- 🛡️ Production Ready - Built for reliability and performance
StreamCaster uses a multi-container architecture for optimal performance and reliability:
graph TD
A[Controller] -->|UDP Stream| B[Receiver]
B -->|RTMP| C[RTMP Server]
C -->|Pull| D[OBS]
C -->|Pull| F[Relay]
F -->|再エンコード + Push| G[配信先]
subgraph "ストリーミングシステム"
A
B
C
F
end
subgraph "外部システム"
D
E
G
end
style A fill:#e1f5fe
style B fill:#e8f5e8
style C fill:#fff3e0
style F fill:#fce4ec
| Component | Purpose | Technology |
|---|---|---|
| Controller | Web UI, API, Process Management | Node.js + Express |
| Receiver | UDP to RTMP conversion | FFmpeg |
| Relay | Dynamic video switching | FFmpeg |
| RTMP Server | Local testing server | Nginx + RTMP module |
- Docker & Docker Compose
- 4GB+ RAM
- 2+ CPU cores
- 10GB+ disk space
git clone https://github.com/azumag/streamcaster.git
cd streamcaster
# Install dependencies
npm install
# Prepare video directory
mkdir -p videos
cp your-videos/* videos/# Start all services
docker-compose up -d
# Check status
docker-compose ps
# View logs
docker-compose logs -f- Control Panel: http://localhost:8080
- RTMP Stats: http://localhost:8081/stat
- Open the web interface
- Select a video file
- Click "Start Streaming"
- Stream URL:
rtmp://localhost:1935/live/stream
# Clone repository
git clone https://github.com/azumag/streamcaster.git
cd streamcaster
# Install Node.js dependencies
npm install
# Install controller dependencies
cd controller
npm install
# Run tests
npm test
# Start development server
npm run dev# Create production environment file
cp .env.example .env.production
# Edit configuration
vim .env.production
# Deploy with production settings
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d# Install system dependencies
sudo apt update
sudo apt install ffmpeg docker.io docker-compose nodejs npm
# Clone and setup project
git clone https://github.com/azumag/streamcaster.git
cd streamcaster
npm install
# Configure environment
cp .env.example .env
# Edit .env with your settings
# Start services
docker-compose up -dThe web interface provides complete control over your streaming setup:
- Live Status Display - Current streaming status and video
- Video Library - Browse and manage your video files
- Stream Controls - Start, stop, and switch streams
- Real-time Monitoring - CPU, memory, and network usage
- Log Viewer - Real-time system logs
-
Start Streaming
- Select video from library
- Click "Start Stream"
- Monitor status in dashboard
-
Switch Videos
- Select new video while streaming
- Click "Switch" for seamless transition
- No stream interruption
-
Stop Streaming
- Click "Stop Stream"
- Safely terminates all processes
Complete RESTful API for programmatic control:
# Get current status
curl http://localhost:8080/api/status
# List available videos
curl http://localhost:8080/api/videos
# Start/switch video
curl -X POST http://localhost:8080/api/switch \
-H "Content-Type: application/json" \
-d '{"video": "your-video.mp4"}'
# Stop streaming
curl -X POST http://localhost:8080/api/stop
# Health check
curl http://localhost:8080/api/health// GET /api/status
{
"stream_status": "streaming",
"current_video": "demo.mp4",
"process_status": {
"udp_streaming_running": true,
"udp_sender_pid": 1234
},
"timestamp": "2024-06-05T12:00:00.000Z"
}
// GET /api/videos
{
"videos": [
{
"filename": "demo.mp4",
"size": 52428800,
"modified": "2024-06-05T10:30:00.000Z"
}
],
"count": 1
}# Health monitoring
./scripts/health_check.sh
# Manual process control
./scripts/start_sender.sh video.mp4
./scripts/stop_sender.sh
# Container management
docker-compose restart receiver
docker-compose logs controllerCreate .env file with your configuration:
# RTMP Configuration
RTMP_SERVER=rtmp://live.twitch.tv/live
STREAM_KEY=your_stream_key_here
# Google Drive Configuration
GOOGLE_DRIVE_API_KEY=your_google_drive_api_key_here
GOOGLE_CLIENT_ID=your_google_client_id_here
GOOGLE_CLIENT_SECRET=your_google_client_secret_here
GOOGLE_REFRESH_TOKEN=your_refresh_token_here
# Network Settings
UDP_PORT=1234
HTTP_PORT=8080
RTMP_PORT=1935
# Resource Limits
CONTROLLER_CPU_LIMIT=0.5
RECEIVER_CPU_LIMIT=1.0
CONTROLLER_MEMORY_LIMIT=512m
RECEIVER_MEMORY_LIMIT=1g
MAX_DOWNLOAD_SIZE=1073741824
TEMP_FILE_TTL=3600000
# Logging
LOG_LEVEL=info
TZ=Asia/Tokyo
# Docker Settings
COMPOSE_PROJECT_NAME=streamcaster
DOCKER_BUILDKIT=1RTMP_SERVER=rtmp://live.twitch.tv/live
STREAM_KEY=live_1234567890_abcdefghijklmnopRTMP_SERVER=rtmp://a.rtmp.youtube.com/live2
STREAM_KEY=your-youtube-stream-keyRTMP_SERVER=rtmp://live-api-s.facebook.com:80/rtmp
STREAM_KEY=your-facebook-stream-keyRTMP_SERVER=rtmp://your-server.com/live
STREAM_KEY=your-custom-keyTo enable Google Drive functionality, you need to set up Google Drive API access:
- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable the Google Drive API
- Create an API key in Credentials
- Set the API key in your environment:
GOOGLE_DRIVE_API_KEY=your_api_key_here- Go to Google Cloud Console
- Enable the Google Drive API
- Create OAuth 2.0 credentials (Desktop application)
- Download the credentials JSON file
- Use a tool like Google's OAuth Playground to get a refresh token
- Configure all OAuth settings:
GOOGLE_CLIENT_ID=your_client_id_here
GOOGLE_CLIENT_SECRET=your_client_secret_here
GOOGLE_REFRESH_TOKEN=your_refresh_token_here- Share your Google Drive folder publicly (for API key) or ensure OAuth access
- Copy the folder URL or ID
- In the web interface, switch to the "Google Drive" tab
- Paste the folder link and click "ファイルリスト取得"
- Select videos from the list to stream
Supported formats and recommended settings:
| Setting | Recommended | Supported |
|---|---|---|
| Container | MP4 | MP4, MOV, AVI, MKV |
| Video Codec | H.264 | H.264, H.265 |
| Audio Codec | AAC | AAC, MP3 |
| Resolution | 1920x1080 | Any |
| Framerate | 30fps | 24-60fps |
| Bitrate | 2-6 Mbps | 1-50 Mbps |
To achieve maximum stability across all system components (Controller → Receiver → RTMP Server → Relay), use these specific encoding settings:
ffmpeg -i input.mp4 \
-c:v libx264 -preset medium -crf 21 \
-maxrate 4000k -bufsize 8000k \
-pix_fmt yuv420p -profile:v high -level 4.0 \
-r 30 -g 60 -keyint_min 30 -sc_threshold 0 \
-vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black,fps=30" \
-aspect 16:9 \
-c:a aac -b:a 192k -ar 48000 -ac 2 -profile:a aac_low \
-movflags +faststart \
output.mp4Video Configuration:
- Codec:
libx264- Maximum compatibility across all components - Preset:
medium- Balance between encoding speed and quality - CRF:
21- High quality constant rate factor - Rate Control:
maxrate 4000k -bufsize 8000k- Prevents UDP overflow - Pixel Format:
yuv420p- Universal compatibility - Profile/Level:
high@4.0- Optimal for streaming platforms - Frame Rate:
30fps- Stable UDP transmission - GOP:
60 frames (2s)- Good seek performance and stability - Scene Detection: Disabled (
-sc_threshold 0) - Predictable bitrate
Audio Configuration:
- Codec:
aac- Standard for RTMP streaming - Bitrate:
192k- High quality audio - Sample Rate:
48000Hz- Broadcast standard - Channels:
2(stereo) - Standard configuration - Profile:
aac_low- Maximum compatibility
Video Processing:
- Resolution: Normalized to 1920x1080 with black padding
- Aspect Ratio: Forced to 16:9 for consistent output
- Scaling: Maintains original aspect ratio, adds black bars if needed
- Controller (UDP Sender): Fixed frame rate and bitrate limits ensure stable UDP transmission
- Receiver (UDP to RTMP): Standard H.264 profile ensures reliable decoding
- RTMP Server: Level 4.0 and AAC Low profile are universally supported
- Relay (Re-streaming): Consistent 1920x1080 output simplifies relay processing
These settings prioritize system stability over file size optimization and are specifically tuned for real-time streaming workflows.
Returns current streaming status and system information.
Response:
{
"stream_status": "streaming|stopped|error",
"current_video": "filename.mp4|null",
"process_status": {
"udp_streaming_running": boolean,
"udp_sender_pid": number|null
},
"timestamp": "ISO-8601-datetime"
}Start streaming or switch to a different video.
Request (Local File):
{
"video": "filename.mp4",
"source": "local"
}Request (Google Drive):
{
"video": "filename.mp4",
"source": "googledrive",
"googledriveFileId": "file_id_from_google_drive"
}Response:
{
"success": boolean,
"message": "string",
"video": "filename.mp4",
"source": "local|googledrive",
"status": "streaming"
}Stop current streaming session.
Response:
{
"success": boolean,
"message": "Stream stopped successfully"
}List all available video files.
Response:
{
"videos": [
{
"filename": "video.mp4",
"size": 52428800,
"modified": "2024-06-05T10:30:00.000Z"
}
],
"count": 1
}Get video files from a Google Drive folder.
Request:
{
"folderLink": "https://drive.google.com/drive/folders/folder_id"
}Response:
{
"success": boolean,
"files": [
{
"id": "file_id",
"filename": "video.mp4",
"size": 52428800,
"modified": "2024-06-05T10:30:00.000Z"
}
],
"count": 1,
"folderId": "folder_id"
}Check Google Drive authentication status and temporary files.
Response:
{
"authenticated": boolean,
"tempDir": {
"fileCount": 3,
"totalSize": 157286400,
"totalSizeMB": "150.00"
},
"timestamp": "ISO-8601-datetime"
}Clean up temporary Google Drive files.
Response:
{
"success": boolean,
"message": "Cleanup completed"
}System health check endpoint.
Response:
{
"status": "healthy|unhealthy",
"udp_process": boolean,
"timestamp": "ISO-8601-datetime"
}All endpoints return standardized error responses:
{
"success": false,
"error": "Error description",
"code": "ERROR_CODE"
}Common Error Codes:
VIDEO_NOT_FOUND- Specified video file doesn't existPROCESS_START_FAILED- Failed to start streaming processINVALID_REQUEST- Malformed request dataSYSTEM_ERROR- Internal system error
streamcaster/
├── controller/ # Node.js controller service
│ ├── __tests__/ # Test files
│ ├── templates/ # Web UI templates
│ ├── controller.js # Main application
│ ├── process_manager.js # Process management
│ ├── google_drive_manager.js # Google Drive integration
│ └── package.json # Dependencies
├── scripts/ # Utility scripts
│ ├── health_check.sh # Health monitoring
│ ├── start_sender.sh # Process control
│ └── stop_sender.sh # Process control
├── rtmp-server/ # Local RTMP server
├── videos/ # Video file storage
├── logs/ # Application logs
├── .env.example # Environment configuration template
├── docker-compose.yml # Docker configuration
└── README.md # This file
# Start development environment
npm run dev
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Check code quality
npm run lint
# Fix linting issues
npm run lint:fix
# Run full CI pipeline
npm run ciStreamCaster includes comprehensive test coverage:
# Run all tests
npm test
# Run with coverage report
npm run test:coverage
# Run specific test file
npm test -- controller.test.js
# Run tests in watch mode
npm run test:watchTest Categories:
- Unit tests for individual components
- Integration tests for API endpoints
- End-to-end tests for complete workflows
- Performance tests for resource usage
We maintain high code quality standards:
- ESLint - Code style and error checking
- Jest - Comprehensive testing framework
- GitHub Actions - Automated CI/CD pipeline
- Husky - Pre-commit hooks for quality gates
- Fork the repository
- Create feature branch:
git checkout -b feature/amazing-feature - Make changes and add tests
- Run quality checks:
npm run ci - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Create Pull Request
For production deployment, use the production compose file:
# Create production environment
cp .env.example .env.production
# Configure production settings
vim .env.production
# Deploy with production optimizations
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d- Set secure RTMP server credentials
- Configure resource limits appropriately
- Set up log rotation
- Configure firewall rules
- Set up monitoring and alerting
- Configure backup strategy
- Test failover procedures
For high-volume streaming scenarios:
# docker-compose.scale.yml
version: '3.8'
services:
receiver:
deploy:
replicas: 3
resources:
limits:
cpus: '2'
memory: 2gFor multiple streaming destinations:
# Start multiple receivers
docker-compose up -d --scale receiver=3
# Configure load balancer
# See nginx.conf.example for configurationBuilt-in health check system:
# Manual health check
./scripts/health_check.sh
# Continuous monitoring
./scripts/health_check.sh --watch
# Docker health checks
docker-compose psComprehensive logging for troubleshooting:
# View all logs
docker-compose logs
# Follow specific service logs
docker-compose logs -f controller
docker-compose logs -f receiver
# Filter by timestamp
docker-compose logs --since="2024-06-05T10:00:00"
# Export logs for analysis
docker-compose logs > streamcaster.logMonitor system resources:
# Container resource usage
docker stats
# System resource usage
top
htop
iotop
# Network monitoring
netstat -tlnp
ss -tlnp# Check video file permissions
ls -la videos/
# Verify Docker containers are running
docker-compose ps
# Check FFmpeg processes
ps aux | grep ffmpeg
# Review controller logs
docker-compose logs controller# Check resource limits
docker-compose config
# Monitor container resources
docker stats
# Adjust CPU limits in docker-compose.yml# Check port availability
netstat -tlnp | grep 8080
netstat -tlnp | grep 1935
# Test RTMP connectivity
ffmpeg -f lavfi -i testsrc -f flv rtmp://your-server/live/key
# Verify Docker network
docker network ls
docker network inspect streamcaster_streaming-networkAutomated recovery for common failures:
# Complete system restart
docker-compose down
docker-compose up -d
# Clean restart with rebuild
docker-compose down -v
docker-compose build --no-cache
docker-compose up -d
# Reset to known good state
git pull origin main
docker-compose down -v
docker-compose up -d --build- CPU: 2 cores
- RAM: 2GB
- Storage: 10GB
- Network: 10 Mbps upload
- CPU: 4+ cores
- RAM: 8GB+
- Storage: 100GB+ SSD
- Network: 50+ Mbps upload
# Optimize video files for streaming
ffmpeg -i input.mp4 \
-c:v libx264 -preset medium -crf 23 \
-c:a aac -b:a 128k \
-movflags +faststart \
output.mp4# Optimized resource allocation
services:
controller:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.2'
memory: 256M- Multiple receiver containers
- Load balancing across streams
- Geographic distribution
- Increased CPU/memory allocation
- High-performance storage
- Dedicated network interfaces
- Use private networks for internal communication
- Implement firewall rules for external access
- Use VPN for remote management
- Regular security updates
# Restrict web interface access
# Configure nginx proxy with authentication
# Secure RTMP endpoints
# Use strong stream keys
# Implement IP whitelisting- Encrypt RTMP streams when possible
- Secure video file storage
- Regular backup procedures
- Access logging and monitoring
- Change default passwords/keys
- Configure HTTPS for web interface
- Set up proper firewall rules
- Enable audit logging
- Regular security updates
- Backup and recovery testing
- Access control implementation
Q: Can I stream to multiple platforms simultaneously? A: Yes, you can configure multiple receiver containers for different platforms. See the scaling section for details.
Q: What video formats are supported? A: Any format supported by FFmpeg (MP4, MOV, AVI, MKV, etc.). H.264/AAC is recommended for best compatibility.
Q: Is there a limit to video file size? A: No hard limit, but consider storage space and network bandwidth for large files.
Q: Can I use this without Docker? A: Yes, but Docker is highly recommended. Manual installation requires FFmpeg, Node.js, and proper process management.
Q: How do I add custom FFmpeg parameters? A: Modify the process_manager.js file or create custom scripts in the scripts/ directory.
Q: Can I run this on ARM processors (Raspberry Pi)? A: Yes, but performance may be limited. Use ARM-compatible Docker images.
Q: Stream is choppy or has artifacts A: Check CPU usage, reduce video bitrate, or increase hardware resources.
Q: Web interface is not accessible A: Verify port 8080 is not blocked and the controller container is running.
Q: RTMP connection fails A: Verify stream key and server URL. Check network connectivity and firewall rules.
This project is licensed under the MIT License - see the LICENSE file for details.
We welcome contributions! Please see our Contributing Guide for details.
- Development Team - Core system architecture and implementation
- Community - Bug reports, feature requests, and testing
- FFmpeg - Multimedia processing library
- Nginx RTMP Module - RTMP server implementation
- OBS Studio - Broadcasting software
- Node Media Server - Node.js RTMP server
- Documentation: This README and inline code comments
- Issues: GitHub Issues
- Discussions: GitHub Discussions
StreamCaster - Professional streaming made simple. 🎬✨