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() { updatePlugin() {
// If there is the VHS tech if (this.player.claimSrcVhs || this.player.isLivestream) {
if (this.getVhs()) {
// Show quality selector
this._qualityButton.show(); this._qualityButton.show();
} else { } else {
// Hide quality selector
this._qualityButton.hide(); this._qualityButton.hide();
} }
} }
@ -200,6 +197,7 @@ class HlsQualitySelectorPlugin {
return 0; return 0;
}); });
if (!player.isLivestream) {
levelItems.push( levelItems.push(
this.getQualityMenuItem.call(this, { this.getQualityMenuItem.call(this, {
label: this.resolveOriginalQualityLabel(false, true), label: this.resolveOriginalQualityLabel(false, true),
@ -207,6 +205,7 @@ class HlsQualitySelectorPlugin {
selected: false, selected: false,
}) })
); );
}
levelItems.push( levelItems.push(
this.getQualityMenuItem.call(this, { 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) * Sets quality (based on media height)
* *
@ -244,6 +252,24 @@ class HlsQualitySelectorPlugin {
quality.enabled = quality.height === height || height === 'auto' || height === 'original'; 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(); this._qualityButton.unpressButton();
} }

View file

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