SRT is not WebVTT: shipping a subtitle converter in a 1.17 MB player
I'm the developer of RKMovies, an ultra-lightweight 4K media player client for Android and Windows (1.17 MB APK, 29.5 MB PC installer). This is a dev diary about the part nobody blogs about: subtitles.
The upstream sources serve a mix of .srt and .vtt files. SRT uses comma decimal separators in timestamps (00:00:01,500 --> 00:00:03,200), WebVTT requires dots. The player library only speaks VTT, so every caption track goes through a converter before it reaches the renderer.
captionVtt() fetches the track text. If it already starts with WEBVTT, it passes the header through but still cleans each cue line. Otherwise it parses SRT blocks: split on blank lines, drop the numeric index line, keep the block only if the timing line contains -->, convert commas to dots, and prefix the output with WEBVTT.
The cleaning half is cleanSubtitleText(). It strips SSA/ASS override tags like {\an8}, removes HTML-ish markup (<i>, <font color=...>, <v Speaker>), decodes entities (&, , '), and turns <br> into real newlines. Most "broken subtitle" reports we got early on were just leftover markup tags rendering as literal text on screen.
For local files (.srt, .vtt, .ass uploads), fileToVtt() runs the same SRT parser over the file contents, so a downloaded subtitle file works with zero server round-trips.
On the render side I hook subtitleBeforeUpdate plus a MutationObserver on the .art-subtitle-line elements to re-clean whatever the library injects into the DOM. Font size, bottom offset and color are driven through CSS variables (--art-subtitle-font-size, --art-subtitle-bottom, --art-subtitle-color) that get recomputed on resize and orientation change, because subtitles on a 6-inch phone held at arm's length need to be bigger than on a TV.
Total cost: about 80 lines of JavaScript. Which is the point. In a player this small, features don't cost APK size, dependencies do. Subtitles in Hindi, Tamil, Telugu and English ship in the box, and the desktop app for the TV runs the same pipeline.
If you want to poke at it: the Android APK is 1.17 MB with MediaCodec hardware decode, and there is no account and no telemetry.
Top comments (1)
The SRT comma-to-dot nightmare is a classic headache. Hooking a MutationObserver to clean up whatever the library injects into the DOM is a brilliantly pragmatic hack—sometimes you just have to patch the render layer in real-time. 80 lines of vanilla JS to handle multiple subtitle formats without adding a single dependency is exactly the kind of engineering flex I love to see.