2017-11-21 2 views

Antwort

0

Auf der Grundlage Ihrer Frage nehme ich Sie verwenden HLS oder DASH nicht, sondern Sie habe mehrere MP4s, die mit unterschiedlichen Bitraten oder Auflösungen codiert wurden. Die MP4 müssen für die Unterstützung für progressiven Download ordnungsgemäß codiert werden, und der http-Server muss Byte-Range-Header unterstützen. Es ist möglich, den Jwplayer-Puffer zu überwachen, und wenn er zu niedrig wird, können Sie zu einer Quelle mit geringerer Qualität wechseln. Wir tun dies als www.scormfly.com. Hier ist ein Typoskript-Code, mit dem Sie beginnen können.

import * as _ from 'lodash' 
import Controls, { StreamingMode } from '../controls' 
const controls = new Controls() 

export default class ProgressiveDownloadProvider { 
    private positionBeforeQualityChange = 0 
    private isSeeking: boolean 
    private jwplayer: JWPlayer 
    constructor(jwplayer: JWPlayer) { 
    jwplayer.on('levels', this.setToBestFitQuality) 
    jwplayer.on('levelsChanged', this.onQualityChange) 
    jwplayer.on('time', this.tick) 

    this.jwplayer = jwplayer 
    } 

    public tick(args: TimeParam) { 
    if (this.isQualityTooHigh(args.position)) { 
     this.reduceQualityLevel() 
    } 
    } 
    public onResize() { 
    // don't change the quality unless the the video is playing 
    // because changing the quality will start playing the video 
    if (this.jwplayer.getState().toUpperCase() === 'PLAYING') { 
     this.setToBestFitQuality() 
    } 
    } 

    private isQualityTooHigh(currentPosition: number): boolean { 
    if (this.isSeeking) { return false } 
    if (currentPosition < this.positionBeforeQualityChange + 1) { return false } 

    const videoElement = $('video')[0] 
    const bufferPositionInSeconds = videoElement ? 
     (videoElement as any).buffered.end((videoElement as any).buffered.length - 1) : 
     this.jwplayer.getBuffer()/100.0 * controls.getDuration() 
    const bufferAlmostComplete = bufferPositionInSeconds > controls.getDuration() - 10 
    if (bufferAlmostComplete) { return false } 

    const bufferRunningLow = bufferPositionInSeconds - currentPosition < 0.5 
    return bufferRunningLow 
    } 

    private reduceQualityLevel() { 
    // qualityLevels are indexed 0-best to 5-worst quality 
    const qualityLevels = this.jwplayer.getQualityLevels() 
    const indexOfWorstQuality = qualityLevels.length - 1 
    const indexOfCurrentQuality = this.jwplayer.getCurrentQuality() 
    if (indexOfCurrentQuality === indexOfWorstQuality) { return } 

    // tslint:disable-next-line:no-console 
    console.log('reducing quality from ' 
     + qualityLevels[indexOfCurrentQuality].label + ' to ' 
     + qualityLevels[indexOfCurrentQuality + 1].label + ' due to buffering') 
    this.jwplayer.setCurrentQuality(indexOfCurrentQuality + 1) 
    } 

    // detect viewport height and use the best fitting source 
    private setToBestFitQuality() { 
    if (controls.getStreamingMode() === StreamingMode.YouTube) { return } // don't adjust youtube videos 
    if (typeof this.jwplayer.getQualityLevels() === 'undefined') { return } // not ready yet 
    if (this.jwplayer.getQualityLevels().length === 0) { return } // nothing to do 
    if (this.jwplayer.getCurrentQuality() === -1) { return } // this can happen onComplete 

    const newHeight = $('#jwPlayer').height() 

    const currentQuality = this.jwplayer.getQualityLevels()[this.jwplayer.getCurrentQuality()].label // eg 720p HD 

    let optimalQuality: string 
    const heights = _.map(this.jwplayer.getQualityLevels(), (item) => item.label.replace('p', '')) 
    for (const height of heights) { 
     const tooBig = height > newHeight 
     if (tooBig) { 
     break 
     } 
     optimalQuality = height + 'p' 
    } 

    if (optimalQuality !== this.jwplayer.getQualityLevels()[this.jwplayer.getCurrentQuality()].label) { 
     // tslint:disable-next-line:no-console 
     console.log('Switching quality to ' 
     + optimalQuality + ' because window will fit up to ' 
     + $(window).height() + 'p') 

     // find desired quality level and use it 
     const levels = this.jwplayer.getQualityLevels() 
     for (let j = 0; j < levels.length; j++) { 
     if (levels[j].label === optimalQuality) { 
      this.jwplayer.setCurrentQuality(j) 
     } 
     } 
    } 
    } 

    // preserve playback position 
    private onQualityChange() { 
    this.positionBeforeQualityChange = this.jwplayer.getPosition() 
    setTimeout(() => { 
     controls.seek(this.positionBeforeQualityChange) 
    }, 500) 
    } 

} 
Verwandte Themen