Add PeerTube support
This commit is contained in:
parent
f365d4192a
commit
614a039266
|
@ -22,6 +22,7 @@ var order = [
|
||||||
'rtmp.coffee',
|
'rtmp.coffee',
|
||||||
'hls.coffee',
|
'hls.coffee',
|
||||||
'twitchclip.coffee',
|
'twitchclip.coffee',
|
||||||
|
'peertube.coffee',
|
||||||
'update.coffee'
|
'update.coffee'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
113
player/peertube.coffee
Normal file
113
player/peertube.coffee
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
PEERTUBE_EMBED_WARNING = 'This channel is embedding PeerTube content from %link%.
|
||||||
|
PeerTube instances may use P2P technology that will expose your IP address to third parties, including but not
|
||||||
|
limited to other users in this channel. It is also conceivable that if the content in question is in violation of
|
||||||
|
copyright laws your IP address could be potentially be observed by legal authorities monitoring the tracker of
|
||||||
|
this PeerTube instance. The operators of %site% are not responsible for the data sent by the embedded player to
|
||||||
|
third parties on your behalf.<br><br> If you understand the risks, wish to assume all liability, and continue to
|
||||||
|
the content, click "Embed" below to allow the content to be embedded.<hr>'
|
||||||
|
|
||||||
|
window.PeerPlayer = class PeerPlayer extends Player
|
||||||
|
constructor: (data) ->
|
||||||
|
if not (this instanceof PeerPlayer)
|
||||||
|
return new PeerPlayer(data)
|
||||||
|
|
||||||
|
@warn(data)
|
||||||
|
|
||||||
|
warn: (data) ->
|
||||||
|
site = new URL(document.URL).hostname
|
||||||
|
embedSrc = data.meta.embed.domain
|
||||||
|
link = "<a href=\"http://#{embedSrc}\" target=\"_blank\"><strong>#{embedSrc}</strong></a>"
|
||||||
|
alert = makeAlert('Privacy Advisory', PEERTUBE_EMBED_WARNING.replace('%link%', link).replace('%site%', site),
|
||||||
|
'alert-warning')
|
||||||
|
.removeClass('col-md-12')
|
||||||
|
$('<button/>').addClass('btn btn-default')
|
||||||
|
.text('Embed')
|
||||||
|
.on('click', =>
|
||||||
|
@load(data)
|
||||||
|
)
|
||||||
|
.appendTo(alert.find('.alert'))
|
||||||
|
removeOld(alert)
|
||||||
|
|
||||||
|
load: (data) ->
|
||||||
|
@setMediaProperties(data)
|
||||||
|
|
||||||
|
waitUntilDefined(window, 'PeerTubePlayer', =>
|
||||||
|
video = $('<iframe/>')
|
||||||
|
removeOld(video)
|
||||||
|
video.attr(
|
||||||
|
src: "https://#{data.meta.embed.domain}/videos/embed/#{data.meta.embed.uuid}?api=1"
|
||||||
|
allow: 'autoplay; fullscreen'
|
||||||
|
)
|
||||||
|
|
||||||
|
if USEROPTS.wmode_transparent
|
||||||
|
video.attr('wmode', 'transparent')
|
||||||
|
|
||||||
|
@peertube = new PeerTubePlayer(video[0])
|
||||||
|
|
||||||
|
@peertube.addEventListener('playbackStatusChange', (status) =>
|
||||||
|
@paused = status == 'paused'
|
||||||
|
if CLIENT.leader
|
||||||
|
sendVideoUpdate()
|
||||||
|
)
|
||||||
|
|
||||||
|
@peertube.addEventListener('playbackStatusUpdate', (status) =>
|
||||||
|
@peertube.currentTime = status.position
|
||||||
|
|
||||||
|
if status.playbackState == "ended" and CLIENT.leader
|
||||||
|
socket.emit('playNext')
|
||||||
|
)
|
||||||
|
|
||||||
|
@peertube.addEventListener('volumeChange', (volume) =>
|
||||||
|
VOLUME = volume
|
||||||
|
setOpt("volume", VOLUME)
|
||||||
|
)
|
||||||
|
|
||||||
|
@play()
|
||||||
|
@setVolume(VOLUME)
|
||||||
|
)
|
||||||
|
|
||||||
|
play: ->
|
||||||
|
@paused = false
|
||||||
|
if @peertube and @peertube.ready
|
||||||
|
@peertube.play().catch((error) ->
|
||||||
|
console.error('PeerTube::play():', error)
|
||||||
|
)
|
||||||
|
|
||||||
|
pause: ->
|
||||||
|
@paused = true
|
||||||
|
if @peertube and @peertube.ready
|
||||||
|
@peertube.pause().catch((error) ->
|
||||||
|
console.error('PeerTube::pause():', error)
|
||||||
|
)
|
||||||
|
|
||||||
|
seekTo: (time) ->
|
||||||
|
if @peertube and @peertube.ready
|
||||||
|
@peertube.seek(time)
|
||||||
|
|
||||||
|
getVolume: (cb) ->
|
||||||
|
if @peertube and @peertube.ready
|
||||||
|
@peertube.getVolume().then((volume) ->
|
||||||
|
cb(parseFloat(volume))
|
||||||
|
).catch((error) ->
|
||||||
|
console.error('PeerTube::getVolume():', error)
|
||||||
|
)
|
||||||
|
else
|
||||||
|
cb(VOLUME)
|
||||||
|
|
||||||
|
setVolume: (volume) ->
|
||||||
|
if @peertube and @peertube.ready
|
||||||
|
@peertube.setVolume(volume).catch((error) ->
|
||||||
|
console.error('PeerTube::setVolume():', error)
|
||||||
|
)
|
||||||
|
|
||||||
|
getTime: (cb) ->
|
||||||
|
if @peertube and @peertube.ready
|
||||||
|
cb(@peertube.currentTime)
|
||||||
|
else
|
||||||
|
cb(0)
|
||||||
|
|
||||||
|
setQuality: (quality) ->
|
||||||
|
# USEROPTS.default_quality
|
||||||
|
# @peertube.getResolutions()
|
||||||
|
# @peertube.setResolution(resolutionId : number)
|
||||||
|
|
|
@ -14,6 +14,7 @@ TYPE_MAP =
|
||||||
sb: StreamablePlayer
|
sb: StreamablePlayer
|
||||||
tc: TwitchClipPlayer
|
tc: TwitchClipPlayer
|
||||||
cm: VideoJSPlayer
|
cm: VideoJSPlayer
|
||||||
|
pt: PeerPlayer
|
||||||
|
|
||||||
window.loadMediaPlayer = (data) ->
|
window.loadMediaPlayer = (data) ->
|
||||||
try
|
try
|
||||||
|
|
|
@ -6,6 +6,7 @@ const ffmpeg = require("./ffmpeg");
|
||||||
const mediaquery = require("@cytube/mediaquery");
|
const mediaquery = require("@cytube/mediaquery");
|
||||||
const YouTube = require("@cytube/mediaquery/lib/provider/youtube");
|
const YouTube = require("@cytube/mediaquery/lib/provider/youtube");
|
||||||
const Vimeo = require("@cytube/mediaquery/lib/provider/vimeo");
|
const Vimeo = require("@cytube/mediaquery/lib/provider/vimeo");
|
||||||
|
const PeerTube = require("@cytube/mediaquery/lib/provider/peertube");
|
||||||
const Streamable = require("@cytube/mediaquery/lib/provider/streamable");
|
const Streamable = require("@cytube/mediaquery/lib/provider/streamable");
|
||||||
const TwitchVOD = require("@cytube/mediaquery/lib/provider/twitch-vod");
|
const TwitchVOD = require("@cytube/mediaquery/lib/provider/twitch-vod");
|
||||||
const TwitchClip = require("@cytube/mediaquery/lib/provider/twitch-clip");
|
const TwitchClip = require("@cytube/mediaquery/lib/provider/twitch-clip");
|
||||||
|
@ -366,6 +367,16 @@ var Getters = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/* PeerTube network */
|
||||||
|
pt: function (id, callback) {
|
||||||
|
PeerTube.lookup(id).then(video => {
|
||||||
|
video = new Media(video.id, video.title, video.duration, "pt", video.meta);
|
||||||
|
callback(null, video);
|
||||||
|
}).catch(error => {
|
||||||
|
callback(error.message || error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/* custom media - https://github.com/calzoneman/sync/issues/655 */
|
/* custom media - https://github.com/calzoneman/sync/issues/655 */
|
||||||
cm: async function (id, callback) {
|
cm: async function (id, callback) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -205,6 +205,9 @@
|
||||||
return "https://clips.twitch.tv/" + id;
|
return "https://clips.twitch.tv/" + id;
|
||||||
case "cm":
|
case "cm":
|
||||||
return id;
|
return id;
|
||||||
|
case "pt":
|
||||||
|
const [domain,uuid] = id.split(';');
|
||||||
|
return `https://${domain}/videos/watch/${uuid}`;
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,6 +252,7 @@ html(lang="en")
|
||||||
script(defer, src="https://www.youtube.com/iframe_api")
|
script(defer, src="https://www.youtube.com/iframe_api")
|
||||||
script(defer, src="https://api.dmcdn.net/all.js")
|
script(defer, src="https://api.dmcdn.net/all.js")
|
||||||
script(defer, src="https://player.vimeo.com/api/player.js")
|
script(defer, src="https://player.vimeo.com/api/player.js")
|
||||||
|
script(defer, src="/js/peertube.js")
|
||||||
script(defer, src="/js/sc.js")
|
script(defer, src="/js/sc.js")
|
||||||
script(defer, src="/js/video.js")
|
script(defer, src="/js/video.js")
|
||||||
script(defer, src="/js/videojs-contrib-hls.min.js")
|
script(defer, src="/js/videojs-contrib-hls.min.js")
|
||||||
|
|
1
www/js/peertube.js
Normal file
1
www/js/peertube.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -52,6 +52,12 @@ function formatURL(data) {
|
||||||
return data.id;
|
return data.id;
|
||||||
case "cu":
|
case "cu":
|
||||||
return data.meta.embed.src;
|
return data.meta.embed.src;
|
||||||
|
case "pt":
|
||||||
|
if(data.meta.embed.onlyLong){
|
||||||
|
return `https://${data.meta.embed.domain}/videos/watch/${data.meta.embed.uuid}`;
|
||||||
|
} else {
|
||||||
|
return `https://${data.meta.embed.domain}/w/${data.meta.embed.short}`;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return "#";
|
return "#";
|
||||||
}
|
}
|
||||||
|
@ -1385,6 +1391,19 @@ function parseMediaLink(url) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PeerTubes */
|
||||||
|
if(data.pathname.match('^/w/|^/videos/watch/')){
|
||||||
|
const regLong = [8, 4, 4, 4, 12].map(x => `[0-9a-f]{${x}}`).join('-');
|
||||||
|
const regShort = '[a-zA-Z0-9]{22}';
|
||||||
|
const pattern = new RegExp(`(?:/w/|/videos/watch/)(?:(?<short>${regShort})|(?<long>${regLong}))`);
|
||||||
|
if((m = data.pathname.match(pattern))) {
|
||||||
|
return {
|
||||||
|
id: `${data.hostname};${m.groups.short || m.groups.long}`,
|
||||||
|
type: "pt"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Raw file (server will check) */
|
/* Raw file (server will check) */
|
||||||
if (data.protocol.match(/^http/)) {
|
if (data.protocol.match(/^http/)) {
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in a new issue