Developing a Music Streaming Platform
We build music streaming platforms that handle thousands of simultaneous listeners, deliver low-latency playback, and ensure accurate royalty accounting. Our stack includes React, Next.js, PHP/Laravel, PostgreSQL, Elasticsearch, and Cloudflare CDN. With over 5 years of guaranteed experience, we've delivered more than 10 certified projects for independent labels and major media companies. The challenge isn't just serving MP3 over HTTP—it's transcoding audio into multiple bitrates, protecting content from downloads, implementing search across the catalog, and delivering personalized recommendations. We support projects at every stage: from architecture selection to load testing and deployment. Below—our architecture, protocols, and key decisions based on real-world experience.
How to Ensure Low-Latency Playback
The choice of delivery protocol is the first trade-off between latency and complexity.
Progressive download — the simplest option. The file is served over plain HTTP with Range request support. The browser buffers and plays. Suitable for small libraries without strict download restrictions.
location /audio/ { root /var/media; add_header Accept-Ranges bytes; add_header Cache-Control "no-store"; # for DRM } HLS (HTTP Live Streaming) — the production standard. The file is split into 5–10 second segments; the client fetches via a manifest. It supports adaptive bitrate (ABR): the client switches between 128/256/320 kbps depending on the channel. For slicing, we use FFmpeg with the asplit filter.
MPEG-DASH — an alternative to HLS with better DRM support via EME. If label-level content protection is needed, go with DASH + Widevine/FairPlay. More details on protocols can be found in the HTTP Live Streaming documentation.
| Characteristic | HLS | MPEG-DASH |
|---|---|---|
| Browser compatibility | Native in Safari, via players in Chrome/Firefox | Native in Chrome/Edge, via players in Safari |
| DRM support | FairPlay (Safari) + Widevine (via player) | Widevine, PlayReady, FairPlay |
| Implementation complexity | Medium (2x faster to implement) | High |
| Adaptive bitrate | Yes (ABR) | Yes (DASH) |
For most projects, we choose HLS — it's simpler to implement and supported by all modern players (hls.js, Video.js).
How to Protect Content from Illegal Distribution
Signed URLs with short TTLs provide basic protection. We generate URLs with a 60-second lifetime tied to the user's IP:
public function stream(Request $request, int $trackId): JsonResponse { $track = Track::findOrFail($trackId); if (!$track->canStream($this->geoService->getCountry($request->ip()))) { return response()->json(['error' => 'not_available'], 451); } $url = $this->cdn->signedUrl("hls/{$trackId}/master.m3u8", 60, $request->ip()); StreamEvent::dispatch($trackId, $request->user()->id, now()); return response()->json(['url' => $url]); } For labels requiring hardware-level protection, we add DRM via EME. In this case, the CDN (Cloudflare Stream, AWS MediaPackage) handles encryption and license issuance.
Content Processing Pipeline
Uploading a track is not just saving a file—it's a pipeline: Upload → Validation → Transcoding → Waveform → Fingerprint → CDN → DB.
from celery import chain @app.task def process_upload(track_id, raw_path): chain( validate_audio.s(track_id, raw_path), transcode_variants.s(), generate_waveform.s(), fingerprint_audio.s(), push_to_cdn.s(), update_track_status.s('ready') ).delay() We perform transcoding in three passes: 128k AAC (streaming), 320k MP3 (download), FLAC (hi-fi). For each bitrate, we generate HLS segments.
Waveform is a mandatory player element. We use the audiowaveform utility from BBC, rendering it on the frontend via a custom Canvas.
The rights system is a relational model with territory and right type checks:
CREATE TABLE tracks ( id BIGSERIAL PRIMARY KEY, title TEXT NOT NULL, duration_sec INT, isrc CHAR(12), status TEXT DEFAULT 'processing' ); CREATE TABLE track_rights ( track_id BIGINT REFERENCES tracks(id), territory CHAR(2), -- NULL = worldwide right_type TEXT, -- 'stream', 'download', 'sync' holder_id BIGINT, expires_at TIMESTAMPTZ, PRIMARY KEY (track_id, territory, right_type) ); Search and Recommendations
We handle full-text search across the catalog using Elasticsearch with transliteration and phonetic analysis. The recommendation engine is built on collaborative filtering (matrix factorization)—it requires a separate development track.
Scaling and CDN
HLS segments are static files, ideal for CDN caching. Under peak loads (e.g., a popular artist's new release), we use an origin shield—an intermediate cache between the CDN and storage—to prevent S3 from being overwhelmed. The .m3u8 manifests are cached with a short TTL (5–30 seconds), while segments are cached for 365 days with an immutable flag, as filenames include a content hash.
Royalty Accounting
Every playback ≥30 seconds is counted as a monetizable stream (IFPI standard). We collect heartbeat events every 30 seconds via Kafka and aggregate monthly.
Offline Mode (PWA)
For mobile users, we implement caching of audio segments via a Service Worker. Users can download tracks to their library and listen offline. The cache is tied to their account and cleared upon unsubscription.
What's Included in the Work
| Stage | Duration | Result |
|---|---|---|
| Analysis and design | 1–2 weeks | Technical specification, architecture, stack selection |
| Basic streaming implementation | 8–10 weeks | Working player, track upload, HLS transcoding, signed URLs |
| Rights and royalty system | 4–6 weeks | Rights model, CDN integration, stream aggregation |
| Launch and optimization | 2–4 weeks | Load testing, caching, documentation |
Additional modules
Recommendations, PWA, mobile apps, DRM — discussed separately. Typical cost for a full-featured platform starts at $200K, with enterprise versions reaching $500K or more.Our team has over 5 years of proven experience in audio platform development, delivering more than 10 streaming and radio projects, each guaranteed to meet performance and security standards. Contact us to evaluate your project — we'll help you choose the optimal architecture and timeline.







