MidnightMM: a streaming platform for Myanmar audiences
A multi-channel streaming platform with uploaded films and series, free YouTube channels, live broadcasts and one MCoin wallet.
- Engagement
- Client product
- Role
- Technical lead, built and runs the platform, sits on the product's decision-making board.
- Status
- LiveVisit ↗
In plain words
Before
The product team wanted one place where Myanmar audiences could watch uploaded films and series, follow free YouTube channels and join live broadcasts, with channel owners running their own channels and earning from them. Paying for viewing had to be fair and hard to abuse, and video had to stay private without the servers carrying every byte.
What I built
I built and run MidnightMM with the product team as their technical lead. Viewers browse one catalogue, save favourites, pick up where they left off and pay from a single MCoin wallet, in English or Burmese, on the web or as an installable app.
Channel owners upload films and series through a studio, and the platform prepares them for streaming in the background. Owners can add their YouTube channels, which play through the official player once ownership is verified, and they can go live from the browser with a camera or a shared screen once live streaming is switched on for their channel. Viewers can tip and donate, and owners see their earnings and request payouts.
Payments are confirmed by an administrator rather than taken automatically, by the team’s choice. Administrators manage accounts, channels and settlements from one panel.
Under the hood
Architecture
- Next.js web
- NestJS API
- FFmpeg → HLS
- Private R2
- Metered edge Worker
Stack
- Next.js web app (installable, English and Burmese)
- NestJS API
- PostgreSQL with Prisma
- FFmpeg worker producing HLS
- LiveKit SFU for live broadcasts
- Cloudflare R2 (private bucket) and a Cloudflare Worker
- Docker Compose, Nginx, GitHub Actions
Decisions
- Uploads go to a private R2 bucket in resumable parts. An FFmpeg worker converts each MP4 to HLS and deletes the original only once the processed stream is ready.
- Playback is charged per segment. A Cloudflare Worker swaps reusable download links for one-use, short-lived permissions and debits the wallet atomically through a signed API callback, so replays are rejected and video bytes stay off the app server.
- Live broadcasts use LiveKit as an SFU with short, room-scoped tokens. Broadcasters cannot subscribe, viewers cannot publish, chat is relayed by the server, and permissions are reconciled continuously.
- Sign-in uses HttpOnly cookies, short-lived access tokens and rotating refresh credentials stored only as hashes per device, with replay detection, device revocation and optional MFA for super admins.
- Production transcoding runs in a credential-free, network-disabled decoder container, and app containers run read-only with dropped capabilities.