Host your entire music library on Cloudflare with no server, VPS, or always-on process to manage.
EdgeSonic is a Subsonic-compatible streaming server that runs entirely on Cloudflare Workers. Use it with DSub, Symfonium, Substreamer, Sonixd, or any Subsonic client.
Deploy from your browser in minutes — no command line, local toolchain, or code required. Overture guides every step and provisions the required Cloudflare resources.
Already running Navidrome or another Subsonic server? Migrate tracks, playlists, users, and stars in one flow; interrupted migrations resume from the browser cache.
💸 R2 storage on the Free plan: 100 GB WAV + 20% pre-transcodes ≈ $1.65/month · 500 GB ≈ $8.85/month · no egress fees
☁️ Serverless by design — no host to patch, maintain, or keep online; Cloudflare's global edge delivers efficient access worldwide while reducing infrastructure attack surface
🖥️ Zero-code guided deployment — use a browser-only GUI to provision and deploy; never run a command or touch project code
🔄 Migrate from an existing server or push stars and playlists back upstream
▶ Try the live demo — opens directly as admin
Deploys in a few minutes from your browser — see "Quick start" below for details.
A live demo is hosted at https://edgesonic.lsy-demo.workers.dev/#/login and opens directly as admin.
The demo runs in DEMO_MODE=1: dangerous permissions (user/source management, delete, Cloudflare settings) are locked, uploads are capped, and the library is reset from a fixed set of tracks on every deploy. Everything else — browsing, playback, tag editing, the worker pool — is fully functional.
EdgeSonic serves two roles simultaneously:
- Subsonic-compatible API server (v1.16.1 + OpenSubsonic extensions) — works with native clients like DSub, Symfonium, Substreamer, and Sonixd.
- Music library management UI — tag editing, metadata scraping, file organisation, upload/download, and artwork management; feature-equivalent to music-tag-web v1.
- Multiple storage backends — Cloudflare R2 (primary), WebDAV, S3-compatible (MinIO / AWS / Backblaze B2 / Wasabi), external Subsonic upstream, direct URL
- R2 presigned direct streaming — optional SigV4 302 redirect so browsers fetch R2 objects directly, bypassing Worker bandwidth limits
- Browser worker pool — distributed metadata parsing and transcoding via Web Workers; concurrency is tunable and pauses automatically during playback
- Server-side transcoding — Sandbox DO container (ffmpeg) with on-demand or pre-bake strategy; browser pool engine for zero-backend-CPU transcoding
- Full Subsonic API — playlists, bookmarks, play queue, annotations (star/rating/scrobble), sharing, internet radio, podcasts, Last.fm integration, now playing, cover art, lyrics
- Temporary karaoke rooms — a QR request page for the current player, guest display names, per-person rotation or FIFO; requests stop when the room closes or its host lease expires.
- Independent video library — import videos or explicitly save Bilibili / YouTube references; audio/video links are many-to-many with a separate synchronization offset for each pair. Temporary requests are never saved automatically.
- Watch or listen to videos — use a video's own audio track, or pair muted video with library audio; Subsonic video browsing, details, streaming, HLS and captions are supported.
- Migrate from / push to another Subsonic server — browser-driven clone pulls metadata, audio bytes, user accounts (with each user's own starred items and playlists), playlists, and stars from an upstream Subsonic-compatible server; resumable via a local browser cache so a cancelled or interrupted run picks up where it left off instead of starting over. The reverse direction pushes local stars/playlists back upstream.
- Tag editor — read/write ID3v2 (MP3), VORBIS_COMMENT (FLAC/OGG), batch operations, keyword semantics (
{null}/{write}/{export}) - Metadata scraping — NetEase / QQ Music / Kugou public APIs, frontend-driven, results submitted back to the server
- Incremental WebDAV scanning — ETag + Last-Modified diff; unchanged files skipped; deduplication key prevents double-dispatch
- Feature flags — all major behaviours toggleable at runtime via D1, with 60-second in-isolate memory cache (zero KV cost)
- Cloudflare API integration — push Worker secrets, manage cron triggers, and read analytics without redeploying
- Cross-origin isolation — COOP/COEP headers for SharedArrayBuffer (required by ffmpeg.wasm)
- Anti-loop chain —
esChainmarker prevents A→B→A proxy loops between EdgeSonic instances - SPA version detection — long-lived tabs are prompted to refresh after a Worker deploy
- Persistent audio cache — completed tracks are cached in IndexedDB for offline-friendly replay; capacity and eviction are configurable in Settings
Open Tools → K歌模式 / Karaoke mode. The deployment needs a KTV_ROOMS → KtvRoom SQLite Durable Object binding and migration, as shown in worker/wrangler.toml.example. Apply worker/migrations/0043_videos.sql to an existing database; fresh installations include these tables in Schema.sql. Rooms expire after twelve hours or five minutes without a controller heartbeat. Fullscreen stage controls are hidden until interaction; the bare, translucent upper-right QR is shown by default and can be toggled independently. It uses H error correction and a short /#/k?c=123456 link; guests can also open /#/k and type the six-digit room code.
Full playback uses the optional MediaContainer binding and the included ffmpeg/yt-dlp image. It is deployed with the Worker, without a separate public media service or shared-key configuration. The container needs temporary disk and platform network access; native video preparation accepts files up to 1 GiB. The release includes the image context and publishes an immutable media image for container-aware installation. Existing installations need the new binding and migration provisioned through Wrangler before code-only updates can use full mode.
Without the container, compatibility mode plays library audio and browser-supported video files. Its optional iframe switch also accepts standalone YouTube/Bilibili videos or library audio plus muted iframe. Switching destroys the iframe; EdgeSonic cannot control its timeline, infer its ending or guarantee audio/video synchronization. The embedded player may limit quality, login, autoplay or playback. Browser isolation/privacy settings can further restrict embeds.
Mobile guests can search the library, search YouTube/Bilibili in full mode, and paste video URLs, short links or BV/AV IDs. External requests stay in the room until the host explicitly saves them. Full mode supports Bilibili QR authorization and explicit Netscape cookie-file import (including YouTube). Credentials are scoped to the host, encrypted through the private container Durable Object and never exposed to guests. Account benefits depend on actual platform entitlements; authentication does not bypass DRM or every playback restriction. Disconnecting or replacing authorization invalidates prepared streams. See yt-dlp authentication support.
Initial setup of these resources currently requires the CLI; the existing in-app updater preserves configured Durable Object bindings. Release database patches and installer resource declarations must also be checked when packaging a release.
No local toolchain is required. Open Overture, which is preconfigured for this repository, sign in with Cloudflare when prompted, and follow the browser-based steps to deploy the published EdgeSonic package. The wizard provisions or reuses the resources requested by the package, including D1 and R2.
Prefer to build and deploy from your own machine (e.g. while developing)? Use the Wrangler CLI flow below.
- Node.js 20+
- Workspace Wrangler CLI (
pnpm exec wrangler); workspace installs provide the pinned CLI. - A Cloudflare account with:
- D1 database (
edgesonic-db) - R2 bucket (
edgesonic-storage)
- D1 database (
git clone https://github.com/lsy-404/edgesonic.git
cd edgesonic
cp worker/wrangler.toml.example worker/wrangler.toml
# Edit worker/wrangler.toml — fill in account_id, database_id, R2 bucket name, INSTANCE_ID, domainworker/wrangler.toml is gitignored — it contains private resource IDs and must never be committed.
# Create the database (first time only)
cd worker
wrangler d1 create edgesonic-db
# Apply schema
wrangler d1 execute edgesonic-db --remote --file migrations/Schema.sqlSee worker/SECRETS.md for details. At minimum:
cd worker
wrangler secret put WORK_UPLOAD_HMAC_KEY # random 48-byte base64Optional — one Custom Token yields all three secrets at once (Workers + R2 Object Read permission
groups on the same token; see docs/DEPLOY_BY_AGENT.md §3.5 for the
click-through). This enables R2 presigned direct streaming, the in-app Cloudflare integration, and
Cloudflare Images Transformations (on-demand cover thumbnailing):
wrangler secret put CF_API_TOKEN # token value (Bearer string)
wrangler secret put R2_ACCESS_KEY_ID # Access Key ID = token id
wrangler secret put R2_SECRET_ACCESS_KEY # Secret Access Key = SHA-256(token value)
wrangler secret put CF_ACCOUNT_IDAfter pushing CF_API_TOKEN, also enable Images Transformations on your zone
(dash.cloudflare.com/<account-id>/images/transformations → select zone → Enable) so the
IMAGES binding actually resizes covers instead of falling back to the original bytes.
./deploy.shThe script builds the Vue frontend and bundles it with the Worker via [assets]. When CLOUDFLARE_API_TOKEN is present, it also restores the default cron trigger after deployment.
Create the first administrator before signing in:
wrangler d1 execute edgesonic-db --remote --command \
"INSERT INTO users (username, master_password, level) VALUES ('admin', hex(sha256('yourpassword')), 3)"The technical reference lives under docs/:
| Doc | Covers |
|---|---|
DEPLOY_BY_AGENT.md |
Self-contained deploy runbook for AI coding agents — precompiled release package, no local build |
ARCHITECTURE.md |
Monorepo layout, storage backend model, adding an S3-compatible source |
DEVELOPMENT.md |
Dev servers, type-checking, running tests, applying the DB schema |
worker/SECRETS.md |
Worker secrets and optional R2 presigned streaming |
worker/CF_CRON.md |
Runtime-managed cron schedules |
If you are an AI agent asked to deploy this project, follow
docs/DEPLOY_BY_AGENT.md.