Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Viewing HTML5 video with captions offline

I am trying to implement an HTML5 video player for viewing local videos using a local HTML file, and I would like to have VTT captions and subtitles capability.

I am currently using VideoJS for playback; however, my question is not implementation specific. When I attempt to use the VTT files, I get a cross-origin error saying that the files cannot be used. (This depends on the browser though, as IE 10 seems to play just fine while Firefox and Chrome throw the error.)

I would like to have a cross-browser way of doing this, and I would be interested in any solutions/work arounds that anyone has found. One solution I am aware of would be to use Node Web Kit to create web-server hybrid package; however, I am not able to use this solution, as I want to keep my solution platform independent and installation free.

like image 823
losmescaleros Avatar asked May 08 '14 22:05

losmescaleros


People also ask

How do I view HTML5 video?

The webmasters need to use special HTML5 coding and include WebM, MP4 and OGG formats on their web pages. Before HTML5 videos were only played using the Flash Player. You can view HTML5 videos on all popular browsers such as Google Chrome, Internet Explorer, Mozilla Firefox, and Safari.

What is the difference between captions and subtitles?

They differ from each other in definition and purpose – captions are designed for viewers who cannot hear the audio in a video, while subtitles are designed for viewers who can hear, but do not understand the language being spoken in the video.


1 Answers

I've hacked up a solution! It requires only two files:

  • The video file.
  • The HTML file, containing:
    • The subtitles in either VTT or SRT format.
    • A script to parse the embedded VTT text and add it to the video.

Get my solution from this GitHub Gist, or from below:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Playing a local video</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<style>
html, body {
    background: black;
    color: white;
}
html, body, video {
    padding: 0;
    margin: 0;
}
video {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    width: 100%;
    height: 100%;
}
</style>
</head>
<body>

<video controls>
<source src="Your local video file.mp4" type="video/mp4">
</video>

<!-- Check https://quuz.org/webvtt/ for validation. -->
<script type="text/vtt" id="subtitle" data-label="English" data-lang="en">
WEBVTT

1
00:00:02.500 --> 00:00:05.250
Instead of loading an external .vtt file,

2
00:00:05.250 --> 00:00:09.750
The workaround is to embed it inside a script tag,

3
00:00:10.001 --> 00:00:15.000
And then parse it using JavaScript
and dynamically add it as a new TextTrack.

</script>

<script>
function parse_timestamp(s) {
    var match = s.match(/^(?:([0-9]{2,}):)?([0-5][0-9]):([0-5][0-9][.,][0-9]{0,3})/);
    if (match == null) {
        throw 'Invalid timestamp format: ' + s;
    }
    var hours = parseInt(match[1] || "0", 10);
    var minutes = parseInt(match[2], 10);
    var seconds = parseFloat(match[3].replace(',', '.'));
    return seconds + 60 * minutes + 60 * 60 * hours;
}

// https://w3c.github.io/webvtt/
// https://developer.mozilla.org/en/docs/Web/API/Web_Video_Text_Tracks_Format
// https://en.wikipedia.org/wiki/WebVTT
//
// For better parsers, look at:
// https://github.com/annevk/webvtt
// https://github.com/mozilla/vtt.js
function quick_and_dirty_vtt_or_srt_parser(vtt) {
    var lines = vtt.trim().replace('\r\n', '\n').split(/[\r\n]/).map(function(line) {
        return line.trim();
    });
    var cues = [];
    var start = null;
    var end = null;
    var payload = null;
    for (var i = 0; i < lines.length; i++) {
        if (lines[i].indexOf('-->') >= 0) {
            var splitted = lines[i].split(/[ \t]+-->[ \t]+/);
            if (splitted.length != 2) {
                throw 'Error when splitting "-->": ' + lines[i];
            }

            // Already ignoring anything past the "end" timestamp (i.e. cue settings).
            start = parse_timestamp(splitted[0]);
            end = parse_timestamp(splitted[1]);
        } else if (lines[i] == '') {
            if (start && end) {
                var cue = new VTTCue(start, end, payload);
                cues.push(cue);
                start = null;
                end = null;
                payload = null;
            }
        } else if(start && end) {
            if (payload == null) {
                payload = lines[i];
            } else {
                payload += '\n' + lines[i];
            }
        }
    }

    return cues;
}

function init() {
    // http://www.html5rocks.com/en/tutorials/track/basics/
    // https://www.iandevlin.com/blog/2015/02/javascript/dynamically-adding-text-tracks-to-html5-video
    var video = document.querySelector('video');
    var subtitle = document.getElementById('subtitle');
    var track = video.addTextTrack('subtitles', subtitle.dataset.label, subtitle.dataset.lang);
    track.mode = "showing";
    quick_and_dirty_vtt_or_srt_parser(subtitle.innerHTML).map(function(cue) {
        track.addCue(cue);
    });
}
init();
</script>

</body>
</html>

Alternative approaches:

  • Use a JavaScript video player to dynamically update the DOM to display the subtitles. That was my previous approach, still available in this GitHub Gist. I used a heavily modified version of VideoSub v0.9.9 by Thomas Sturm.

  • Use MP4Box.js to build a player that reads embedded subtitles from within the video file. (Try the “Multiplexed Audio/Video/Subtitle (unfragmented, AVC+AAC+WebVTT)” test video in this demo.)

  • Use Subtitle Videoplayer from Chrome Web Store, or maybe build your own Chrome app. Yeah, this is a highly specific alternative and it is not cross-browser.

  • In Chrome, you can disable the security checks by passing a command-line flag. Be careful when doing that!

like image 95
Denilson Sá Maia Avatar answered Oct 04 '22 05:10

Denilson Sá Maia