v0.5.0 — Cloud hosting works, and audio files are 3× smaller
v0.4.0 said, flatly, that Syncwave could not run on a cloud host. That was true when it was written. It isn't any more.
☁️ Cloud hosting works now
YouTube refuses most datacenter IPs, and cookies genuinely do not lift it — that finding stands. What was wrong was the conclusion drawn from it.
The refusal isn't uniform. Measured from a fresh cloud instance: every direct attempt was refused, while 4 of 10 commodity proxies fetched the same track fine. Which proxies work varies by origin and drifts over time, so the useful fix was never "route through a proxy" — it's try routes until one answers, and remember which did.
- Direct is always tried first. At home it simply works, and on a metered plan every byte not spent is another track someone gets to play. The pool is only reached for when the IP is actually refused.
- Only IP-reputation failures reroute — bot-check, 429, 403. A deleted video fails identically through all ten proxies, so retrying it there is waste.
- It learns. A proxy that delivers gets tried first next time; a refused one backs off with an escalating cooldown, but is never parked permanently, since providers recycle addresses.
- Credentials never reach a log line — only
host:portis printed.
Point it at a provider, or supply your own list:
WEBSHARE_API_KEY=your-key
# or, any provider:
YTDLP_PROXY_LIST=http://user:pass@host:port,http://user:pass@host2:portBoth are also settable in /admin on a running instance, so a host that turns out to be blocked can be fixed from the browser instead of an SSH session and a redeploy.
Verified live: 5 of 5 previously-refused tracks now serve HTTP 200 from a cloud instance.
🎧 Audio files are 3× smaller, and better
This one is a plain bug fix and it helps every install, cloud or not.
Asking for bestaudio gets Opus in a webm container. Converting that to m4a re-encoded it — losing a generation of quality and inflating the file, because the encoder was told to aim high. A 4.4 MB Opus stream came back out as a 14 MB m4a.
Requesting the m4a rendition instead means ffmpeg only rewrites the container. Same audio, no transcode, no CPU cost:
| Before | After | |
|---|---|---|
| Cached file, direct | 14.0 MB | 4.3 MB |
| Cached file, via proxy | 14.0 MB | 1.6 MB |
On a proxy the bitrate is capped as well, since that traffic is billed by the byte — taking a 1 GB allowance from ~210 tracks to ~380. Direct connections are never capped. PROXY_MAX_ABR tunes the cap; 0 turns it off.
The ceiling is bandwidth, not blocking. Measured end to end a proxied track costs ~2.7 MB — the file is ~1.6 MB, the rest is metadata and protocol overhead. A 1 GB/month free plan is therefore roughly 350–400 tracks: plenty for a few friends, not enough for a public instance. Every track is cached for 72h, so repeat plays cost nothing.
🚂 Running it on Railway
If you have no machine to leave running, there's now a
step-by-step Railway guide
— repo to listening room in about ten minutes.
Two steps decide whether it works, and both are easy to miss: attach a volume
before first boot, or your admin password, rooms and cache are wiped by the
next redeploy; and configure a proxy pool, or Railway's datacenter IP means
nothing plays.
🛠️ Also
docker-compose.ymlwhitelists environment variables explicitly, so the new proxy settings were being read for substitution and then never reaching the process that needed them. Fixed.- README and DEPLOY.md rewritten around what actually happens, including the bandwidth ceiling.
Upgrading: git pull && docker compose up -d --build. Existing cached audio stays at the old size until it ages out; delete cache/*.m4a to reclaim the space immediately.