# Droppy A self-hosted, browser-based media casting system — like AirPlay/Chromecast but runs entirely in your browser. ## Features - **Drag & drop** files or **paste URLs** to cast instantly - **YouTube** extraction with ad-free playback and SponsorBlock integration - **Spotify & SoundCloud** display with album art and embedded players - **Social media** support (Instagram, Twitter/X, TikTok, Reddit, Twitch) via Cobalt - **Real-time sync** between uploader and display via WebSocket - **Queue management** with duration estimates and finish time - **TV-native UI** — large text, auto-hiding controls, works from couch distance - **Volume sync** and remote playback controls ## Quick Start (Docker) ```bash docker compose up -d --build # Access at http://localhost:3001 # Display page: http://localhost:3001/display ``` That's it! The Docker image includes Node.js, yt-dlp, ffmpeg, and Cobalt. ## How It Works ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Upload Page │ ───► │ Docker Server │ ───► │ Display Page │ │ (browser tab) │ │ (localhost) │ │ (fullscreen) │ └─────────────────┘ └─────────────────┘ └─────────────────┘ ``` 1. Open the display page (`/display`) in fullscreen on your TV or second monitor 2. Open the main page in another browser tab or device 3. Drop files or paste URLs — content appears on the display instantly ## Supported Content | Source | Support | |--------|---------| | Direct media files (.mp4, .jpg, .mp3, etc.) | ✅ Full | | YouTube | ✅ Full (downloads, SponsorBlock) | | Spotify | ✅ Album art + embedded player | | SoundCloud | ✅ Full with waveform display | | Instagram Reels/Posts | ✅ Via Cobalt | | Twitter/X videos | ✅ Via Cobalt | | TikTok | ✅ Via Cobalt | | Reddit videos | ✅ Via Cobalt | | Twitch clips | ✅ Via Cobalt | | Vimeo | ✅ Embedded player | ## Requirements ### Docker (Recommended) - Docker & Docker Compose ### Manual Setup - Node.js 20+ - ffmpeg - yt-dlp - Python 3 ## Installation ### Docker ```bash # Clone the repo git clone https://github.com/vidrun/droppy.git cd droppy # Start services (Droppy + Cobalt) docker compose up -d --build # View logs docker compose logs -f # Stop docker compose down ``` ### Manual ```bash # Install system dependencies (Ubuntu/Debian) sudo apt install ffmpeg python3 python3-pip pip3 install yt-dlp # Install Node dependencies npm install # Start development server npm run dev ``` ## Configuration ### Environment Variables Create a `.env` file (see `.env.example`): ```bash # Server port (default: 3000) PORT=3000 # Cobalt API for social media extraction COBALT_API_URL=http://cobalt:9000 ``` ### Network Access To access from other devices on your network: 1. Find your IP: `ip addr` or `hostname -I` 2. Access from other devices: `http://YOUR_IP:3001` 3. Open firewall if needed: `firewall-cmd --add-port=3001/tcp` ## Tech Stack - **Frontend**: SvelteKit (Svelte 5) - **Backend**: Node.js + Express - **Real-time**: Socket.IO - **Media**: yt-dlp, ffmpeg - **Social media**: Cobalt API ## Project Structure ``` droppy/ ├── src/ │ ├── lib/ │ │ ├── components/ │ │ │ ├── ContentDisplay.svelte # TV display renderer │ │ │ ├── DropZone.svelte # Upload interface │ │ │ ├── MediaPlayer.svelte # Video/audio player │ │ │ └── SoundCloudPlayer.svelte │ │ └── socket.ts # WebSocket client │ └── routes/ │ ├── +page.svelte # Upload page │ └── display/+page.svelte # Display page ├── server/ │ ├── index.ts # Express + Socket.IO server │ └── services/ │ ├── contentExtractor.ts # URL routing logic │ ├── youtubeExtractor.ts # yt-dlp integration │ ├── cobaltClient.ts # Social media extraction │ ├── spotifyExtractor.ts │ └── soundcloudExtractor.ts ├── docker-compose.yml # Docker orchestration ├── Dockerfile # Container build └── package.json ``` ## Troubleshooting **YouTube extraction fails:** - yt-dlp may need updating: `docker compose up -d --build` - Some videos are age-restricted or region-locked **No audio on YouTube (Firefox/Linux):** - Videos are encoded with VP9+Opus for Firefox compatibility - Install codecs: `sudo dnf install ffmpeg-libs` (Fedora/RHEL) **Social media not working:** - Ensure Cobalt container is running: `docker compose ps` - Check Cobalt logs: `docker compose logs cobalt` **Display not receiving content:** - Check both pages show "Connected" status - Refresh both pages - Check browser console for WebSocket errors ## License MIT