Use non-VHS link when "original" is selected.

Ticket: 638
This commit is contained in:
infinite-persistence 2022-04-12 18:02:13 +08:00 committed by Thomas Zarebczan
parent 33adf7aab2
commit c1fb160452
2 changed files with 53 additions and 24 deletions

View file

@ -50,12 +50,9 @@ class HlsQualitySelectorPlugin {
}
updatePlugin() {
// If there is the VHS tech
if (this.getVhs()) {
// Show quality selector
if (this.player.claimSrcVhs || this.player.isLivestream) {
this._qualityButton.show();
} else {
// Hide quality selector
this._qualityButton.hide();
}
}
@ -200,13 +197,15 @@ class HlsQualitySelectorPlugin {
return 0;
});
levelItems.push(
this.getQualityMenuItem.call(this, {
label: this.resolveOriginalQualityLabel(false, true),
value: 'original',
selected: false,
})
);
if (!player.isLivestream) {
levelItems.push(
this.getQualityMenuItem.call(this, {
label: this.resolveOriginalQualityLabel(false, true),
value: 'original',
selected: false,
})
);
}
levelItems.push(
this.getQualityMenuItem.call(this, {
@ -224,6 +223,15 @@ class HlsQualitySelectorPlugin {
}
}
swapSrcTo(mode = 'original') {
const currentTime = this.player.currentTime();
this.player.src(mode === 'vhs' ? this.player.claimSrcVhs : this.player.claimSrcOriginal);
this.player.load();
this.player.currentTime(currentTime);
console.assert(mode === 'vhs' || mode === 'original', 'Unexpected input');
}
/**
* Sets quality (based on media height)
*
@ -244,6 +252,24 @@ class HlsQualitySelectorPlugin {
quality.enabled = quality.height === height || height === 'auto' || height === 'original';
}
if (height === 'original') {
if (this.player.currentSrc() !== this.player.claimSrcOriginal.src) {
setTimeout(() => this.swapSrcTo('original'));
}
} else {
if (!this.player.isLivestream && this.player.currentSrc() !== this.player.claimSrcVhs.src) {
setTimeout(() => this.swapSrcTo('vhs'));
if (height !== 'auto') {
// -- Re-select quality --
// Until we have "persistent quality" implemented, we need to do this
// because the VHS internals default to "auto" when initialized,
// causing a GUI mismatch.
setTimeout(() => this.setQuality(height), 1000);
}
}
}
this._qualityButton.unpressButton();
}

View file

@ -30,10 +30,17 @@ require('@silvermine/videojs-chromecast')(videojs);
require('@silvermine/videojs-airplay')(videojs);
export type Player = {
// -- custom --
claimSrcOriginal: ?{ src: string, type: string },
claimSrcVhs: ?{ src: string, type: string },
isLivestream?: boolean,
// -- original --
controlBar: { addChild: (string, any) => void },
loadingSpinner: any,
autoplay: (any) => boolean,
chromecast: (any) => void,
hlsQualitySelector: ?any,
tech: (?boolean) => { vhs: ?any },
currentTime: (?number) => number,
dispose: () => void,
duration: () => number,
@ -51,6 +58,8 @@ export type Player = {
playbackRate: (?number) => number,
readyState: () => number,
requestFullscreen: () => boolean,
src: ({ src: string, type: string }) => ?string,
currentSrc: () => string,
userActive: (?boolean) => boolean,
volume: (?number) => number,
};
@ -364,29 +373,23 @@ export default React.memo<Props>(function VideoJs(props: Props) {
}
if (isLivestreamClaim && userClaimId) {
vjsPlayer.isLivestream = true;
vjsPlayer.addClass('livestreamPlayer');
vjsPlayer.src({
type: 'application/x-mpegURL',
src: livestreamVideoUrl,
});
vjsPlayer.src({ type: 'application/x-mpegURL', src: livestreamVideoUrl });
} else {
vjsPlayer.isLivestream = false;
vjsPlayer.removeClass('livestreamPlayer');
// change to m3u8 if applicable
const response = await fetch(source, { method: 'HEAD', cache: 'no-store' });
playerServerRef.current = response.headers.get('x-powered-by');
vjsPlayer.claimSrcOriginal = { type: sourceType, src: source };
if (response && response.redirected && response.url && response.url.endsWith('m3u8')) {
vjsPlayer.src({
type: 'application/x-mpegURL',
src: response.url,
});
vjsPlayer.claimSrcVhs = { type: 'application/x-mpegURL', src: response.url };
vjsPlayer.src(vjsPlayer.claimSrcVhs);
} else {
vjsPlayer.src({
type: sourceType,
src: source,
});
vjsPlayer.src(vjsPlayer.claimSrcOriginal);
}
}