All posts
HLSProduct19 Jun 2025 · 2 min read

Four hours from a subdomains demo to an HLS tool

JPJean Perez

The first commit in this repo is Vercel's Platforms starter kit: a multi-tenant subdomains demo, pulled straight from vercel.com/new. app/s/[subdomain]/page.tsx, a subdomain signup form, an admin dashboard for managing tenants. Nothing about video anywhere in it.

Four hours later, none of that was left. The next commit, "Initial HLS Commit," deletes the subdomain pages and the signup form and replaces them with lib/storage.ts, an upload API route, and a video player. The README got rewritten to match: "HLS Streaming Service - Proof of Concept," with a roadmap that read "Phase 1: VOD HLS (Implemented)" and "Phase 2: Live Streaming (Coming Soon)."

Live streaming never got built. The walk-back from that roadmap started the next day.

One piece of the subdomains starter survived the gutting by accident. The early GCS config that same afternoon fell back to a hardcoded default project id, personalportfolio-4caf3, from an earlier portfolio project. It stayed in the config for days.

Not a streaming platform

The commit on June 18 carries its own explanation in the title: "Update messaging: BeemMeUp is an HLS analysis tool, not a streaming platform." It rewrites the landing page, the upload demo and the analyze page, and adds a footer that lists what the project was running on: Next.js 15 and TypeScript on the frontend, Vercel Edge Functions on the backend, Google Cloud Transcoder for the HLS output, Google Cloud Storage and Redis for storage, and an FFprobe service for the inspection itself.

It went from "streaming service" to "analysis tool" on day two, before anyone outside had used it.

What the analyzer actually did

By the end of that first stretch, three pieces were real.

  • Upload. Signed GCS URLs and a direct browser-to-bucket upload, no server sitting in the middle of the file transfer. It started as a single signed-URL request and grew a chunked-upload path the same day, for files too large to hand off in one request.
  • A transcode ladder. Google Cloud Transcoder, wired in the same day, turned an uploaded file into multiple HLS renditions instead of one fixed quality.
  • Segment probing. An API route that pulls individual segments out of the HLS output and runs FFprobe against each one, surfacing codec, bitrate, and container details per segment instead of a single summary for the whole file.

The segment probing got extended fast. Within a day it handled fragmented MP4 as well as MPEG-TS, which meant solving a real gap: an fMP4 media segment isn't self-describing the way a .ts segment is. The codec parameters live in a separate initialization segment, not in the media segment itself, so probing a media segment alone gives FFprobe nothing usable. The fix was to fetch the init segment first and hand FFprobe the two concatenated together:

GET init-segment.mp4   (moov box: codec config, resolution, profile)
GET segment003.m4s      (media data only, no codec config)
→ concatenate init + media, then run ffprobe against the combined bytes

That change touched 72 lines in the probe route and 81 in the Cloud Run FFprobe service that backs it, plus a rewrite of how the analyze page displays fMP4-specific compliance notes. Before it, the analyzer only understood .ts segments.

Then nothing for six months

Two days in, the multi-tenant starter and the live-streaming roadmap were both gone. What was left takes a video file, runs it through a real transcode ladder and tells you what's in each HLS segment it produced.

After June the commit log goes quiet until December, when the next thing to land is a plan document for a tool called What The FFMPEG.