mirror of https://github.com/Chocobozzz/PeerTube
Improve HLS redundancy
parent
60c2bc80b8
commit
8f9d3767b3
|
@ -3,7 +3,7 @@
|
|||
import * as videojs from 'video.js'
|
||||
import { P2PMediaLoaderPluginOptions, PlayerNetworkInfo, VideoJSComponentInterface } from '../peertube-videojs-typings'
|
||||
import { Engine, initHlsJsPlayer, initVideoJsContribHlsJsPlayer } from 'p2p-media-loader-hlsjs'
|
||||
import { Events } from 'p2p-media-loader-core'
|
||||
import { Events, Segment } from 'p2p-media-loader-core'
|
||||
import { timeToInt } from '../utils'
|
||||
|
||||
// videojs-hlsjs-plugin needs videojs in window
|
||||
|
@ -57,7 +57,6 @@ class P2pMediaLoaderPlugin extends Plugin {
|
|||
initVideoJsContribHlsJsPlayer(player)
|
||||
|
||||
this.startTime = timeToInt(options.startTime)
|
||||
console.log(this.startTime)
|
||||
|
||||
player.src({
|
||||
type: options.type,
|
||||
|
@ -90,11 +89,13 @@ class P2pMediaLoaderPlugin extends Plugin {
|
|||
this.trigger('resolutionChange', { auto: this.hlsjs.autoLevelEnabled, resolutionId: data.height })
|
||||
})
|
||||
|
||||
this.p2pEngine.on(Events.SegmentError, (segment, err) => {
|
||||
this.p2pEngine.on(Events.SegmentError, (segment: Segment, err) => {
|
||||
console.error('Segment error.', segment, err)
|
||||
|
||||
this.options.redundancyUrlManager.removeByOriginUrl(segment.url)
|
||||
})
|
||||
|
||||
this.statsP2PBytes.numPeers = 1 + this.options.redundancyBaseUrls.length
|
||||
this.statsP2PBytes.numPeers = 1 + this.options.redundancyUrlManager.countBaseUrls()
|
||||
|
||||
this.runStats()
|
||||
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
import { basename, dirname } from 'path'
|
||||
|
||||
class RedundancyUrlManager {
|
||||
|
||||
// Remember by what new URL we replaced an origin URL
|
||||
private replacedSegmentUrls: { [originUrl: string]: string } = {}
|
||||
|
||||
constructor (private baseUrls: string[] = []) {
|
||||
// empty
|
||||
}
|
||||
|
||||
removeBySegmentUrl (segmentUrl: string) {
|
||||
console.log('Removing redundancy of segment URL %s.', segmentUrl)
|
||||
|
||||
const baseUrl = dirname(segmentUrl)
|
||||
|
||||
this.baseUrls = this.baseUrls.filter(u => u !== baseUrl && u !== baseUrl + '/')
|
||||
}
|
||||
|
||||
removeByOriginUrl (originUrl: string) {
|
||||
const replaced = this.replacedSegmentUrls[originUrl]
|
||||
if (!replaced) return
|
||||
|
||||
return this.removeBySegmentUrl(replaced)
|
||||
}
|
||||
|
||||
buildUrl (url: string) {
|
||||
delete this.replacedSegmentUrls[url]
|
||||
|
||||
const max = this.baseUrls.length + 1
|
||||
const i = this.getRandomInt(max)
|
||||
|
||||
if (i === max - 1) return url
|
||||
|
||||
const newBaseUrl = this.baseUrls[i]
|
||||
const slashPart = newBaseUrl.endsWith('/') ? '' : '/'
|
||||
|
||||
const newUrl = newBaseUrl + slashPart + basename(url)
|
||||
this.replacedSegmentUrls[url] = newUrl
|
||||
|
||||
return newUrl
|
||||
}
|
||||
|
||||
countBaseUrls () {
|
||||
return this.baseUrls.length
|
||||
}
|
||||
|
||||
private getRandomInt (max: number) {
|
||||
return Math.floor(Math.random() * Math.floor(max))
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
RedundancyUrlManager
|
||||
}
|
|
@ -1,17 +1,9 @@
|
|||
import { basename } from 'path'
|
||||
import { Segment } from 'p2p-media-loader-core'
|
||||
import { RedundancyUrlManager } from './redundancy-url-manager'
|
||||
|
||||
function segmentUrlBuilderFactory (baseUrls: string[]) {
|
||||
function segmentUrlBuilderFactory (redundancyUrlManager: RedundancyUrlManager) {
|
||||
return function segmentBuilder (segment: Segment) {
|
||||
const max = baseUrls.length + 1
|
||||
const i = getRandomInt(max)
|
||||
|
||||
if (i === max - 1) return segment.url
|
||||
|
||||
const newBaseUrl = baseUrls[i]
|
||||
const middlePart = newBaseUrl.endsWith('/') ? '' : '/'
|
||||
|
||||
return newBaseUrl + middlePart + basename(segment.url)
|
||||
return redundancyUrlManager.buildUrl(segment.url)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,9 +12,3 @@ function segmentUrlBuilderFactory (baseUrls: string[]) {
|
|||
export {
|
||||
segmentUrlBuilderFactory
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function getRandomInt (max: number) {
|
||||
return Math.floor(Math.random() * Math.floor(max))
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import { buildVideoEmbed, buildVideoLink, copyToClipboard, getRtcConfig } from '
|
|||
import { getCompleteLocale, getShortLocale, is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n'
|
||||
import { segmentValidatorFactory } from './p2p-media-loader/segment-validator'
|
||||
import { segmentUrlBuilderFactory } from './p2p-media-loader/segment-url-builder'
|
||||
import { RedundancyUrlManager } from './p2p-media-loader/redundancy-url-manager'
|
||||
|
||||
// Change 'Playback Rate' to 'Speed' (smaller for our settings menu)
|
||||
videojsUntyped.getComponent('PlaybackRateMenuButton').prototype.controlText_ = 'Speed'
|
||||
|
@ -226,8 +227,10 @@ export class PeertubePlayerManager {
|
|||
}
|
||||
|
||||
if (mode === 'p2p-media-loader') {
|
||||
const redundancyUrlManager = new RedundancyUrlManager(options.p2pMediaLoader.redundancyBaseUrls)
|
||||
|
||||
const p2pMediaLoader: P2PMediaLoaderPluginOptions = {
|
||||
redundancyBaseUrls: options.p2pMediaLoader.redundancyBaseUrls,
|
||||
redundancyUrlManager,
|
||||
type: 'application/x-mpegURL',
|
||||
startTime: commonOptions.startTime,
|
||||
src: p2pMediaLoaderOptions.playlistUrl
|
||||
|
@ -242,7 +245,7 @@ export class PeertubePlayerManager {
|
|||
segmentValidator: segmentValidatorFactory(options.p2pMediaLoader.segmentsSha256Url),
|
||||
rtcConfig: getRtcConfig(),
|
||||
requiredSegmentsPriority: 5,
|
||||
segmentUrlBuilder: segmentUrlBuilderFactory(options.p2pMediaLoader.redundancyBaseUrls)
|
||||
segmentUrlBuilder: segmentUrlBuilderFactory(redundancyUrlManager)
|
||||
},
|
||||
segments: {
|
||||
swarmId: p2pMediaLoaderOptions.playlistUrl
|
||||
|
|
|
@ -7,6 +7,7 @@ import { PeerTubePlugin } from './peertube-plugin'
|
|||
import { WebTorrentPlugin } from './webtorrent/webtorrent-plugin'
|
||||
import { P2pMediaLoaderPlugin } from './p2p-media-loader/p2p-media-loader-plugin'
|
||||
import { PlayerMode } from './peertube-player-manager'
|
||||
import { RedundancyUrlManager } from './p2p-media-loader/redundancy-url-manager'
|
||||
|
||||
declare namespace videojs {
|
||||
interface Player {
|
||||
|
@ -62,7 +63,7 @@ type WebtorrentPluginOptions = {
|
|||
}
|
||||
|
||||
type P2PMediaLoaderPluginOptions = {
|
||||
redundancyBaseUrls: string[]
|
||||
redundancyUrlManager: RedundancyUrlManager
|
||||
type: string
|
||||
src: string
|
||||
|
||||
|
|
Loading…
Reference in New Issue