# 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
