I have a video file on my local disk. I also have some subtitles (in HTML5's WebVTT format).
I want to create an HTML file to play that video with subtitles, all from the local filesystem.
Loading an external VTT file from the local filesystem fails due to same-origin policy.
Disable cross-origin protection in the browser.
While it works, it is troublesome and dangerous. Please don't do it.
Try embedding the VTT file as a data:
URI inside <track src="">
.
Unfortunately, I still got issues related to cross-origin, so I abandoned this idea.
I had trouble in 2016, but now in 2024 this solution works fine! According to the comments, it has been working fine since 2022 or earlier. However, this solution has a few drawbacks:
data:
URIs are ugly. The nice human-readable subtitle files have to be converted to an ugly string of characters.data:
URIs might have size limits, which means longer subtitles may not work correctly.- Due to encoding,
data:
URIs are larger than raw VTT files.
It still has a few advantages, though:
- No JavaScript required, just plain HTML.
- Works fine enough for shorter subtitles.
Try embedding the VTT file inside the HTML file, generating a Blob URL, and adding a new <track src="">
to the video.
Unfortunately, it did not work for me.
I had trouble in 2016, but now in 2024 this solution works fine! Probably because the VTT format doesn't allow any leading whitespace, so we need to use .trimStart()
when extracting the text from the <script>
tag. Thanks to @hugoheden for figuring it out!
Try embedding the SRT file inside the HTML file and use JavaScript code to dynamically parse and display the subtitles.
That was my previous attempt, I used a highly modified version of VideoSub. Still, this solution felt a bit bloated, specially because it runs JavaScript code while the video is playing. In addition, it was insecure, because it added the subtitle text directly through innerHTML
.
Try embedding the VTT file inside the HTML file and dynamically create a new Text Track when the document loads.
This is the solution implemented in this Gist. It is relatively small (the bigger portion is the VTT parser), and the JavaScript code runs only once (when the document is loading).
The text style can be tweaked using video::cue
selector. Styling can be refined, for instance, we can set the style of underlined subtitles through video::cue(u)
selector.
These examples in this Gist are assuming you have only one subtitle track and you want it to be enabled by default. Adding support for multiple tracks is left as an exercise to the reader. (Or just look at the comments down below, someone might have implemented it.)
Just as an FYI... I was able to embed a VTT file directly into an HTML page (Solution 2). It requires that you base64 encode the VTT file's content and copy that into the src of the track tag.
Example:
<track label="English" kind="subtitles" srclang="en" src="data:text/plain;base64,V0VCVlRUCgoxC">
Note: Everything after the "base64," is usually a very long text of gibberish which is the converted data of any file you base64 encode.
It just makes it nearly impossible to directly manipulate unless you are a machine... or you need to keep a copy of the VTT around and re-encode any changes you may make in the future.
It can be used for other files you may want to embed, outside of merely VTTs, such as images, text files, and even binary data that I used to embed a "tape" file for a localized web-based emulator of some old computer, recently. You just need to use the correct "data:" header for the file you are working with, such as:
data:text/plain;
data:image/png;
etc...