diff options
Diffstat (limited to 'javascript/videojs/src/js/tracks/text-track.js')
| -rw-r--r-- | javascript/videojs/src/js/tracks/text-track.js | 464 |
1 files changed, 0 insertions, 464 deletions
diff --git a/javascript/videojs/src/js/tracks/text-track.js b/javascript/videojs/src/js/tracks/text-track.js deleted file mode 100644 index 6a2f5c4..0000000 --- a/javascript/videojs/src/js/tracks/text-track.js +++ /dev/null @@ -1,464 +0,0 @@ -/** - * @file text-track.js - */ -import TextTrackCueList from './text-track-cue-list'; -import * as Fn from '../utils/fn.js'; -import {TextTrackKind, TextTrackMode} from './track-enums'; -import log from '../utils/log.js'; -import window from 'global/window'; -import Track from './track.js'; -import textTrackConverter from './text-track-list-converter.js'; -import { isCrossOrigin } from '../utils/url.js'; -import XHR from '@videojs/xhr'; -import {merge} from '../utils/obj'; - -/** @import Tech from '../tech/tech' */ - -/** - * Takes a webvtt file contents and parses it into cues - * - * @param {string} srcContent - * webVTT file contents - * - * @param {TextTrack} track - * TextTrack to add cues to. Cues come from the srcContent. - * - * @private - */ -const parseCues = function(srcContent, track) { - const parser = new window.WebVTT.Parser( - window, - window.vttjs, - window.WebVTT.StringDecoder() - ); - const errors = []; - - parser.oncue = function(cue) { - track.addCue(cue); - }; - - parser.onparsingerror = function(error) { - errors.push(error); - }; - - parser.onflush = function() { - track.trigger({ - type: 'loadeddata', - target: track - }); - }; - - parser.parse(srcContent); - if (errors.length > 0) { - if (window.console && window.console.groupCollapsed) { - window.console.groupCollapsed(`Text Track parsing errors for ${track.src}`); - } - errors.forEach((error) => log.error(error)); - if (window.console && window.console.groupEnd) { - window.console.groupEnd(); - } - } - - parser.flush(); -}; - -/** - * Load a `TextTrack` from a specified url. - * - * @param {string} src - * Url to load track from. - * - * @param {TextTrack} track - * Track to add cues to. Comes from the content at the end of `url`. - * - * @private - */ -const loadTrack = function(src, track) { - const opts = { - uri: src - }; - const crossOrigin = isCrossOrigin(src); - - if (crossOrigin) { - opts.cors = crossOrigin; - } - - const withCredentials = track.tech_.crossOrigin() === 'use-credentials'; - - if (withCredentials) { - opts.withCredentials = withCredentials; - } - - XHR(opts, Fn.bind_(this, function(err, response, responseBody) { - if (err) { - return log.error(err, response); - } - - 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') { - if (track.tech_) { - // to prevent use before define eslint error, we define loadHandler - // as a let here - track.tech_.any(['vttjsloaded', 'vttjserror'], (event) => { - if (event.type === 'vttjserror') { - log.error(`vttjs failed to load, stopping trying to process ${track.src}`); - return; - } - return parseCues(responseBody, track); - }); - } - } else { - parseCues(responseBody, track); - } - - })); -}; - -/** - * A representation of a single `TextTrack`. - * - * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrack} - * @extends Track - */ -class TextTrack extends Track { - - /** - * Create an instance of this class. - * - * @param {Object} options={} - * Object of option names and values - * - * @param {Tech} options.tech - * A reference to the tech that owns this TextTrack. - * - * @param {TextTrack~Kind} [options.kind='subtitles'] - * A valid text track kind. - * - * @param {TextTrack~Mode} [options.mode='disabled'] - * A valid text track mode. - * - * @param {string} [options.id='vjs_track_' + Guid.newGUID()] - * A unique id for this TextTrack. - * - * @param {string} [options.label=''] - * The menu label for this track. - * - * @param {string} [options.language=''] - * A valid two character language code. - * - * @param {string} [options.srclang=''] - * A valid two character language code. An alternative, but deprioritized - * version of `options.language` - * - * @param {string} [options.src] - * A url to TextTrack cues. - * - * @param {boolean} [options.default] - * If this track should default to on or off. - */ - constructor(options = {}) { - if (!options.tech) { - throw new Error('A tech was not provided.'); - } - - const settings = merge(options, { - kind: TextTrackKind[options.kind] || 'subtitles', - language: options.language || options.srclang || '' - }); - let mode = TextTrackMode[settings.mode] || 'disabled'; - const default_ = settings.default; - - if (settings.kind === 'metadata' || settings.kind === 'chapters') { - mode = 'hidden'; - } - super(settings); - - this.tech_ = settings.tech; - - this.cues_ = []; - this.activeCues_ = []; - - this.preload_ = this.tech_.preloadTextTracks !== false; - - const cues = new TextTrackCueList(this.cues_); - const activeCues = new TextTrackCueList(this.activeCues_); - let changed = false; - - this.timeupdateHandler = Fn.bind_(this, function(event = {}) { - if (this.tech_.isDisposed()) { - return; - } - - if (!this.tech_.isReady_) { - if (event.type !== 'timeupdate') { - this.rvf_ = this.tech_.requestVideoFrameCallback(this.timeupdateHandler); - } - - return; - } - - // Accessing this.activeCues for the side-effects of updating itself - // due to its nature as a getter function. Do not remove or cues will - // stop updating! - // Use the setter to prevent deletion from uglify (pure_getters rule) - this.activeCues = this.activeCues; - if (changed) { - this.trigger('cuechange'); - changed = false; - } - - if (event.type !== 'timeupdate') { - this.rvf_ = this.tech_.requestVideoFrameCallback(this.timeupdateHandler); - } - - }); - - const disposeHandler = () => { - this.stopTracking(); - }; - - this.tech_.one('dispose', disposeHandler); - if (mode !== 'disabled') { - this.startTracking(); - } - - Object.defineProperties(this, { - /** - * @memberof TextTrack - * @member {boolean} default - * If this track was set to be on or off by default. Cannot be changed after - * creation. - * @instance - * - * @readonly - */ - default: { - get() { - return default_; - }, - set() {} - }, - - /** - * @memberof TextTrack - * @member {string} mode - * Set the mode of this TextTrack to a valid {@link TextTrack~Mode}. Will - * not be set if setting to an invalid mode. - * @instance - * - * @fires TextTrack#modechange - */ - mode: { - get() { - return mode; - }, - set(newMode) { - if (!TextTrackMode[newMode]) { - return; - } - if (mode === newMode) { - return; - } - - mode = newMode; - if (!this.preload_ && mode !== 'disabled' && this.cues.length === 0) { - // On-demand load. - loadTrack(this.src, this); - } - this.stopTracking(); - - if (mode !== 'disabled') { - this.startTracking(); - } - /** - * An event that fires when mode changes on this track. This allows - * the TextTrackList that holds this track to act accordingly. - * - * > Note: This is not part of the spec! - * - * @event TextTrack#modechange - * @type {Event} - */ - this.trigger('modechange'); - - } - }, - - /** - * @memberof TextTrack - * @member {TextTrackCueList} cues - * The text track cue list for this TextTrack. - * @instance - */ - cues: { - get() { - if (!this.loaded_) { - return null; - } - - return cues; - }, - set() {} - }, - - /** - * @memberof TextTrack - * @member {TextTrackCueList} activeCues - * The list text track cues that are currently active for this TextTrack. - * @instance - */ - activeCues: { - get() { - if (!this.loaded_) { - return null; - } - - // nothing to do - if (this.cues.length === 0) { - return activeCues; - } - - const ct = this.tech_.currentTime(); - const active = []; - - for (let i = 0, l = this.cues.length; i < l; i++) { - const cue = this.cues[i]; - - if (cue.startTime <= ct && cue.endTime >= ct) { - active.push(cue); - } - } - - changed = false; - - if (active.length !== this.activeCues_.length) { - changed = true; - } else { - for (let i = 0; i < active.length; i++) { - if (this.activeCues_.indexOf(active[i]) === -1) { - changed = true; - } - } - } - - this.activeCues_ = active; - activeCues.setCues_(this.activeCues_); - - return activeCues; - }, - - // /!\ Keep this setter empty (see the timeupdate handler above) - set() {} - } - }); - - if (settings.src) { - this.src = settings.src; - if (!this.preload_) { - // Tracks will load on-demand. - // Act like we're loaded for other purposes. - this.loaded_ = true; - } - if (this.preload_ || (settings.kind !== 'subtitles' && settings.kind !== 'captions')) { - loadTrack(this.src, this); - } - } else { - this.loaded_ = true; - } - } - - startTracking() { - // More precise cues based on requestVideoFrameCallback with a requestAnimationFram fallback - this.rvf_ = this.tech_.requestVideoFrameCallback(this.timeupdateHandler); - // Also listen to timeupdate in case rVFC/rAF stops (window in background, audio in video el) - this.tech_.on('timeupdate', this.timeupdateHandler); - } - - stopTracking() { - if (this.rvf_) { - this.tech_.cancelVideoFrameCallback(this.rvf_); - this.rvf_ = undefined; - } - this.tech_.off('timeupdate', this.timeupdateHandler); - } - - /** - * Add a cue to the internal list of cues. - * - * @param {TextTrack~Cue} cue - * The cue to add to our internal list - */ - addCue(originalCue) { - let cue = originalCue; - - // Testing if the cue is a VTTCue in a way that survives minification - if (!('getCueAsHTML' in cue)) { - cue = new window.vttjs.VTTCue(originalCue.startTime, originalCue.endTime, originalCue.text); - - for (const prop in originalCue) { - if (!(prop in cue)) { - cue[prop] = originalCue[prop]; - } - } - - // make sure that `id` is copied over - cue.id = originalCue.id; - cue.originalCue_ = originalCue; - } - - const tracks = this.tech_.textTracks(); - - for (let i = 0; i < tracks.length; i++) { - if (tracks[i] !== this) { - tracks[i].removeCue(cue); - } - } - - this.cues_.push(cue); - this.cues.setCues_(this.cues_); - } - - /** - * Creates a copy of the text track and makes it serializable - * by removing circular dependencies. - * - * @return {Object} The track information as a serializable object - */ - toJSON() { - return textTrackConverter.trackToJson(this); - } - - /** - * Remove a cue from our internal list - * - * @param {TextTrack~Cue} removeCue - * The cue to remove from our internal list - */ - removeCue(removeCue) { - let i = this.cues_.length; - - while (i--) { - const cue = this.cues_[i]; - - if (cue === removeCue || (cue.originalCue_ && cue.originalCue_ === removeCue)) { - this.cues_.splice(i, 1); - this.cues.setCues_(this.cues_); - break; - } - } - } -} - -/** - * cuechange - One or more cues in the track have become active or stopped being active. - * - * @protected - */ -TextTrack.prototype.allowedEvents_ = { - cuechange: 'cuechange' -}; - -export default TextTrack; |
