224 lines
6.6 KiB
JavaScript
224 lines
6.6 KiB
JavaScript
|
/*! videojs-ass
|
||
|
* Copyright (c) 2014 Sunny Li
|
||
|
* Licensed under the Apache-2.0 license. */
|
||
|
|
||
|
(function (videojs, libjass) {
|
||
|
'use strict';
|
||
|
|
||
|
var vjs_ass = function (options) {
|
||
|
var cur_id = 0,
|
||
|
id_count = 0,
|
||
|
overlay = document.createElement('div'),
|
||
|
clocks = [],
|
||
|
clockRate = options.rate || 1,
|
||
|
delay = options.delay || 0,
|
||
|
player = this,
|
||
|
renderers = [],
|
||
|
rendererSettings = null,
|
||
|
OverlayComponent = null,
|
||
|
assTrackIdMap = {},
|
||
|
tracks = player.textTracks(),
|
||
|
isTrackSwitching = false;
|
||
|
|
||
|
if (!options.src) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
overlay.className = 'vjs-ass';
|
||
|
|
||
|
OverlayComponent = {
|
||
|
name: function () {
|
||
|
return 'AssOverlay';
|
||
|
},
|
||
|
el: function () {
|
||
|
return overlay;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
player.addChild(OverlayComponent, {}, 3);
|
||
|
|
||
|
function getCurrentTime() {
|
||
|
return player.currentTime() - delay;
|
||
|
}
|
||
|
|
||
|
clocks[cur_id] = new libjass.renderers.AutoClock(getCurrentTime, 500);
|
||
|
|
||
|
player.on('play', function () {
|
||
|
clocks[cur_id].play();
|
||
|
});
|
||
|
|
||
|
player.on('pause', function () {
|
||
|
clocks[cur_id].pause();
|
||
|
});
|
||
|
|
||
|
player.on('seeking', function () {
|
||
|
clocks[cur_id].seeking();
|
||
|
});
|
||
|
|
||
|
function updateClockRate() {
|
||
|
clocks[cur_id].setRate(player.playbackRate() * clockRate);
|
||
|
}
|
||
|
|
||
|
updateClockRate();
|
||
|
player.on('ratechange', updateClockRate);
|
||
|
|
||
|
function updateDisplayArea() {
|
||
|
setTimeout(function () {
|
||
|
// player might not have information on video dimensions when using external providers
|
||
|
var videoWidth = options.videoWidth || player.videoWidth() || player.el().offsetWidth,
|
||
|
videoHeight = options.videoHeight || player.videoHeight() || player.el().offsetHeight,
|
||
|
videoOffsetWidth = player.el().offsetWidth,
|
||
|
videoOffsetHeight = player.el().offsetHeight,
|
||
|
|
||
|
ratio = Math.min(videoOffsetWidth / videoWidth, videoOffsetHeight / videoHeight),
|
||
|
subsWrapperWidth = videoWidth * ratio,
|
||
|
subsWrapperHeight = videoHeight * ratio,
|
||
|
subsWrapperLeft = (videoOffsetWidth - subsWrapperWidth) / 2,
|
||
|
subsWrapperTop = (videoOffsetHeight - subsWrapperHeight) / 2;
|
||
|
|
||
|
renderers[cur_id].resize(subsWrapperWidth, subsWrapperHeight, subsWrapperLeft, subsWrapperTop);
|
||
|
}, 100);
|
||
|
}
|
||
|
|
||
|
window.addEventListener('resize', updateDisplayArea);
|
||
|
player.on('loadedmetadata', updateDisplayArea);
|
||
|
player.on('resize', updateDisplayArea);
|
||
|
player.on('fullscreenchange', updateDisplayArea);
|
||
|
|
||
|
player.on('dispose', function () {
|
||
|
for (var i = 0; i < clocks.length; i++) {
|
||
|
clocks[i].disable();
|
||
|
}
|
||
|
window.removeEventListener('resize', updateDisplayArea);
|
||
|
});
|
||
|
|
||
|
tracks.on('change', function () {
|
||
|
if (isTrackSwitching) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var activeTrack = this.tracks_.find(function (track) {
|
||
|
return track.mode === 'showing';
|
||
|
});
|
||
|
|
||
|
if (activeTrack) {
|
||
|
overlay.style.display = '';
|
||
|
switchTrackTo(assTrackIdMap[activeTrack.language + activeTrack.label]);
|
||
|
} else {
|
||
|
overlay.style.display = 'none';
|
||
|
}
|
||
|
})
|
||
|
|
||
|
rendererSettings = new libjass.renderers.RendererSettings();
|
||
|
libjass.ASS.fromUrl(options.src, libjass.Format.ASS).then(
|
||
|
function (ass) {
|
||
|
if (options.hasOwnProperty('enableSvg')) {
|
||
|
rendererSettings.enableSvg = options.enableSvg;
|
||
|
}
|
||
|
if (options.hasOwnProperty('fontMap')) {
|
||
|
rendererSettings.fontMap = new libjass.Map(options.fontMap);
|
||
|
} else if (options.hasOwnProperty('fontMapById')) {
|
||
|
rendererSettings.fontMap = libjass.renderers.RendererSettings
|
||
|
.makeFontMapFromStyleElement(document.getElementById(options.fontMapById));
|
||
|
}
|
||
|
|
||
|
addTrack(options.src, { label: options.label, srclang: options.srclang, switchImmediately: true });
|
||
|
renderers[cur_id] = new libjass.renderers.WebRenderer(ass, clocks[cur_id], overlay, rendererSettings);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
function addTrack(url, opts) {
|
||
|
var newTrack = player.addRemoteTextTrack({
|
||
|
src: "",
|
||
|
kind: 'subtitles',
|
||
|
label: opts.label || 'ASS #' + cur_id,
|
||
|
srclang: opts.srclang || 'vjs-ass-' + cur_id,
|
||
|
default: opts.switchImmediately
|
||
|
});
|
||
|
|
||
|
assTrackIdMap[newTrack.srclang + newTrack.label] = cur_id;
|
||
|
|
||
|
if(!opts.switchImmediately) {
|
||
|
// fix multiple track selected highlight issue
|
||
|
for (var t = 0; t < tracks.length; t++) {
|
||
|
if (tracks[t].mode === "showing") {
|
||
|
tracks[t].mode = "showing";
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
isTrackSwitching = true;
|
||
|
for (var t = 0; t < tracks.length; t++) {
|
||
|
if (tracks[t].label == newTrack.label && tracks[t].language == newTrack.srclang) {
|
||
|
if (tracks[t].mode !== "showing") {
|
||
|
tracks[t].mode = "showing";
|
||
|
}
|
||
|
} else {
|
||
|
if (tracks[t].mode === "showing") {
|
||
|
tracks[t].mode = "disabled";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
isTrackSwitching = false;
|
||
|
}
|
||
|
|
||
|
function switchTrackTo(selected_track_id) {
|
||
|
renderers[cur_id]._removeAllSubs();
|
||
|
renderers[cur_id]._preRenderedSubs.clear();
|
||
|
renderers[cur_id].clock.disable();
|
||
|
|
||
|
cur_id = selected_track_id;
|
||
|
if (cur_id == undefined) {
|
||
|
// case when we switche to regular non ASS closed captioning
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
renderers[cur_id].clock.enable();
|
||
|
updateDisplayArea();
|
||
|
clocks[cur_id].play();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Experimental API use at your own risk!!
|
||
|
*/
|
||
|
function loadNewSubtitle(url, label, srclang, switchImmediately) {
|
||
|
var old_id = cur_id;
|
||
|
if (switchImmediately) {
|
||
|
renderers[cur_id]._removeAllSubs();
|
||
|
renderers[cur_id]._preRenderedSubs.clear();
|
||
|
renderers[cur_id].clock.disable();
|
||
|
}
|
||
|
|
||
|
libjass.ASS.fromUrl(url, libjass.Format.ASS).then(
|
||
|
function (ass) {
|
||
|
cur_id = ++id_count;
|
||
|
clocks[cur_id] = new libjass.renderers.AutoClock(getCurrentTime, 500);
|
||
|
renderers[cur_id] = new libjass.renderers.WebRenderer(ass, clocks[cur_id], overlay, rendererSettings);
|
||
|
updateDisplayArea();
|
||
|
|
||
|
if (switchImmediately) {
|
||
|
clocks[cur_id].play();
|
||
|
} else {
|
||
|
renderers[cur_id]._removeAllSubs();
|
||
|
renderers[cur_id]._preRenderedSubs.clear();
|
||
|
renderers[cur_id].clock.disable();
|
||
|
}
|
||
|
|
||
|
addTrack(options.src, { label: label, srclang: srclang, switchImmediately: switchImmediately });
|
||
|
|
||
|
if (!switchImmediately) {
|
||
|
cur_id = old_id;
|
||
|
}
|
||
|
}
|
||
|
);
|
||
|
};
|
||
|
|
||
|
return {
|
||
|
loadNewSubtitle: loadNewSubtitle
|
||
|
};
|
||
|
};
|
||
|
|
||
|
videojs.plugin('ass', vjs_ass);
|
||
|
}(window.videojs, window.libjass));
|