Skip to content
Browse files

@gkatsev changed emulated tracks to in novtt to wait for vttjs to loa…

…d or error before parsing. closes #3181
1 parent 0b26d83 commit e2c8c125a2b410216c9c1e6d38acdeedea30fe21 @gkatsev gkatsev committed
Showing with 146 additions and 4 deletions.
  1. +1 −1 CHANGELOG.md
  2. +4 −0 build/grunt.js
  3. +6 −0 src/js/tech/tech.js
  4. +11 −3 src/js/tracks/text-track.js
  5. +124 −0 test/unit/tracks/text-track.test.js
View
2 CHANGELOG.md
@@ -2,7 +2,7 @@ CHANGELOG
=========
## HEAD (Unreleased)
-_(none)_
+* @gkatsev changed emulated tracks to in novtt to wait for vttjs to load or error before parsing ([view](https://github.com/videojs/video.js/pull/3181))
--------------------
View
4 build/grunt.js
@@ -149,6 +149,10 @@ module.exports = function(grunt) {
},
dist: {},
watch: {
+ novtt: {
+ files: ['build/temp/video.js'],
+ tasks: ['concat:novtt']
+ },
minify: {
files: ['build/temp/video.js'],
tasks: ['uglify']
View
6 src/js/tech/tech.js
@@ -327,6 +327,12 @@ class Tech extends Component {
if (!window['WebVTT'] && this.el().parentNode != null) {
let script = document.createElement('script');
script.src = this.options_['vtt.js'] || '../node_modules/videojs-vtt.js/dist/vtt.js';
+ script.onload = () => {
+ this.trigger('vttjsloaded');
+ };
+ script.onerror = () => {
+ this.trigger('vttjserror');
+ };
this.el().parentNode.appendChild(script);
window['WebVTT'] = true;
}
View
14 src/js/tracks/text-track.js
@@ -67,14 +67,22 @@ const loadTrack = function(src, track) {
track.loaded_ = true;
+ // Make sure that vttjs has loaded, otherwise, wait till it finished loading
// NOTE: this is only used for the alt/video.novtt.js build
if (typeof window.WebVTT !== 'function') {
- window.setTimeout(function() {
- parseCues(responseBody, track);
- }, 100);
+ if (track.tech_) {
+ let loadHandler = () => parseCues(responseBody, track);
+ track.tech_.on('vttjsloaded', loadHandler);
+ track.tech_.on('vttjserror', () => {
+ log.error(`vttjs failed to load, stopping trying to process ${track.src}`);
+ track.tech_.off('vttjsloaded', loadHandler);
+ });
+
+ }
} else {
parseCues(responseBody, track);
}
+
}));
};
View
124 test/unit/tracks/text-track.test.js
@@ -1,5 +1,8 @@
+import window from 'global/window';
+import EventTarget from '../../../src/js/event-target.js';
import TextTrack from '../../../src/js/tracks/text-track.js';
import TestHelpers from '../test-helpers.js';
+import log from '../../../src/js/utils/log.js';
const defaultTech = {
textTracks() {},
@@ -254,3 +257,124 @@ test('fires cuechange when cues become active and inactive', function() {
player.dispose();
});
+
+test('tracks are parsed if vttjs is loaded', function() {
+ const clock = sinon.useFakeTimers();
+ const oldVTT = window.WebVTT;
+ let parserCreated = false;
+
+ window.WebVTT = () => {};
+ window.WebVTT.StringDecoder = () => {};
+ window.WebVTT.Parser = () => {
+ parserCreated = true;
+ return {
+ oncue() {},
+ onparsingerror() {},
+ onflush() {},
+ parse() {},
+ flush() {}
+ };
+ };
+
+ let xhr;
+ window.xhr.onCreate = (newXhr) => xhr = newXhr;
+
+ let tt = new TextTrack({
+ tech: defaultTech,
+ src: 'http://example.com'
+ });
+
+ xhr.respond(200, {}, 'WebVTT\n');
+
+ ok(parserCreated, 'WebVTT is loaded, so we can just parse');
+
+ clock.restore();
+ window.WebVTT = oldVTT;
+});
+
+test('tracks are parsed once vttjs is loaded', function() {
+ const clock = sinon.useFakeTimers();
+ const oldVTT = window.WebVTT;
+ let parserCreated = false;
+
+ window.WebVTT = true;
+
+ let xhr;
+ window.xhr.onCreate = (newXhr) => xhr = newXhr;
+
+ let testTech = new EventTarget();
+ testTech.textTracks = () => {};
+ testTech.currentTime = () => {};
+
+ let tt = new TextTrack({
+ tech: testTech,
+ src: 'http://example.com'
+ });
+
+ xhr.respond(200, {}, 'WebVTT\n');
+
+ ok(!parserCreated, 'WebVTT is not loaded, do not try to parse yet');
+
+ clock.tick(100);
+ ok(!parserCreated, 'WebVTT still not loaded, do not try to parse yet');
+
+ window.WebVTT = () => {};
+ window.WebVTT.StringDecoder = () => {};
+ window.WebVTT.Parser = () => {
+ parserCreated = true;
+ return {
+ oncue() {},
+ onparsingerror() {},
+ onflush() {},
+ parse() {},
+ flush() {}
+ };
+ };
+
+ testTech.trigger('vttjsloaded');
+ ok(parserCreated, 'WebVTT is loaded, so we can parse now');
+
+ clock.restore();
+ window.WebVTT = oldVTT;
+});
+
+test('stops processing if vttjs loading errored out', function() {
+ const clock = sinon.useFakeTimers();
+ sinon.stub(log, 'error');
+ const oldVTT = window.WebVTT;
+ let parserCreated = false;
+
+ window.WebVTT = true;
+
+ let xhr;
+ window.xhr.onCreate = (newXhr) => xhr = newXhr;
+
+ let testTech = new EventTarget();
+ testTech.textTracks = () => {};
+ testTech.currentTime = () => {};
+
+ sinon.stub(testTech, 'off');
+ testTech.off.withArgs('vttjsloaded');
+
+ let tt = new TextTrack({
+ tech: testTech,
+ src: 'http://example.com'
+ });
+
+ xhr.respond(200, {}, 'WebVTT\n');
+
+ ok(!parserCreated, 'WebVTT is not loaded, do not try to parse yet');
+
+ testTech.trigger('vttjserror');
+ let errorSpyCall = log.error.getCall(0);
+ let offSpyCall = testTech.off.getCall(0);
+
+ ok(errorSpyCall.calledWithMatch('vttjs failed to load, stopping trying to process'),
+ 'vttjs failed to load, so, we logged an error');
+ ok(!parserCreated, 'WebVTT is not loaded, do not try to parse yet');
+ ok(offSpyCall, 'tech.off was called');
+
+ clock.restore();
+ log.error.restore();
+ window.WebVTT = oldVTT;
+});

0 comments on commit e2c8c12

Please sign in to comment.
Something went wrong with that request. Please try again.