Have you ever had a project start because of a minor technical annoyance, only to look back later and realize you built a mini-engineering system?
For me, that annoyance was trying to watch high-quality anime on a legacy Smart TV.
Most high-quality anime files are distributed in .mkv containers with complex dual-audio tracks (Japanese/English) and heavy, styled text subtitles (.ass format). Older Smart TVs have very limited built-in media players—they simply refuse to open .mkv files, and they have no idea what to do with styled subtitles.
To solve this, I started a journey that went from manual desktop editing to a full-scale homelab streaming server. Here is how that progression looked:
1. The Manual Era: HandBrake & CPU Melting
My first solution was simple but painful: transcoding. I loaded my media library into HandBrake, selected H.264 video, transcoded the audio into standard AC3 format, and checked the box to "hard-burn" Spanish subtitles directly onto the video frames.
To keep the highest video fidelity, I set HandBrake to a Constant Rate Factor (RF 18.5).
-
The Pro: The output
.mp4file played flawlessly on the oldest smart TVs, and the video quality was pristine. - The Con: Hard-burning subtitles means decoding and re-encoding every single video frame. This put a massive load on my CPU, keeping it pegged at 100% for hours to transcode a single season. It also created massive, duplicated files that wasted storage.
2. The Automation Era: Discovering the Power of FFMPEG
Clicking buttons in a GUI for hundreds of episodes became unsustainable. That’s when I discovered FFMPEG, the command-line media engine that HandBrake actually runs under the hood.
I wrote custom scripts (using PowerShell and Bash) to automate the entire folder-scanning process. The scripts would:
- Scan a directory for
.mkvfiles. - Use
ffprobeto scan the streams and automatically detect which track index contained Spanish (SPA/ESP) subtitles. - Feed that stream index into the FFMPEG
subtitlesfilter and run the H.264 encode automatically.
Now I could convert entire folders with a single command line. But the CPU bottleneck was still there—my computer was still acting as a heater for days on end.
3. The Homelab Era: On-Demand Remuxing (My "Netflix" Competitor)
When I finally migrated my setup into a dedicated homelab server, I knew I had to stop the CPU-melting H.264 transcodes.
The breakthrough came when I realized: Why transcode the video stream at all if the modern browser can decode it natively?
I redesigned my system to perform On-Demand Remuxing instead of full transcoding:
- Video Passthrough: The server copies the H.264 video stream directly (
-c:v copy) without decoding/re-encoding. This is a pure copy-paste operation that takes almost 0% CPU. - Audio Transcoding: It transcodes the audio on the fly to standard stereo AAC—a very light operation.
- Subtitles in the Browser: I pulled the
.asssubtitles out and served them as text. In the browser player, I integrated WebAssembly (SubtitlesOctopus), compiling the native subtitle rendering library to WASM. The browser draws the styled text overlays in real-time over the HTML5<video>player, keeping the beautiful typography without server-side transcoding!
To make this feel like a premium streaming platform, I implemented support for HTTP Range Requests. This allows the browser to request specific byte chunks on the fly. If you click to seek to the middle of an episode, the server immediately jumps to that byte offset and streams from there—instantly.
The Engineering Lessons
What started as a workaround for an old TV taught me the core fundamentals of:
-
Containers vs. Codecs: The difference between a file wrapper (
.mkv/.mp4) and the encoding algorithm (H.264/H.265/Opus). - Text vs. Image-Based Subtitles: Why image-based PGS subtitles from Blu-rays cannot be easily exported to plain text (SRT) without running them through an OCR (Optical Character Recognition) engine.
- Browser Media Delivery: Balancing browser compatibility (H.264/AAC/WebVTT) with backend performance.
If you want to read the full, deep-dive technical breakdown—complete with the exact FFMPEG commands, automation scripts, and system architecture diagrams—check out my latest blog post:
Top comments (0)