218 lines
No EOL
9.4 KiB
JavaScript
218 lines
No EOL
9.4 KiB
JavaScript
define(["appSettings", "browser", "events"], function(appSettings, browser, events) {
|
|
"use strict";
|
|
|
|
function getSavedVolume() {
|
|
return appSettings.get("volume") || 1
|
|
}
|
|
|
|
function saveVolume(value) {
|
|
value && appSettings.set("volume", value)
|
|
}
|
|
|
|
function getCrossOriginValue(mediaSource) {
|
|
return mediaSource.IsRemote ? null : "anonymous"
|
|
}
|
|
|
|
function canPlayNativeHls() {
|
|
var media = document.createElement("video");
|
|
return !(!media.canPlayType("application/x-mpegURL").replace(/no/, "") && !media.canPlayType("application/vnd.apple.mpegURL").replace(/no/, ""))
|
|
}
|
|
|
|
function enableHlsShakaPlayer(item, mediaSource, mediaType) {
|
|
if (window.MediaSource && MediaSource.isTypeSupported) {
|
|
if (canPlayNativeHls()) {
|
|
if (browser.edge && "Video" === mediaType) return !0;
|
|
mediaSource.RunTimeTicks
|
|
}
|
|
return !0
|
|
}
|
|
return !1
|
|
}
|
|
|
|
function enableHlsJsPlayer(runTimeTicks, mediaType) {
|
|
if (null == window.MediaSource) return !1;
|
|
if (browser.iOS) return !1;
|
|
if (browser.tizen || browser.web0s) return !1;
|
|
if (canPlayNativeHls()) {
|
|
if (browser.android && "Audio" === mediaType) return !0;
|
|
if (browser.edge, runTimeTicks) return !1
|
|
}
|
|
return !0
|
|
}
|
|
|
|
function handleHlsJsMediaError(instance, reject) {
|
|
var hlsPlayer = instance._hlsPlayer;
|
|
if (hlsPlayer) {
|
|
var now = Date.now();
|
|
window.performance && window.performance.now && (now = performance.now()), !recoverDecodingErrorDate || now - recoverDecodingErrorDate > 3e3 ? (recoverDecodingErrorDate = now, console.log("try to recover media Error ..."), hlsPlayer.recoverMediaError()) : !recoverSwapAudioCodecDate || now - recoverSwapAudioCodecDate > 3e3 ? (recoverSwapAudioCodecDate = now, console.log("try to swap Audio Codec and recover media Error ..."), hlsPlayer.swapAudioCodec(), hlsPlayer.recoverMediaError()) : (console.error("cannot recover, last media error recovery failed ..."), reject ? reject() : onErrorInternal(instance, "mediadecodeerror"))
|
|
}
|
|
}
|
|
|
|
function onErrorInternal(instance, type) {
|
|
instance.destroyCustomTrack && instance.destroyCustomTrack(instance._mediaElement), events.trigger(instance, "error", [{
|
|
type: type
|
|
}])
|
|
}
|
|
|
|
function isValidDuration(duration) {
|
|
return !(!duration || isNaN(duration) || duration === Number.POSITIVE_INFINITY || duration === Number.NEGATIVE_INFINITY)
|
|
}
|
|
|
|
function setCurrentTimeIfNeeded(element, seconds, allowance) {
|
|
Math.abs((element.currentTime || 0) - seconds) >= allowance && (element.currentTime = seconds)
|
|
}
|
|
|
|
function seekOnPlaybackStart(instance, element, ticks) {
|
|
var seconds = (ticks || 0) / 1e7;
|
|
if (seconds) {
|
|
(instance.currentSrc() || "").toLowerCase();
|
|
setCurrentTimeIfNeeded(element, seconds, 5), setTimeout(function() {
|
|
setCurrentTimeIfNeeded(element, seconds, 10)
|
|
}, 2500)
|
|
}
|
|
}
|
|
|
|
function applySrc(elem, src, options) {
|
|
return window.Windows && options.mediaSource && options.mediaSource.IsLocal ? Windows.Storage.StorageFile.getFileFromPathAsync(options.url).then(function(file) {
|
|
var playlist = new Windows.Media.Playback.MediaPlaybackList,
|
|
source1 = Windows.Media.Core.MediaSource.createFromStorageFile(file),
|
|
startTime = (options.playerStartPositionTicks || 0) / 1e4;
|
|
return playlist.items.append(new Windows.Media.Playback.MediaPlaybackItem(source1, startTime)), elem.src = URL.createObjectURL(playlist, {
|
|
oneTimeOnly: !0
|
|
}), Promise.resolve()
|
|
}) : (elem.src = src, Promise.resolve())
|
|
}
|
|
|
|
function onSuccessfulPlay(elem, onErrorFn) {
|
|
elem.addEventListener("error", onErrorFn)
|
|
}
|
|
|
|
function playWithPromise(elem, onErrorFn) {
|
|
try {
|
|
var promise = elem.play();
|
|
return promise && promise.then ? promise.catch(function(e) {
|
|
var errorName = (e.name || "").toLowerCase();
|
|
return "notallowederror" === errorName || "aborterror" === errorName ? (onSuccessfulPlay(elem, onErrorFn), Promise.resolve()) : Promise.reject()
|
|
}) : (onSuccessfulPlay(elem, onErrorFn), Promise.resolve())
|
|
} catch (err) {
|
|
return console.log("error calling video.play: " + err), Promise.reject()
|
|
}
|
|
}
|
|
|
|
function destroyCastPlayer(instance) {
|
|
var player = instance._castPlayer;
|
|
if (player) {
|
|
try {
|
|
player.unload()
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
instance._castPlayer = null
|
|
}
|
|
}
|
|
|
|
function destroyShakaPlayer(instance) {
|
|
var player = instance._shakaPlayer;
|
|
if (player) {
|
|
try {
|
|
player.destroy()
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
instance._shakaPlayer = null
|
|
}
|
|
}
|
|
|
|
function destroyHlsPlayer(instance) {
|
|
var player = instance._hlsPlayer;
|
|
if (player) {
|
|
try {
|
|
player.destroy()
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
instance._hlsPlayer = null
|
|
}
|
|
}
|
|
|
|
function destroyFlvPlayer(instance) {
|
|
var player = instance._flvPlayer;
|
|
if (player) {
|
|
try {
|
|
player.unload(), player.detachMediaElement(), player.destroy()
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
instance._flvPlayer = null
|
|
}
|
|
}
|
|
|
|
function bindEventsToHlsPlayer(instance, hls, elem, onErrorFn, resolve, reject) {
|
|
hls.on(Hls.Events.MANIFEST_PARSED, function() {
|
|
playWithPromise(elem, onErrorFn).then(resolve, function() {
|
|
reject && (reject(), reject = null)
|
|
})
|
|
}), hls.on(Hls.Events.ERROR, function(event, data) {
|
|
switch (console.log("HLS Error: Type: " + data.type + " Details: " + (data.details || "") + " Fatal: " + (data.fatal || !1)), data.type) {
|
|
case Hls.ErrorTypes.NETWORK_ERROR:
|
|
if (data.response && data.response.code && data.response.code >= 400) return console.log("hls.js response error code: " + data.response.code), hls.destroy(), void(reject ? (reject("servererror"), reject = null) : onErrorInternal(instance, "servererror"))
|
|
}
|
|
if (data.fatal) switch (data.type) {
|
|
case Hls.ErrorTypes.NETWORK_ERROR:
|
|
data.response && 0 === data.response.code ? (console.log("hls.js response error code: " + data.response.code), hls.destroy(), reject ? (reject("network"), reject = null) : onErrorInternal(instance, "network")) : (console.log("fatal network error encountered, try to recover"), hls.startLoad());
|
|
break;
|
|
case Hls.ErrorTypes.MEDIA_ERROR:
|
|
console.log("fatal media error encountered, try to recover");
|
|
var currentReject = reject;
|
|
reject = null, handleHlsJsMediaError(instance, currentReject);
|
|
break;
|
|
default:
|
|
console.log("Cannot recover from hls error - destroy and trigger error"), hls.destroy(), reject ? (reject(), reject = null) : onErrorInternal(instance, "mediadecodeerror")
|
|
}
|
|
})
|
|
}
|
|
|
|
function onEndedInternal(instance, elem, onErrorFn) {
|
|
elem.removeEventListener("error", onErrorFn), elem.src = "", elem.innerHTML = "", elem.removeAttribute("src"), destroyHlsPlayer(instance), destroyFlvPlayer(instance), destroyShakaPlayer(instance), destroyCastPlayer(instance);
|
|
var stopInfo = {
|
|
src: instance._currentSrc
|
|
};
|
|
events.trigger(instance, "stopped", [stopInfo]), instance._currentTime = null, instance._currentSrc = null, instance._currentPlayOptions = null
|
|
}
|
|
|
|
function getBufferedRanges(instance, elem) {
|
|
var offset, ranges = [],
|
|
seekable = elem.buffered || [],
|
|
currentPlayOptions = instance._currentPlayOptions;
|
|
currentPlayOptions && (offset = currentPlayOptions.transcodingOffsetTicks), offset = offset || 0;
|
|
for (var i = 0, length = seekable.length; i < length; i++) {
|
|
var start = seekable.start(i),
|
|
end = seekable.end(i);
|
|
isValidDuration(start) || (start = 0), isValidDuration(end) ? ranges.push({
|
|
start: 1e7 * start + offset,
|
|
end: 1e7 * end + offset
|
|
}) : end = 0
|
|
}
|
|
return ranges
|
|
}
|
|
var recoverDecodingErrorDate, recoverSwapAudioCodecDate;
|
|
return {
|
|
getSavedVolume: getSavedVolume,
|
|
saveVolume: saveVolume,
|
|
enableHlsJsPlayer: enableHlsJsPlayer,
|
|
enableHlsShakaPlayer: enableHlsShakaPlayer,
|
|
handleHlsJsMediaError: handleHlsJsMediaError,
|
|
isValidDuration: isValidDuration,
|
|
onErrorInternal: onErrorInternal,
|
|
seekOnPlaybackStart: seekOnPlaybackStart,
|
|
applySrc: applySrc,
|
|
playWithPromise: playWithPromise,
|
|
destroyHlsPlayer: destroyHlsPlayer,
|
|
destroyFlvPlayer: destroyFlvPlayer,
|
|
destroyCastPlayer: destroyCastPlayer,
|
|
bindEventsToHlsPlayer: bindEventsToHlsPlayer,
|
|
onEndedInternal: onEndedInternal,
|
|
getCrossOriginValue: getCrossOriginValue,
|
|
getBufferedRanges: getBufferedRanges
|
|
}
|
|
}); |