forked from 0x2620/oxjs
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
|
|
@ -71,8 +71,8 @@ Ox.VideoPlayer <f> Generic Video Player
|
|||
out <n> Out point (sec)
|
||||
text <s> Text
|
||||
tracks <[s]> Track names, like "English" or "Director's Commentary"
|
||||
subtitlesDefaultTrack <s|'en'> Default subtitle language (ISO 639-1) or track name
|
||||
subtitlesTrack <s|'en'> Subtitle language (ISO 639-1) or track name
|
||||
subtitlesDefaultTrack <s|'English'> Track name
|
||||
subtitlesTrack <s|'English'> Track name
|
||||
timeline <s> Timeline image URL
|
||||
timelineType <s|''> Current timeline type id
|
||||
timelineTypes <[o]|[]> Array of timeline type objects (id and title)
|
||||
|
|
@ -166,8 +166,8 @@ Ox.VideoPlayer = function(options, self) {
|
|||
showProgress: false,
|
||||
sizeIsLarge: false,
|
||||
subtitles: [],
|
||||
subtitlesDefaultTrack: 'en',
|
||||
subtitlesTrack: 'en',
|
||||
subtitlesDefaultTrack: 'English',
|
||||
subtitlesTrack: 'English',
|
||||
timeline: '',
|
||||
timelineType: '',
|
||||
timelineTypes: [],
|
||||
|
|
@ -285,6 +285,8 @@ Ox.VideoPlayer = function(options, self) {
|
|||
self.videoHeight = self.options.height;
|
||||
self.results = [];
|
||||
|
||||
loadSubtitles();
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------------
|
||||
Keyboard
|
||||
|
|
@ -1237,8 +1239,6 @@ Ox.VideoPlayer = function(options, self) {
|
|||
|
||||
self.results = [];
|
||||
|
||||
loadSubtitles();
|
||||
|
||||
setSizes(false, function() {
|
||||
self.options.fullscreen && enterFullscreen();
|
||||
});
|
||||
|
|
@ -1535,11 +1535,6 @@ Ox.VideoPlayer = function(options, self) {
|
|||
return css;
|
||||
}
|
||||
|
||||
function getMenuSection(str) {
|
||||
var match = str.match(/<span class="(.+?)">/);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
function getPosition(e) {
|
||||
// fixme: no offsetX in firefox???
|
||||
if ($.browser.mozilla) {
|
||||
|
|
@ -1617,23 +1612,25 @@ Ox.VideoPlayer = function(options, self) {
|
|||
|
||||
function getSubtitle() {
|
||||
var subtitle = '';
|
||||
self.options.enableSubtitles && Ox.forEach(self.options.subtitles, function(v) {
|
||||
if (
|
||||
v['in'] <= self.options.position
|
||||
&& v.out >= self.options.position
|
||||
&& v.track == self.options.subtitlesTrack
|
||||
) {
|
||||
subtitle = v.text;
|
||||
return false; // break
|
||||
}
|
||||
});
|
||||
if (self.options.enableSubtitles) {
|
||||
Ox.forEach(self.options.subtitles, function(v) {
|
||||
if (
|
||||
v['in'] <= self.options.position
|
||||
&& v.out >= self.options.position
|
||||
&& Ox.contains(v.tracks, self.options.subtitlesTrack)
|
||||
) {
|
||||
subtitle = v.text;
|
||||
return false; // break
|
||||
}
|
||||
});
|
||||
}
|
||||
return subtitle;
|
||||
}
|
||||
|
||||
function getSubtitles() {
|
||||
return self.options.enableSubtitles
|
||||
? self.options.subtitles.map(function(v) {
|
||||
return v.track == self.options.subtitlesTrack;
|
||||
? self.options.subtitles.filter(function(v) {
|
||||
return Ox.contains(v.tracks, self.options.subtitlesTrack);
|
||||
})
|
||||
: [];
|
||||
}
|
||||
|
|
@ -1714,8 +1711,13 @@ Ox.VideoPlayer = function(options, self) {
|
|||
|
||||
function getVideo() {
|
||||
return self.options.video.filter(function(video) {
|
||||
return video.audioTrack == self.options.audioTrack
|
||||
&& video.resolution == self.options.resolution;
|
||||
return (
|
||||
!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() {
|
||||
if (!self.subtitlesTracks || Ox.isEmpty(self.subtitlesTracks)) {
|
||||
self.subtitlesTracks = [{
|
||||
code: self.options.subtitlesDefaultTrack,
|
||||
name: Ox.getLanguageNameByCode(
|
||||
self.options.subtitlesDefaultTrack
|
||||
)
|
||||
}];
|
||||
self.subtitlesTracks = [self.options.subtitlesDefaultTrack];
|
||||
}
|
||||
self.subtitlesTracks.push({code: '', name: 'None'});
|
||||
self.subtitlesTracks.push('None');
|
||||
if (self.options.find) {
|
||||
submitFindInput(self.options.find);
|
||||
if (self.options.duration) {
|
||||
|
|
@ -1968,23 +1965,13 @@ Ox.VideoPlayer = function(options, self) {
|
|||
}
|
||||
|
||||
function loadSubtitles() {
|
||||
if (self.options.subtitles) {
|
||||
if (self.options.subtitles.length) {
|
||||
if (Ox.isArray(self.options.subtitles)) {
|
||||
self.subtitlesTracks = Ox.sortBy(
|
||||
Ox.unique(
|
||||
self.options.subtitles.map(function(subtitle) {
|
||||
return subtitle.track;
|
||||
}).filter(function(track) {
|
||||
return !!track;
|
||||
})
|
||||
).map(function(track) {
|
||||
return {
|
||||
code: track,
|
||||
name: Ox.getLanguageNameByCode(track)
|
||||
};
|
||||
}),
|
||||
'name'
|
||||
);
|
||||
self.subtitlesTracks = Ox.sort(Ox.unique(Ox.flatten(
|
||||
self.options.subtitles.map(function(subtitle) {
|
||||
return subtitle.tracks;
|
||||
})
|
||||
)));
|
||||
loadedsubtitles();
|
||||
} else {
|
||||
if (self.options.subtitles.indexOf('\n') > -1) {
|
||||
|
|
@ -2050,86 +2037,24 @@ Ox.VideoPlayer = function(options, self) {
|
|||
}
|
||||
|
||||
function renderSettings() {
|
||||
// fixme: use proper ids (as class of span)
|
||||
var $settings = $('<div>')
|
||||
.addClass('OxControls OxSettings')
|
||||
.on({
|
||||
click: function(e) {
|
||||
var $target = $(e.target), resolution, title, track, type;
|
||||
self.$settings.hide();
|
||||
if (!$target.is('.OxLine') && !$target.is('.OxSpace')) {
|
||||
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) {
|
||||
self.options.resolution = resolution;
|
||||
setResolution();
|
||||
}
|
||||
} else if (getMenuSection(title) == 'audioTrack') {
|
||||
track = Ox.stripTags(title);
|
||||
self.options.audioTrack = Ox.getLanguageCodeByName(track);
|
||||
setAudioTrack();
|
||||
} else if (getMenuSection(title) == 'subtitlesTrack') {
|
||||
track = Ox.stripTags(title);
|
||||
self.options.subtitlesTrack = track == 'None'
|
||||
? '' : Ox.getLanguageCodeByName(track);
|
||||
setSubtitlesTrack();
|
||||
} else {
|
||||
type = self.options.timelineTypes[
|
||||
Ox.indexOf(self.options.timelineTypes, function(type) {
|
||||
return type.title == title;
|
||||
})
|
||||
].id;
|
||||
if (type != self.options.timelineType) {
|
||||
self.options.timelineType = type;
|
||||
setTimelineType();
|
||||
}
|
||||
}
|
||||
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(
|
||||
return Ox.VideoPlayerMenu({
|
||||
items: [{disabled: true, title: Ox._('Resolution')}].concat(
|
||||
self.resolutions.map(function(resolution) {
|
||||
return {
|
||||
group: 'resolution',
|
||||
id: resolution,
|
||||
checked: resolution == self.options.resolution,
|
||||
title: '<span class="resolution">'
|
||||
+ resolution + 'p</span>'
|
||||
title: resolution + 'p'
|
||||
};
|
||||
}),
|
||||
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>'
|
||||
group: 'audioTrack',
|
||||
id: track,
|
||||
checked: track == self.options.audioTrack,
|
||||
title: Ox._(track)
|
||||
};
|
||||
})
|
||||
)
|
||||
|
|
@ -2138,10 +2063,12 @@ Ox.VideoPlayer = function(options, self) {
|
|||
? [{}, {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>'
|
||||
group: 'subtitlesTrack',
|
||||
id: track,
|
||||
checked: self.options.enableSubtitles
|
||||
? track == self.options.subtitlesTrack
|
||||
: track == '',
|
||||
title: Ox._(track)
|
||||
};
|
||||
})
|
||||
)
|
||||
|
|
@ -2150,50 +2077,52 @@ Ox.VideoPlayer = function(options, self) {
|
|||
? [{}, {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: '<span class="timeline">'
|
||||
+ type.title + '</span>'
|
||||
title: type.title
|
||||
};
|
||||
})
|
||||
)
|
||||
: [],
|
||||
self.options.enableDownload
|
||||
? [{}, {title: Ox._('Download')}]
|
||||
? [{}, {id: 'download', 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');
|
||||
}
|
||||
});
|
||||
)
|
||||
})
|
||||
.addClass('OxControls OxSettings')
|
||||
.bindEvent({
|
||||
click: function(data) {
|
||||
var resolution, type;
|
||||
if (data.group == 'resolution') {
|
||||
resolution = parseInt(data.id, 10);
|
||||
if (resolution != self.options.resolution) {
|
||||
self.options.resolution = resolution;
|
||||
setResolution();
|
||||
}
|
||||
} else if (data.group == 'audioTrack') {
|
||||
self.options.audioTrack = data.id;
|
||||
setAudioTrack();
|
||||
} else if (data.group == 'subtitlesTrack') {
|
||||
self.options.subtitlesTrack = data.id == 'None'
|
||||
? '' : data.id;
|
||||
setSubtitlesTrack();
|
||||
} else if (data.group == 'timeline') {
|
||||
type = self.options.timelineTypes[
|
||||
Ox.indexOf(self.options.timelineTypes, function(type) {
|
||||
return type.title == title;
|
||||
})
|
||||
].id;
|
||||
if (type != self.options.timelineType) {
|
||||
self.options.timelineType = type;
|
||||
setTimelineType();
|
||||
}
|
||||
} else if (data.id == 'download') {
|
||||
that.triggerEvent('download');
|
||||
}
|
||||
$('<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() {
|
||||
|
|
@ -2223,7 +2152,7 @@ Ox.VideoPlayer = function(options, self) {
|
|||
}
|
||||
|
||||
function setAudioTrack() {
|
||||
// ...
|
||||
updateVideo();
|
||||
}
|
||||
|
||||
function setCensored() {
|
||||
|
|
@ -2298,17 +2227,7 @@ Ox.VideoPlayer = function(options, self) {
|
|||
}
|
||||
|
||||
function setResolution() {
|
||||
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});
|
||||
updateVideo();
|
||||
that.triggerEvent('resolution', {
|
||||
resolution: self.options.resolution
|
||||
});
|
||||
|
|
@ -2402,17 +2321,24 @@ Ox.VideoPlayer = function(options, self) {
|
|||
}
|
||||
|
||||
function setSubtitlesTrack() {
|
||||
var enableSubtitles = !!self.options.subtitlesTrack;
|
||||
var enableSubtitles = !!self.options.subtitlesTrack,
|
||||
toggleSubtitles = enableSubtitles != self.options.enableSubtitles;
|
||||
self.options.enableSubtitles = enableSubtitles;
|
||||
setSubtitle();
|
||||
self.$timeline && self.$timeline.options({
|
||||
subtitles: getSubtitles()
|
||||
});
|
||||
if (enableSubtitles != self.options.enableSubtitles) {
|
||||
if (toggleSubtitles) {
|
||||
self.options.enableSubtitles = enableSubtitles;
|
||||
that.triggerEvent('subtitles', {
|
||||
subtitles: self.options.enableSubtitles
|
||||
});
|
||||
}
|
||||
if (enableSubtitles) {
|
||||
that.triggerEvent('subtitlestrack', {
|
||||
track: self.options.subtitlesTrack
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setTimelineType() {
|
||||
|
|
@ -2421,21 +2347,13 @@ Ox.VideoPlayer = function(options, self) {
|
|||
|
||||
function setVideo() {
|
||||
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) {
|
||||
return {
|
||||
code: video.track,
|
||||
name: Ox.getLanguageNameByCode(video.track)
|
||||
};
|
||||
return video.track;
|
||||
})
|
||||
), 'name');
|
||||
if (!Ox.contains(
|
||||
self.audioTracks.map(function(track) {
|
||||
return track.code;
|
||||
}),
|
||||
self.options.audioTrack
|
||||
)) {
|
||||
self.options.audioTrack = self.audioTracks[0].code;
|
||||
));
|
||||
if (!Ox.contains(self.audioTracks, self.options.audioTrack)) {
|
||||
self.options.audioTrack = self.audioTracks[0];
|
||||
}
|
||||
self.resolutions = Ox.sort(Ox.unique(
|
||||
self.options.video.map(function(video) {
|
||||
|
|
@ -2781,6 +2699,20 @@ Ox.VideoPlayer = function(options, self) {
|
|||
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
|
||||
(num) -> <o> change volume
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue