mirror of
https://github.com/p-stream/p-stream.git
synced 2026-04-21 09:32:17 +00:00
Improve autoplay handling after PiP and fullscreen on iOS
Adds logic to attempt autoplay when entering Picture-in-Picture or fullscreen modes, particularly to address autoplay restrictions on iOS. Introduces a flag to track if autoplay should be retried after loading, and ensures the UI updates appropriately if autoplay remains blocked.
This commit is contained in:
parent
3b5a1bb76e
commit
c7dcec2560
1 changed files with 56 additions and 1 deletions
|
|
@ -96,6 +96,7 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
||||||
let lastVolume = 1;
|
let lastVolume = 1;
|
||||||
let lastValidDuration = 0; // Store the last valid duration to prevent reset during source switches
|
let lastValidDuration = 0; // Store the last valid duration to prevent reset during source switches
|
||||||
let lastValidTime = 0; // Store the last valid time to prevent reset during source switches
|
let lastValidTime = 0; // Store the last valid time to prevent reset during source switches
|
||||||
|
let shouldAutoplayAfterLoad = false; // Flag to track if we should autoplay after loading completes
|
||||||
|
|
||||||
const languagePromises = new Map<
|
const languagePromises = new Map<
|
||||||
string,
|
string,
|
||||||
|
|
@ -335,6 +336,15 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
||||||
isPictureInPicture = isInWebkitPip;
|
isPictureInPicture = isInWebkitPip;
|
||||||
// Use native tracks in WebKit PiP mode for iOS compatibility
|
// Use native tracks in WebKit PiP mode for iOS compatibility
|
||||||
emit("needstrack", isInWebkitPip);
|
emit("needstrack", isInWebkitPip);
|
||||||
|
|
||||||
|
// On iOS, entering PiP may allow autoplay that was previously blocked
|
||||||
|
if (isInWebkitPip && videoElement.paused && shouldAutoplayAfterLoad) {
|
||||||
|
shouldAutoplayAfterLoad = false;
|
||||||
|
videoElement.play().catch(() => {
|
||||||
|
// If still blocked, emit pause to show play button
|
||||||
|
emit("pause", undefined);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSource() {
|
function setSource() {
|
||||||
|
|
@ -356,7 +366,22 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
||||||
});
|
});
|
||||||
videoElement.addEventListener("playing", () => emit("play", undefined));
|
videoElement.addEventListener("playing", () => emit("play", undefined));
|
||||||
videoElement.addEventListener("pause", () => emit("pause", undefined));
|
videoElement.addEventListener("pause", () => emit("pause", undefined));
|
||||||
videoElement.addEventListener("canplay", () => emit("loading", false));
|
videoElement.addEventListener("canplay", () => {
|
||||||
|
emit("loading", false);
|
||||||
|
// Attempt autoplay if this was an autoplay transition (startAt = 0)
|
||||||
|
if (shouldAutoplayAfterLoad && startAt === 0 && videoElement) {
|
||||||
|
shouldAutoplayAfterLoad = false; // Reset the flag
|
||||||
|
// Try to play - this will work on most platforms, but iOS may block it
|
||||||
|
const playPromise = videoElement.play();
|
||||||
|
if (playPromise !== undefined) {
|
||||||
|
playPromise.catch(() => {
|
||||||
|
// Play was blocked (likely iOS), emit that we're not playing
|
||||||
|
// The AutoPlayStart component will show a play button
|
||||||
|
emit("pause", undefined);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
videoElement.addEventListener("waiting", () => emit("loading", true));
|
videoElement.addEventListener("waiting", () => emit("loading", true));
|
||||||
videoElement.addEventListener("volumechange", () =>
|
videoElement.addEventListener("volumechange", () =>
|
||||||
emit(
|
emit(
|
||||||
|
|
@ -465,6 +490,20 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
||||||
!!(document as any).webkitFullscreenElement; // safari
|
!!(document as any).webkitFullscreenElement; // safari
|
||||||
emit("fullscreen", isFullscreen);
|
emit("fullscreen", isFullscreen);
|
||||||
if (!isFullscreen) emit("needstrack", false);
|
if (!isFullscreen) emit("needstrack", false);
|
||||||
|
|
||||||
|
// On iOS, entering fullscreen may allow autoplay that was previously blocked
|
||||||
|
if (
|
||||||
|
isFullscreen &&
|
||||||
|
videoElement &&
|
||||||
|
videoElement.paused &&
|
||||||
|
shouldAutoplayAfterLoad
|
||||||
|
) {
|
||||||
|
shouldAutoplayAfterLoad = false;
|
||||||
|
videoElement.play().catch(() => {
|
||||||
|
// If still blocked, emit pause to show play button
|
||||||
|
emit("pause", undefined);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fscreen.addEventListener("fullscreenchange", fullscreenChange);
|
fscreen.addEventListener("fullscreenchange", fullscreenChange);
|
||||||
|
|
||||||
|
|
@ -472,6 +511,20 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
||||||
isPictureInPicture = !!document.pictureInPictureElement;
|
isPictureInPicture = !!document.pictureInPictureElement;
|
||||||
// Use native tracks in PiP mode for better compatibility with iOS and other platforms
|
// Use native tracks in PiP mode for better compatibility with iOS and other platforms
|
||||||
emit("needstrack", isPictureInPicture);
|
emit("needstrack", isPictureInPicture);
|
||||||
|
|
||||||
|
// Entering PiP may allow autoplay that was previously blocked
|
||||||
|
if (
|
||||||
|
isPictureInPicture &&
|
||||||
|
videoElement &&
|
||||||
|
videoElement.paused &&
|
||||||
|
shouldAutoplayAfterLoad
|
||||||
|
) {
|
||||||
|
shouldAutoplayAfterLoad = false;
|
||||||
|
videoElement.play().catch(() => {
|
||||||
|
// If still blocked, emit pause to show play button
|
||||||
|
emit("pause", undefined);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("enterpictureinpicture", pictureInPictureChange);
|
document.addEventListener("enterpictureinpicture", pictureInPictureChange);
|
||||||
|
|
@ -502,6 +555,8 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
||||||
source = ops.source;
|
source = ops.source;
|
||||||
emit("loading", true);
|
emit("loading", true);
|
||||||
startAt = ops.startAt;
|
startAt = ops.startAt;
|
||||||
|
// Set autoplay flag if starting from beginning (indicates autoplay transition)
|
||||||
|
shouldAutoplayAfterLoad = ops.startAt === 0;
|
||||||
setSource();
|
setSource();
|
||||||
},
|
},
|
||||||
changeQuality(newAutomaticQuality, newPreferredQuality) {
|
changeQuality(newAutomaticQuality, newPreferredQuality) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue