obs-r2-uploader/README.md

294 lines
8.1 KiB
Markdown

# OBS to Cloudflare R2 Direct Upload System
Upload OBS Studio recordings directly to Cloudflare R2 storage with public video sharing capabilities. No YouTube required!
## Features
- **Direct Upload**: Upload video files to Cloudflare R2 with a single command
- **Progress Tracking**: Real-time upload progress with visual feedback
- **Auto-Upload**: File watcher automatically uploads new OBS recordings
- **Public Sharing**: Instantly shareable video URLs via videos.jeffemmett.com
- **Video Gallery**: Beautiful web gallery to browse all your videos
- **Admin Panel**: Web-based admin interface to manage video visibility
- **Privacy Controls**: Set videos as Private, Shareable, or Clip-Shareable
- **Clip Generation**: Create shareable time-based clips from longer videos
- **Clipboard Integration**: Public URLs automatically copied to clipboard
- **Large File Support**: Multipart uploads for videos over 100MB
- **Cross-Platform**: Works on Windows, macOS, and Linux
## Quick Start
### 1. Installation
```bash
# Run the setup script
./scripts/setup.sh
# Authenticate with Cloudflare
wrangler login
```
### 2. Configuration
Edit `.env` file with your Cloudflare R2 credentials:
```env
R2_ACCOUNT_ID=your_account_id
R2_ACCESS_KEY_ID=your_access_key
R2_SECRET_ACCESS_KEY=your_secret_key
R2_BUCKET_NAME=obs-videos
PUBLIC_DOMAIN=videos.jeffemmett.com
```
### 3. Deploy
```bash
# Create R2 bucket and deploy worker
./scripts/deploy.sh
```
### 4. Upload Your First Video
```bash
# Upload a video
./scripts/upload.sh /path/to/video.mp4
# The public URL will be displayed and copied to your clipboard
```
## Usage
### Manual Upload
Upload a single video file:
```bash
./scripts/upload.sh /path/to/video.mp4
```
Upload with custom name:
```bash
./scripts/upload.sh /path/to/video.mp4 my-awesome-video.mp4
```
### Automatic Upload (File Watcher)
Watch a directory and auto-upload new recordings:
```bash
# Watch a specific directory
./scripts/start-watcher.sh /path/to/obs/recordings
# Or set OBS_RECORDING_DIR in .env and run:
./scripts/start-watcher.sh
```
The file watcher will:
- Monitor the directory for new video files
- Wait until recording is complete (file size stable)
- Automatically upload the video
- Copy the public URL to clipboard
- Optionally delete the local file (if `AUTO_DELETE_AFTER_UPLOAD=true`)
### View Your Videos
- **Direct Access**: `https://videos.jeffemmett.com/video-name.mp4`
- **Gallery View**: `https://videos.jeffemmett.com/gallery`
- **JSON API**: `https://videos.jeffemmett.com/` or `https://videos.jeffemmett.com/api/list`
- **Admin Panel**: `https://videos.jeffemmett.com/admin` (requires authentication)
## Admin Panel
Manage your video library with a powerful web-based admin interface.
### Features
- **📤 Manual Upload**: Drag-and-drop video files directly in the browser
- **Video Visibility Control**
- 🔒 **Private**: Only you can view
- 🔗 **Shareable**: Anyone with link can view
- ✂️ **Clip Shareable**: Only time-based clips are shareable
- **Clip Generation**: Create shareable clips with start/end times
- **Bulk Management**: Search, filter, and manage multiple videos
- **Delete Videos**: Remove videos directly from the admin panel
- **Statistics Dashboard**: See breakdown of video visibility
- **Upload Progress**: Real-time progress tracking for uploads
- **Empty State**: Helpful UI when no videos exist
### Setup Admin Panel
```bash
# Setup KV namespace and admin password
./scripts/setup-admin.sh
# Build worker with embedded admin interface
python3 scripts/build-worker.py
# Deploy
cd worker && wrangler deploy
```
Access admin panel at: `https://videos.jeffemmett.com/admin`
See [ADMIN.md](ADMIN.md) for complete admin documentation.
## Project Structure
```
obs-r2-uploader/
├── obs_uploader/ # Python upload package
│ ├── upload.py # Core upload script
│ ├── file_watcher.py # Auto-upload daemon
│ └── config.py # Configuration management
├── worker/ # Cloudflare Worker
│ ├── video-server.js # Video serving logic
│ └── wrangler.toml # Worker configuration
├── scripts/ # Convenience scripts
│ ├── setup.sh # One-command setup
│ ├── deploy.sh # Deploy worker
│ ├── upload.sh # Upload wrapper
│ └── start-watcher.sh # Start file watcher
├── .env # Your configuration (not in git)
├── .env.example # Configuration template
└── requirements.txt # Python dependencies
```
## Configuration Options
All configuration is done via `.env` file:
| Variable | Required | Description |
|----------|----------|-------------|
| `R2_ACCOUNT_ID` | Yes | Your Cloudflare account ID |
| `R2_ACCESS_KEY_ID` | Yes | R2 API access key |
| `R2_SECRET_ACCESS_KEY` | Yes | R2 API secret key |
| `R2_BUCKET_NAME` | Yes | Name of R2 bucket (default: obs-videos) |
| `R2_ENDPOINT` | Auto | R2 endpoint URL (auto-generated) |
| `PUBLIC_DOMAIN` | Yes | Your public domain (videos.jeffemmett.com) |
| `OBS_RECORDING_DIR` | No | Default directory for file watcher |
| `AUTO_DELETE_AFTER_UPLOAD` | No | Delete local file after upload (default: false) |
## Supported Video Formats
- MP4 (`.mp4`)
- MKV (`.mkv`)
- MOV (`.mov`)
- AVI (`.avi`)
- WebM (`.webm`)
- FLV (`.flv`)
- WMV (`.wmv`)
## Advanced Usage
### Python Module
Use as a Python module in your own scripts:
```python
from obs_uploader.config import Config
from obs_uploader.upload import R2Uploader
# Load configuration
config = Config()
# Create uploader
uploader = R2Uploader(config)
# Upload a file
public_url = uploader.upload_file(Path("/path/to/video.mp4"))
print(f"Uploaded: {public_url}")
```
### Custom Worker Routes
Edit `worker/wrangler.toml` to customize routes and domains:
```toml
[env.production]
routes = [
{ pattern = "videos.jeffemmett.com/*", custom_domain = true }
]
```
### Gallery Customization
Edit `worker/video-server.js` to customize the gallery appearance and functionality.
## Troubleshooting
### Upload fails with "Invalid credentials"
- Verify your R2 API credentials in `.env`
- Ensure the API token has read/write permissions for R2
- Check that the bucket name matches
### Videos not accessible via public URL
- Verify CORS is configured (see SETUP.md)
- Check that custom domain is set up in Cloudflare dashboard
- Ensure worker is deployed: `cd worker && wrangler deploy`
### File watcher not detecting new files
- Verify the watch directory path is correct
- Check file permissions on the directory
- Ensure video file format is supported
### Clipboard not working on Linux
Install xclip or xsel:
```bash
sudo apt-get install xclip
# or
sudo apt-get install xsel
```
## Performance
- **Small files (<100MB)**: Simple upload with progress bar
- **Large files (>100MB)**: Automatic multipart upload with 10MB chunks
- **Network resilience**: Automatic retries with exponential backoff
- **CDN caching**: Cloudflare automatically caches videos globally
## Security
- All R2 credentials stored in `.env` (gitignored)
- Videos are publicly accessible by URL (no authentication)
- Consider signed URLs for sensitive content (not implemented yet)
- CORS configured for browser access
## Cost Considerations
Cloudflare R2 pricing (as of 2024):
- **Storage**: $0.015/GB per month
- **Class A Operations** (writes): $4.50 per million requests
- **Class B Operations** (reads): $0.36 per million requests
- **Egress**: FREE (no bandwidth charges!)
Example costs for 100GB of videos:
- Storage: $1.50/month
- 1000 uploads: ~$0.005
- 10,000 views: ~$0.004
## Contributing
This is a personal project, but feel free to fork and adapt for your own use!
## License
MIT License - See LICENSE file for details
## Acknowledgments
Built with:
- [Cloudflare R2](https://www.cloudflare.com/products/r2/) - Object storage
- [Cloudflare Workers](https://workers.cloudflare.com/) - Edge computing
- [boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html) - AWS SDK for Python
- [watchdog](https://python-watchdog.readthedocs.io/) - File system monitoring
---
Made with ❤️ by Jeff Emmett