video widgets: add support for multiple audio and subtitles tracks (first pass)
This commit is contained in:
parent
7d7620601c
commit
00e6367ca9
5 changed files with 248 additions and 236 deletions
|
@ -78,6 +78,8 @@ Ox.AnnotationFolder = function(options, self) {
|
||||||
crossesPoint() && updateAnnotations();
|
crossesPoint() && updateAnnotations();
|
||||||
self.position = self.options.position;
|
self.position = self.options.position;
|
||||||
}
|
}
|
||||||
|
} else if (key == 'languages') {
|
||||||
|
updateAnnotations();
|
||||||
} else if (key == 'range') {
|
} else if (key == 'range') {
|
||||||
updateAnnotations();
|
updateAnnotations();
|
||||||
self.$annotations.options({placeholder: getPlaceholder()});
|
self.$annotations.options({placeholder: getPlaceholder()});
|
||||||
|
@ -416,7 +418,9 @@ Ox.AnnotationFolder = function(options, self) {
|
||||||
)
|
)
|
||||||
) && (
|
) && (
|
||||||
self.options.languages == 'all'
|
self.options.languages == 'all'
|
||||||
|| self.options.languages.indexOf(item.language) > -1
|
|| self.options.languages.some(function(language) {
|
||||||
|
return item.languages.indexOf(language) > -1;
|
||||||
|
})
|
||||||
) && (
|
) && (
|
||||||
self.options.users == 'all'
|
self.options.users == 'all'
|
||||||
|| self.options.users.indexOf(item.user) > -1
|
|| self.options.users.indexOf(item.user) > -1
|
||||||
|
|
|
@ -41,6 +41,7 @@ Ox.VideoAnnotationPanel <f> VideoAnnotationPanel Object
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
Ox.VideoAnnotationPanel = function(options, self) {
|
Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
|
|
||||||
self = self || {};
|
self = self || {};
|
||||||
var that = Ox.Element({}, self)
|
var that = Ox.Element({}, self)
|
||||||
.defaults({
|
.defaults({
|
||||||
|
@ -88,6 +89,7 @@ Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
subtitles: [],
|
subtitles: [],
|
||||||
subtitlesDefaultTrack: 'en',
|
subtitlesDefaultTrack: 'en',
|
||||||
subtitlesLayer: null,
|
subtitlesLayer: null,
|
||||||
|
subtitlesTrack: 'en',
|
||||||
timeline: '',
|
timeline: '',
|
||||||
timelines: [],
|
timelines: [],
|
||||||
videoRatio: 16/9,
|
videoRatio: 16/9,
|
||||||
|
@ -281,7 +283,24 @@ Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.options.subtitles = self.options.subtitles || getSubtitles();
|
self.options.subtitles = options.subtitles !== void 0
|
||||||
|
? self.options.subtitles : parseSubtitles();
|
||||||
|
self.subtitlesTracks = Ox.sort(Ox.unique(Ox.flatten(
|
||||||
|
self.options.subtitles.map(function(subtitle) {
|
||||||
|
return subtitle.tracks;
|
||||||
|
})
|
||||||
|
))).map(function(track) {
|
||||||
|
return {
|
||||||
|
id: track,
|
||||||
|
title: Ox._(track),
|
||||||
|
checked: self.options.enableSubtitles
|
||||||
|
&& track == self.options.subtitlesTrack
|
||||||
|
};
|
||||||
|
}).concat([{
|
||||||
|
id: '',
|
||||||
|
title: Ox._('None'),
|
||||||
|
checked: !self.options.enableSubtitles
|
||||||
|
}]);
|
||||||
|
|
||||||
if (Ox.isObject(self.options.video[0])) {
|
if (Ox.isObject(self.options.video[0])) {
|
||||||
self.resolutions = Ox.sort(Ox.unique(
|
self.resolutions = Ox.sort(Ox.unique(
|
||||||
|
@ -302,7 +321,7 @@ Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
)).map(function(track) {
|
)).map(function(track) {
|
||||||
return {
|
return {
|
||||||
id: track,
|
id: track,
|
||||||
title: Ox._(Ox.getLanguageNameByCode(video.track)),
|
title: Ox._(track),
|
||||||
checked: self.options.audioTrack == track
|
checked: self.options.audioTrack == track
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -377,6 +396,7 @@ Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
sizeIsLarge: self.options.videoSize == 'large',
|
sizeIsLarge: self.options.videoSize == 'large',
|
||||||
subtitles: Ox.clone(self.options.subtitles, true),
|
subtitles: Ox.clone(self.options.subtitles, true),
|
||||||
subtitlesDefaultTrack: self.options.subtitlesDefaultTrack,
|
subtitlesDefaultTrack: self.options.subtitlesDefaultTrack,
|
||||||
|
subtitlesTrack: self.options.subtitlesTrack,
|
||||||
type: type,
|
type: type,
|
||||||
video: type == 'play' ? self.options.video : self.options.getFrameURL,
|
video: type == 'play' ? self.options.video : self.options.getFrameURL,
|
||||||
volume: self.options.volume,
|
volume: self.options.volume,
|
||||||
|
@ -591,8 +611,9 @@ Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
]}
|
]}
|
||||||
] : [],
|
] : [],
|
||||||
self.options.subtitles.length ? [
|
self.options.subtitles.length ? [
|
||||||
// TODO...
|
{id: 'subtitlesTracks', title: Ox._('Subtitles'), items: [
|
||||||
{id: 'subtitles', title: Ox._('Show Subtitles'), checked: self.options.enableSubtitles}
|
{group: 'subtitlesTrack', min: 1, max: 1, items: self.subtitlesTracks}
|
||||||
|
]}
|
||||||
] : [],
|
] : [],
|
||||||
[
|
[
|
||||||
{id: 'timelines', title: Ox._('Timeline'), items: [
|
{id: 'timelines', title: Ox._('Timeline'), items: [
|
||||||
|
@ -665,7 +686,8 @@ Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
change: function(data) {
|
change: function(data) {
|
||||||
var id = data.id;
|
var enableSubtitles,
|
||||||
|
id = data.id;
|
||||||
if (id == 'size') {
|
if (id == 'size') {
|
||||||
toggleSize();
|
toggleSize();
|
||||||
} else if (id == 'loop') {
|
} else if (id == 'loop') {
|
||||||
|
@ -674,10 +696,16 @@ Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
self.options.resolution = parseInt(data.checked[0].id, 10);
|
self.options.resolution = parseInt(data.checked[0].id, 10);
|
||||||
self.$player[0].options({resolution: self.options.resolution});
|
self.$player[0].options({resolution: self.options.resolution});
|
||||||
} else if (id == 'audioTrack') {
|
} else if (id == 'audioTrack') {
|
||||||
// ...
|
self.options.audioTrack = data.checked[0].id;
|
||||||
} else if (id == 'subtitles') {
|
self.$player[0].options({audioTrack: self.options.audioTrack});
|
||||||
// TODO...
|
} else if (id == 'subtitlesTrack') {
|
||||||
toggleSubtitles();
|
enableSubtitles = !!data.checked[0].id;
|
||||||
|
if (enableSubtitles != self.options.enableSubtitles) {
|
||||||
|
self.options.enableSubtitles = enableSubtitles;
|
||||||
|
that.triggerEvent('subtitles', {subtitles: enableSubtitles});
|
||||||
|
}
|
||||||
|
self.options.subtitlesTrack = data.checked[0].id;
|
||||||
|
setSubtitlesTrack();
|
||||||
} else if (id == 'timeline') {
|
} else if (id == 'timeline') {
|
||||||
self.options.timeline = data.checked[0].id;
|
self.options.timeline = data.checked[0].id;
|
||||||
updateTimelines();
|
updateTimelines();
|
||||||
|
@ -1151,23 +1179,11 @@ Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubtitles() {
|
function getSubtitles() {
|
||||||
return self.options.subtitlesLayer ? self.options.layers.filter(function(layer) {
|
return self.options.enableSubtitles
|
||||||
return layer.id == self.options.subtitlesLayer;
|
? self.options.subtitles.filter(function(v) {
|
||||||
})[0].items.map(function(subtitle) {
|
return Ox.contains(v.tracks, self.options.subtitlesTrack);
|
||||||
return {
|
|
||||||
id: subtitle.id,
|
|
||||||
'in': subtitle['in'],
|
|
||||||
out: subtitle.out,
|
|
||||||
text: subtitle.value.replace(/\n/g, ' ').replace(/<br\/?>/g, '\n'),
|
|
||||||
tracks: (
|
|
||||||
subtitle.languages
|
|
||||||
? subtitle.languages
|
|
||||||
: [self.options.subtitleDefaultTrack]
|
|
||||||
).map(function(language) {
|
|
||||||
return Ox.getLanguageNameByCode(language);
|
|
||||||
})
|
})
|
||||||
};
|
: [];
|
||||||
}) : [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWords() {
|
function getWords() {
|
||||||
|
@ -1203,6 +1219,20 @@ Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
setPosition(getNextPosition(type, direction));
|
setPosition(getNextPosition(type, direction));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseSubtitles() {
|
||||||
|
return self.options.subtitlesLayer ? self.options.layers.filter(function(layer) {
|
||||||
|
return layer.id == self.options.subtitlesLayer;
|
||||||
|
})[0].items.map(function(subtitle) {
|
||||||
|
return {
|
||||||
|
id: subtitle.id,
|
||||||
|
'in': subtitle['in'],
|
||||||
|
out: subtitle.out,
|
||||||
|
text: subtitle.value.replace(/\n/g, ' ').replace(/<br\/?>/g, '\n'),
|
||||||
|
tracks: subtitle.languages || [self.options.subtitlesDefaultTrack]
|
||||||
|
};
|
||||||
|
}) : [];
|
||||||
|
}
|
||||||
|
|
||||||
function playInToOut() {
|
function playInToOut() {
|
||||||
self.$player[0].playInToOut();
|
self.$player[0].playInToOut();
|
||||||
}
|
}
|
||||||
|
@ -1364,6 +1394,35 @@ Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setSubtitlesTrack() {
|
||||||
|
var enableSubtitles = self.options.subtitlesTrack != '',
|
||||||
|
subtitles,
|
||||||
|
toggleSubtitles = enableSubtitles != self.options.enableSubtitles;
|
||||||
|
self.options.enableSubtitles = enableSubtitles;
|
||||||
|
subtitles = getSubtitles();
|
||||||
|
if (toggleSubtitles) {
|
||||||
|
self.$player.forEach(function($player) {
|
||||||
|
$player.options({
|
||||||
|
enableSubtitles: self.options.enableSubtitles
|
||||||
|
});
|
||||||
|
});
|
||||||
|
that.triggerEvent('subtitles', {
|
||||||
|
subtitles: self.options.enableSubtitles
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.$player.forEach(function($player) {
|
||||||
|
$player.options({
|
||||||
|
subtitles: subtitles
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self.$timeline.forEach(function($timeline) {
|
||||||
|
$timeline.options({
|
||||||
|
subtitles: subtitles
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function showKeyboardShortcuts() {
|
function showKeyboardShortcuts() {
|
||||||
var dialog = Ox.Dialog({
|
var dialog = Ox.Dialog({
|
||||||
buttons: [
|
buttons: [
|
||||||
|
@ -1505,25 +1564,8 @@ Ox.VideoAnnotationPanel = function(options, self) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSubtitles() {
|
|
||||||
self.options.enableSubtitles = !self.options.enableSubtitles;
|
|
||||||
self.$player.forEach(function($player) {
|
|
||||||
$player.options({
|
|
||||||
enableSubtitles: self.options.enableSubtitles
|
|
||||||
});
|
|
||||||
});
|
|
||||||
self.$timeline.forEach(function($timeline) {
|
|
||||||
$timeline.options({
|
|
||||||
subtitles: self.options.enableSubtitles ? Ox.clone(self.options.subtitles, true) : []
|
|
||||||
});
|
|
||||||
});
|
|
||||||
that.triggerEvent('subtitles', {
|
|
||||||
subtitles: self.options.enableSubtitles
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateSubtitles() {
|
function updateSubtitles() {
|
||||||
self.options.subtitles = getSubtitles();
|
self.options.subtitles = parseSubtitles();
|
||||||
self.$player.forEach(function($player) {
|
self.$player.forEach(function($player) {
|
||||||
$player.options({subtitles: Ox.clone(self.options.subtitles, true)});
|
$player.options({subtitles: Ox.clone(self.options.subtitles, true)});
|
||||||
});
|
});
|
||||||
|
|
|
@ -71,8 +71,8 @@ Ox.VideoPlayer <f> Generic Video Player
|
||||||
out <n> Out point (sec)
|
out <n> Out point (sec)
|
||||||
text <s> Text
|
text <s> Text
|
||||||
tracks <[s]> Track names, like "English" or "Director's Commentary"
|
tracks <[s]> Track names, like "English" or "Director's Commentary"
|
||||||
subtitlesDefaultTrack <s|'en'> Default subtitle language (ISO 639-1) or track name
|
subtitlesDefaultTrack <s|'English'> Track name
|
||||||
subtitlesTrack <s|'en'> Subtitle language (ISO 639-1) or track name
|
subtitlesTrack <s|'English'> Track name
|
||||||
timeline <s> Timeline image URL
|
timeline <s> Timeline image URL
|
||||||
timelineType <s|''> Current timeline type id
|
timelineType <s|''> Current timeline type id
|
||||||
timelineTypes <[o]|[]> Array of timeline type objects (id and title)
|
timelineTypes <[o]|[]> Array of timeline type objects (id and title)
|
||||||
|
@ -166,8 +166,8 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
showProgress: false,
|
showProgress: false,
|
||||||
sizeIsLarge: false,
|
sizeIsLarge: false,
|
||||||
subtitles: [],
|
subtitles: [],
|
||||||
subtitlesDefaultTrack: 'en',
|
subtitlesDefaultTrack: 'English',
|
||||||
subtitlesTrack: 'en',
|
subtitlesTrack: 'English',
|
||||||
timeline: '',
|
timeline: '',
|
||||||
timelineType: '',
|
timelineType: '',
|
||||||
timelineTypes: [],
|
timelineTypes: [],
|
||||||
|
@ -285,6 +285,8 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
self.videoHeight = self.options.height;
|
self.videoHeight = self.options.height;
|
||||||
self.results = [];
|
self.results = [];
|
||||||
|
|
||||||
|
loadSubtitles();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
Keyboard
|
Keyboard
|
||||||
|
@ -1237,8 +1239,6 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
|
|
||||||
self.results = [];
|
self.results = [];
|
||||||
|
|
||||||
loadSubtitles();
|
|
||||||
|
|
||||||
setSizes(false, function() {
|
setSizes(false, function() {
|
||||||
self.options.fullscreen && enterFullscreen();
|
self.options.fullscreen && enterFullscreen();
|
||||||
});
|
});
|
||||||
|
@ -1535,11 +1535,6 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
return css;
|
return css;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMenuSection(str) {
|
|
||||||
var match = str.match(/<span class="(.+?)">/);
|
|
||||||
return match ? match[1] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPosition(e) {
|
function getPosition(e) {
|
||||||
// fixme: no offsetX in firefox???
|
// fixme: no offsetX in firefox???
|
||||||
if ($.browser.mozilla) {
|
if ($.browser.mozilla) {
|
||||||
|
@ -1617,23 +1612,25 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
|
|
||||||
function getSubtitle() {
|
function getSubtitle() {
|
||||||
var subtitle = '';
|
var subtitle = '';
|
||||||
self.options.enableSubtitles && Ox.forEach(self.options.subtitles, function(v) {
|
if (self.options.enableSubtitles) {
|
||||||
|
Ox.forEach(self.options.subtitles, function(v) {
|
||||||
if (
|
if (
|
||||||
v['in'] <= self.options.position
|
v['in'] <= self.options.position
|
||||||
&& v.out >= self.options.position
|
&& v.out >= self.options.position
|
||||||
&& v.track == self.options.subtitlesTrack
|
&& Ox.contains(v.tracks, self.options.subtitlesTrack)
|
||||||
) {
|
) {
|
||||||
subtitle = v.text;
|
subtitle = v.text;
|
||||||
return false; // break
|
return false; // break
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return subtitle;
|
return subtitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubtitles() {
|
function getSubtitles() {
|
||||||
return self.options.enableSubtitles
|
return self.options.enableSubtitles
|
||||||
? self.options.subtitles.map(function(v) {
|
? self.options.subtitles.filter(function(v) {
|
||||||
return v.track == self.options.subtitlesTrack;
|
return Ox.contains(v.tracks, self.options.subtitlesTrack);
|
||||||
})
|
})
|
||||||
: [];
|
: [];
|
||||||
}
|
}
|
||||||
|
@ -1714,8 +1711,13 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
|
|
||||||
function getVideo() {
|
function getVideo() {
|
||||||
return self.options.video.filter(function(video) {
|
return self.options.video.filter(function(video) {
|
||||||
return video.audioTrack == self.options.audioTrack
|
return (
|
||||||
&& video.resolution == self.options.resolution;
|
!self.options.audioTrack
|
||||||
|
|| video.track == self.options.audioTrack
|
||||||
|
) && (
|
||||||
|
!self.options.resolution
|
||||||
|
|| video.resolution == self.options.resolution
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1944,14 +1946,9 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
|
|
||||||
function loadedsubtitles() {
|
function loadedsubtitles() {
|
||||||
if (!self.subtitlesTracks || Ox.isEmpty(self.subtitlesTracks)) {
|
if (!self.subtitlesTracks || Ox.isEmpty(self.subtitlesTracks)) {
|
||||||
self.subtitlesTracks = [{
|
self.subtitlesTracks = [self.options.subtitlesDefaultTrack];
|
||||||
code: self.options.subtitlesDefaultTrack,
|
|
||||||
name: Ox.getLanguageNameByCode(
|
|
||||||
self.options.subtitlesDefaultTrack
|
|
||||||
)
|
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
self.subtitlesTracks.push({code: '', name: 'None'});
|
self.subtitlesTracks.push('None');
|
||||||
if (self.options.find) {
|
if (self.options.find) {
|
||||||
submitFindInput(self.options.find);
|
submitFindInput(self.options.find);
|
||||||
if (self.options.duration) {
|
if (self.options.duration) {
|
||||||
|
@ -1968,23 +1965,13 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSubtitles() {
|
function loadSubtitles() {
|
||||||
if (self.options.subtitles) {
|
if (self.options.subtitles.length) {
|
||||||
if (Ox.isArray(self.options.subtitles)) {
|
if (Ox.isArray(self.options.subtitles)) {
|
||||||
self.subtitlesTracks = Ox.sortBy(
|
self.subtitlesTracks = Ox.sort(Ox.unique(Ox.flatten(
|
||||||
Ox.unique(
|
|
||||||
self.options.subtitles.map(function(subtitle) {
|
self.options.subtitles.map(function(subtitle) {
|
||||||
return subtitle.track;
|
return subtitle.tracks;
|
||||||
}).filter(function(track) {
|
|
||||||
return !!track;
|
|
||||||
})
|
})
|
||||||
).map(function(track) {
|
)));
|
||||||
return {
|
|
||||||
code: track,
|
|
||||||
name: Ox.getLanguageNameByCode(track)
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
'name'
|
|
||||||
);
|
|
||||||
loadedsubtitles();
|
loadedsubtitles();
|
||||||
} else {
|
} else {
|
||||||
if (self.options.subtitles.indexOf('\n') > -1) {
|
if (self.options.subtitles.indexOf('\n') > -1) {
|
||||||
|
@ -2050,33 +2037,77 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSettings() {
|
function renderSettings() {
|
||||||
// fixme: use proper ids (as class of span)
|
return Ox.VideoPlayerMenu({
|
||||||
var $settings = $('<div>')
|
items: [{disabled: true, title: Ox._('Resolution')}].concat(
|
||||||
|
self.resolutions.map(function(resolution) {
|
||||||
|
return {
|
||||||
|
group: 'resolution',
|
||||||
|
id: resolution,
|
||||||
|
checked: resolution == self.options.resolution,
|
||||||
|
title: resolution + 'p'
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
self.audioTracks.length > 1
|
||||||
|
? [{}, {disabled: true, title: Ox._('Audio')}].concat(
|
||||||
|
self.audioTracks.map(function(track) {
|
||||||
|
return {
|
||||||
|
group: 'audioTrack',
|
||||||
|
id: track,
|
||||||
|
checked: track == self.options.audioTrack,
|
||||||
|
title: Ox._(track)
|
||||||
|
};
|
||||||
|
})
|
||||||
|
)
|
||||||
|
: [],
|
||||||
|
self.options.subtitles.length
|
||||||
|
? [{}, {disabled: true, title: Ox._('Subtitles')}].concat(
|
||||||
|
self.subtitlesTracks.map(function(track) {
|
||||||
|
return {
|
||||||
|
group: 'subtitlesTrack',
|
||||||
|
id: track,
|
||||||
|
checked: self.options.enableSubtitles
|
||||||
|
? track == self.options.subtitlesTrack
|
||||||
|
: track == '',
|
||||||
|
title: Ox._(track)
|
||||||
|
};
|
||||||
|
})
|
||||||
|
)
|
||||||
|
: [],
|
||||||
|
self.options.timelineTypes.length
|
||||||
|
? [{}, {disabled: true, title: Ox._('Timeline')}].concat(
|
||||||
|
self.options.timelineTypes.map(function(type) {
|
||||||
|
return {
|
||||||
|
group: 'timeline',
|
||||||
|
id: type.id,
|
||||||
|
checked: type.id == self.options.timelineType,
|
||||||
|
title: type.title
|
||||||
|
};
|
||||||
|
})
|
||||||
|
)
|
||||||
|
: [],
|
||||||
|
self.options.enableDownload
|
||||||
|
? [{}, {id: 'download', title: Ox._('Download')}]
|
||||||
|
: []
|
||||||
|
)
|
||||||
|
})
|
||||||
.addClass('OxControls OxSettings')
|
.addClass('OxControls OxSettings')
|
||||||
.on({
|
.bindEvent({
|
||||||
click: function(e) {
|
click: function(data) {
|
||||||
var $target = $(e.target), resolution, title, track, type;
|
var resolution, type;
|
||||||
self.$settings.hide();
|
if (data.group == 'resolution') {
|
||||||
if (!$target.is('.OxLine') && !$target.is('.OxSpace')) {
|
resolution = parseInt(data.id, 10);
|
||||||
title = $(e.target).parent().children()[0].innerHTML;
|
|
||||||
if (title == Ox._('Download')) {
|
|
||||||
that.triggerEvent('download');
|
|
||||||
} else if (getMenuSection(title) == 'resolution') {
|
|
||||||
resolution = parseInt(Ox.stripTags(title), 10);
|
|
||||||
if (resolution != self.options.resolution) {
|
if (resolution != self.options.resolution) {
|
||||||
self.options.resolution = resolution;
|
self.options.resolution = resolution;
|
||||||
setResolution();
|
setResolution();
|
||||||
}
|
}
|
||||||
} else if (getMenuSection(title) == 'audioTrack') {
|
} else if (data.group == 'audioTrack') {
|
||||||
track = Ox.stripTags(title);
|
self.options.audioTrack = data.id;
|
||||||
self.options.audioTrack = Ox.getLanguageCodeByName(track);
|
|
||||||
setAudioTrack();
|
setAudioTrack();
|
||||||
} else if (getMenuSection(title) == 'subtitlesTrack') {
|
} else if (data.group == 'subtitlesTrack') {
|
||||||
track = Ox.stripTags(title);
|
self.options.subtitlesTrack = data.id == 'None'
|
||||||
self.options.subtitlesTrack = track == 'None'
|
? '' : data.id;
|
||||||
? '' : Ox.getLanguageCodeByName(track);
|
|
||||||
setSubtitlesTrack();
|
setSubtitlesTrack();
|
||||||
} else {
|
} else if (data.group == 'timeline') {
|
||||||
type = self.options.timelineTypes[
|
type = self.options.timelineTypes[
|
||||||
Ox.indexOf(self.options.timelineTypes, function(type) {
|
Ox.indexOf(self.options.timelineTypes, function(type) {
|
||||||
return type.title == title;
|
return type.title == title;
|
||||||
|
@ -2086,114 +2117,12 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
self.options.timelineType = type;
|
self.options.timelineType = type;
|
||||||
setTimelineType();
|
setTimelineType();
|
||||||
}
|
}
|
||||||
|
} else if (data.id == 'download') {
|
||||||
|
that.triggerEvent('download');
|
||||||
}
|
}
|
||||||
self.$settings.children('.OxItem').each(function() {
|
|
||||||
var children = $(this).children(),
|
|
||||||
title = children[0].innerHTML,
|
|
||||||
checked = (
|
|
||||||
title == Ox._('Subtitles')
|
|
||||||
&& self.options.enableSubtitles
|
|
||||||
) || (
|
|
||||||
isResolution(title)
|
|
||||||
&& parseInt(title, 10) == self.options.resolution
|
|
||||||
) || (
|
|
||||||
self.options.timelineTypes.length
|
|
||||||
&& title == Ox.getObjectById(
|
|
||||||
self.options.timelineTypes,
|
|
||||||
self.options.timelineType
|
|
||||||
).title
|
|
||||||
);
|
|
||||||
$(children[1]).attr({
|
|
||||||
src: Ox.UI.getImageURL(
|
|
||||||
'symbol' + (checked ? 'Check' : 'None')
|
|
||||||
)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
items = [{
|
|
||||||
disabled: true,
|
|
||||||
title: Ox._('Resolution')
|
|
||||||
}].concat(
|
|
||||||
self.resolutions.map(function(resolution) {
|
|
||||||
return {
|
|
||||||
checked: resolution == self.options.resolution,
|
|
||||||
title: '<span class="resolution">'
|
|
||||||
+ resolution + 'p</span>'
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
self.audioTracks.length > 1
|
|
||||||
? [{}, {disabled: true, title: Ox._('Audio')}].concat(
|
|
||||||
self.audioTracks.map(function(track) {
|
|
||||||
return {
|
|
||||||
checked: track.code == self.options.audioTrack,
|
|
||||||
title: '<span class="audioTrack">'
|
|
||||||
+ Ox._(track.name) + '</span>'
|
|
||||||
};
|
|
||||||
})
|
|
||||||
)
|
|
||||||
: [],
|
|
||||||
self.options.subtitles.length
|
|
||||||
? [{}, {disabled: true, title: Ox._('Subtitles')}].concat(
|
|
||||||
self.subtitlesTracks.map(function(track) {
|
|
||||||
return {
|
|
||||||
checked: track.code == self.options.enableSubtitles
|
|
||||||
? self.options.subtitlesTrack : '',
|
|
||||||
title: '<span class="subtitlesTrack">'
|
|
||||||
+ Ox._(track.name) + '</span>'
|
|
||||||
};
|
|
||||||
})
|
|
||||||
)
|
|
||||||
: [],
|
|
||||||
self.options.timelineTypes.length
|
|
||||||
? [{}, {disabled: true, title: Ox._('Timeline')}].concat(
|
|
||||||
self.options.timelineTypes.map(function(type) {
|
|
||||||
return {
|
|
||||||
checked: type.id == self.options.timelineType,
|
|
||||||
title: '<span class="timeline">'
|
|
||||||
+ type.title + '</span>'
|
|
||||||
};
|
|
||||||
})
|
|
||||||
)
|
|
||||||
: [],
|
|
||||||
self.options.enableDownload
|
|
||||||
? [{}, {title: Ox._('Download')}]
|
|
||||||
: []
|
|
||||||
),
|
|
||||||
height = 0;
|
|
||||||
items.forEach(function(item) {
|
|
||||||
var $item;
|
|
||||||
if (item.title) {
|
|
||||||
$item = $('<div>')
|
|
||||||
.addClass('OxItem' + (item.disabled ? ' OxDisabled' : ''))
|
|
||||||
.appendTo($settings);
|
|
||||||
if (!item.disabled) {
|
|
||||||
$item.on({
|
|
||||||
mouseenter: function() {
|
|
||||||
$(this).addClass('OxSelected');
|
|
||||||
},
|
|
||||||
mouseleave: function() {
|
|
||||||
$(this).removeClass('OxSelected');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
$('<div>').html(item.title).appendTo($item);
|
|
||||||
$('<img>').attr({
|
|
||||||
src: Ox.UI.getImageURL(
|
|
||||||
'symbol' + (item.checked ? 'Check' : 'None')
|
|
||||||
)
|
|
||||||
}).appendTo($item);
|
|
||||||
height += 16;
|
|
||||||
} else {
|
|
||||||
$('<div>').addClass('OxSpace').appendTo($settings);
|
|
||||||
$('<div>').addClass('OxLine').appendTo($settings);
|
|
||||||
$('<div>').addClass('OxSpace').appendTo($settings);
|
|
||||||
height += 1
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$settings.css({height: height + 'px'});
|
|
||||||
return $settings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function rewind() {
|
function rewind() {
|
||||||
|
@ -2223,7 +2152,7 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAudioTrack() {
|
function setAudioTrack() {
|
||||||
// ...
|
updateVideo();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCensored() {
|
function setCensored() {
|
||||||
|
@ -2298,17 +2227,7 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setResolution() {
|
function setResolution() {
|
||||||
if (!self.options.paused) {
|
updateVideo();
|
||||||
self.playOnLoad = true;
|
|
||||||
togglePaused('button');
|
|
||||||
}
|
|
||||||
self.loadedMetadata = false;
|
|
||||||
showLoadingIcon();
|
|
||||||
self.video = getVideo();
|
|
||||||
self.$video.options({
|
|
||||||
items: self.video
|
|
||||||
});
|
|
||||||
self.$playButton && self.$playButton.options({disabled: true});
|
|
||||||
that.triggerEvent('resolution', {
|
that.triggerEvent('resolution', {
|
||||||
resolution: self.options.resolution
|
resolution: self.options.resolution
|
||||||
});
|
});
|
||||||
|
@ -2402,17 +2321,24 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSubtitlesTrack() {
|
function setSubtitlesTrack() {
|
||||||
var enableSubtitles = !!self.options.subtitlesTrack;
|
var enableSubtitles = !!self.options.subtitlesTrack,
|
||||||
|
toggleSubtitles = enableSubtitles != self.options.enableSubtitles;
|
||||||
|
self.options.enableSubtitles = enableSubtitles;
|
||||||
setSubtitle();
|
setSubtitle();
|
||||||
self.$timeline && self.$timeline.options({
|
self.$timeline && self.$timeline.options({
|
||||||
subtitles: getSubtitles()
|
subtitles: getSubtitles()
|
||||||
});
|
});
|
||||||
if (enableSubtitles != self.options.enableSubtitles) {
|
if (toggleSubtitles) {
|
||||||
self.options.enableSubtitles = enableSubtitles;
|
self.options.enableSubtitles = enableSubtitles;
|
||||||
that.triggerEvent('subtitles', {
|
that.triggerEvent('subtitles', {
|
||||||
subtitles: self.options.enableSubtitles
|
subtitles: self.options.enableSubtitles
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (enableSubtitles) {
|
||||||
|
that.triggerEvent('subtitlestrack', {
|
||||||
|
track: self.options.subtitlesTrack
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTimelineType() {
|
function setTimelineType() {
|
||||||
|
@ -2421,21 +2347,13 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
|
|
||||||
function setVideo() {
|
function setVideo() {
|
||||||
if (Ox.isObject(self.options.video[0])) {
|
if (Ox.isObject(self.options.video[0])) {
|
||||||
self.audioTracks = Ox.sortBy(Ox.unique(
|
self.audioTracks = Ox.sort(Ox.unique(
|
||||||
self.options.video.map(function(video) {
|
self.options.video.map(function(video) {
|
||||||
return {
|
return video.track;
|
||||||
code: video.track,
|
|
||||||
name: Ox.getLanguageNameByCode(video.track)
|
|
||||||
};
|
|
||||||
})
|
})
|
||||||
), 'name');
|
));
|
||||||
if (!Ox.contains(
|
if (!Ox.contains(self.audioTracks, self.options.audioTrack)) {
|
||||||
self.audioTracks.map(function(track) {
|
self.options.audioTrack = self.audioTracks[0];
|
||||||
return track.code;
|
|
||||||
}),
|
|
||||||
self.options.audioTrack
|
|
||||||
)) {
|
|
||||||
self.options.audioTrack = self.audioTracks[0].code;
|
|
||||||
}
|
}
|
||||||
self.resolutions = Ox.sort(Ox.unique(
|
self.resolutions = Ox.sort(Ox.unique(
|
||||||
self.options.video.map(function(video) {
|
self.options.video.map(function(video) {
|
||||||
|
@ -2781,6 +2699,20 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
self.$volume.toggle();
|
self.$volume.toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateVideo() {
|
||||||
|
if (!self.options.paused) {
|
||||||
|
self.playOnLoad = true;
|
||||||
|
togglePaused('button');
|
||||||
|
}
|
||||||
|
self.loadedMetadata = false;
|
||||||
|
showLoadingIcon();
|
||||||
|
self.video = getVideo();
|
||||||
|
self.$video.options({
|
||||||
|
items: self.video
|
||||||
|
});
|
||||||
|
self.$playButton && self.$playButton.options({disabled: true});
|
||||||
|
}
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
changeVolume <f> change volume
|
changeVolume <f> change volume
|
||||||
(num) -> <o> change volume
|
(num) -> <o> change volume
|
||||||
|
|
|
@ -38,7 +38,7 @@ Ox.VideoPlayerMenu = function(options, self) {
|
||||||
});
|
});
|
||||||
|
|
||||||
self.$items = [];
|
self.$items = [];
|
||||||
self.height = 0;
|
self.height = 2;
|
||||||
|
|
||||||
self.options.items.forEach(function(item) {
|
self.options.items.forEach(function(item) {
|
||||||
var $item;
|
var $item;
|
||||||
|
|
|
@ -8,6 +8,7 @@ Ox.VideoPlayerPanel <f> VideoPlayerPanel Object
|
||||||
annotationsrange <!> annotationsrange
|
annotationsrange <!> annotationsrange
|
||||||
annotationssize <!> annotationssize
|
annotationssize <!> annotationssize
|
||||||
annotationssort <!> annotationssort
|
annotationssort <!> annotationssort
|
||||||
|
audioTrack <s|''> Two-letter ISO 639-1 language code or track name
|
||||||
censored <!> censored
|
censored <!> censored
|
||||||
downloadvideo <!> downloadvideo
|
downloadvideo <!> downloadvideo
|
||||||
find <!> find
|
find <!> find
|
||||||
|
@ -40,6 +41,7 @@ Ox.VideoPlayerPanel = function(options, self) {
|
||||||
annotationsSize: 256,
|
annotationsSize: 256,
|
||||||
annotationsSort: 'position',
|
annotationsSort: 'position',
|
||||||
annotationsTooltip: 'annotations',
|
annotationsTooltip: 'annotations',
|
||||||
|
audioTrack: '',
|
||||||
censored: [],
|
censored: [],
|
||||||
censoredIcon: '',
|
censoredIcon: '',
|
||||||
censoredTooltip: '',
|
censoredTooltip: '',
|
||||||
|
@ -74,7 +76,9 @@ Ox.VideoPlayerPanel = function(options, self) {
|
||||||
showUsers: false,
|
showUsers: false,
|
||||||
smallTimelineURL: '',
|
smallTimelineURL: '',
|
||||||
subtitles: [],
|
subtitles: [],
|
||||||
subtitlesDefaultTrack: 'en',
|
subtitlesDefaultTrack: 'English',
|
||||||
|
subtitlesLayer: null,
|
||||||
|
subtitlesTrack: 'English',
|
||||||
timeline: '',
|
timeline: '',
|
||||||
timelineTooltip: 'timeline',
|
timelineTooltip: 'timeline',
|
||||||
video: '',
|
video: '',
|
||||||
|
@ -194,6 +198,9 @@ Ox.VideoPlayerPanel = function(options, self) {
|
||||||
key_space: togglePaused
|
key_space: togglePaused
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.options.subtitles = options.subtitles !== void 0
|
||||||
|
? self.options.subtitles : parseSubtitles();
|
||||||
|
|
||||||
self.fullscreen = false;
|
self.fullscreen = false;
|
||||||
self.results = [];
|
self.results = [];
|
||||||
|
|
||||||
|
@ -201,6 +208,7 @@ Ox.VideoPlayerPanel = function(options, self) {
|
||||||
|
|
||||||
self.$video = Ox.VideoPlayer({
|
self.$video = Ox.VideoPlayer({
|
||||||
annotations: getAnnotations(),
|
annotations: getAnnotations(),
|
||||||
|
audioTrack: self.options.audioTrack,
|
||||||
censored: self.options.censored,
|
censored: self.options.censored,
|
||||||
censoredIcon: self.options.censoredIcon,
|
censoredIcon: self.options.censoredIcon,
|
||||||
censoredTooltip: self.options.censoredTooltip,
|
censoredTooltip: self.options.censoredTooltip,
|
||||||
|
@ -227,8 +235,9 @@ Ox.VideoPlayerPanel = function(options, self) {
|
||||||
position: self.options.position,
|
position: self.options.position,
|
||||||
resolution: self.options.resolution,
|
resolution: self.options.resolution,
|
||||||
scaleToFill: self.options.scaleToFill,
|
scaleToFill: self.options.scaleToFill,
|
||||||
subtitles: self.options.subtitles,
|
subtitles: Ox.clone(self.options.subtitles, true),
|
||||||
subtitlesDefaultTrack: self.options.subtitlesDefaultTrack,
|
subtitlesDefaultTrack: self.options.subtitlesDefaultTrack,
|
||||||
|
subtitlesTrack: self.options.subtitlesTrack,
|
||||||
timeline: self.options.smallTimelineURL,
|
timeline: self.options.smallTimelineURL,
|
||||||
video: self.options.video,
|
video: self.options.video,
|
||||||
volume: self.options.volume,
|
volume: self.options.volume,
|
||||||
|
@ -276,11 +285,14 @@ Ox.VideoPlayerPanel = function(options, self) {
|
||||||
},
|
},
|
||||||
select: selectAnnotation,
|
select: selectAnnotation,
|
||||||
subtitles: function(data) {
|
subtitles: function(data) {
|
||||||
self.$timeline.options({
|
self.options.enableSubtitles = data.subtitles;
|
||||||
subtitles: data.subtitles ? self.options.subtitles : []
|
self.$timeline.options({subtitles: getSubtitles()});
|
||||||
});
|
|
||||||
that.triggerEvent('subtitles', data);
|
that.triggerEvent('subtitles', data);
|
||||||
},
|
},
|
||||||
|
subtitlestrack: function(data) {
|
||||||
|
self.options.subtitlesTrack = data.track;
|
||||||
|
self.$timeline.options({subtitles: getSubtitles()});
|
||||||
|
},
|
||||||
volume: function(data) {
|
volume: function(data) {
|
||||||
that.triggerEvent('volume', data);
|
that.triggerEvent('volume', data);
|
||||||
}
|
}
|
||||||
|
@ -301,7 +313,7 @@ Ox.VideoPlayerPanel = function(options, self) {
|
||||||
'in': self.options['in'],
|
'in': self.options['in'],
|
||||||
out: self.options.out,
|
out: self.options.out,
|
||||||
position: self.options.position,
|
position: self.options.position,
|
||||||
subtitles: self.options.enableSubtitles ? self.options.subtitles : [],
|
subtitles: getSubtitles(),
|
||||||
videoId: self.options.videoId, // fixme: not in defaults
|
videoId: self.options.videoId, // fixme: not in defaults
|
||||||
type: self.options.timeline,
|
type: self.options.timeline,
|
||||||
width: getTimelineWidth()
|
width: getTimelineWidth()
|
||||||
|
@ -463,6 +475,14 @@ Ox.VideoPlayerPanel = function(options, self) {
|
||||||
* self.options.annotationsSize - 1;
|
* self.options.annotationsSize - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSubtitles() {
|
||||||
|
return self.options.enableSubtitles
|
||||||
|
? self.options.subtitles.filter(function(v) {
|
||||||
|
return Ox.contains(v.tracks, self.options.subtitlesTrack);
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
function getTimelineWidth() {
|
function getTimelineWidth() {
|
||||||
return self.options.width
|
return self.options.width
|
||||||
- (self.options.showAnnotations && !self.fullscreen)
|
- (self.options.showAnnotations && !self.fullscreen)
|
||||||
|
@ -485,6 +505,20 @@ Ox.VideoPlayerPanel = function(options, self) {
|
||||||
setPosition(getNextPosition(type, direction));
|
setPosition(getNextPosition(type, direction));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseSubtitles() {
|
||||||
|
return self.options.subtitlesLayer ? self.options.layers.filter(function(layer) {
|
||||||
|
return layer.id == self.options.subtitlesLayer;
|
||||||
|
})[0].items.map(function(subtitle) {
|
||||||
|
return {
|
||||||
|
id: subtitle.id,
|
||||||
|
'in': subtitle['in'],
|
||||||
|
out: subtitle.out,
|
||||||
|
text: subtitle.value.replace(/\n/g, ' ').replace(/<br\/?>/g, '\n'),
|
||||||
|
tracks: subtitle.languages || [self.options.subtitlesDefaultTrack]
|
||||||
|
};
|
||||||
|
}) : [];
|
||||||
|
}
|
||||||
|
|
||||||
function resizeAnnotations(data) {
|
function resizeAnnotations(data) {
|
||||||
// called on annotations resize
|
// called on annotations resize
|
||||||
self.options.annotationsSize = data.size;
|
self.options.annotationsSize = data.size;
|
||||||
|
|
Loading…
Reference in a new issue