jump to live on safari/iOS

This commit is contained in:
Josh Hawkins 2024-08-16 16:31:12 -05:00
parent 86a989ef53
commit d09e1e5512

View File

@ -216,7 +216,6 @@ function MSEPlayer({
type: "mse",
// @ts-expect-error for typing
value: codecs(MediaSource.isTypeSupported),
duration: Number.POSITIVE_INFINITY, // https://stackoverflow.com/questions/74461792/mediasource-api-safari-pauses-video-on-buffer-underflow
},
3000,
).catch(() => {
@ -248,7 +247,6 @@ function MSEPlayer({
{
type: "mse",
value: codecs(MediaSource.isTypeSupported),
duration: Number.POSITIVE_INFINITY, // https://stackoverflow.com/questions/74461792/mediasource-api-safari-pauses-video-on-buffer-underflow
},
3000,
).catch(() => {
@ -266,17 +264,24 @@ function MSEPlayer({
},
{ once: true },
);
videoRef.current!.src = URL.createObjectURL(msRef.current!);
videoRef.current!.srcObject = null;
if (videoRef.current && msRef.current) {
videoRef.current.src = URL.createObjectURL(msRef.current);
videoRef.current.srcObject = null;
}
}
play();
onmessageRef.current["mse"] = (msg) => {
if (msg.type !== "mse") return;
console.log(msg.value);
let sb: SourceBuffer | undefined;
try {
sb = msRef.current?.addSourceBuffer(msg.value);
if (sb?.mode) {
sb.mode = "segments";
}
} catch (e) {
// Safari sometimes throws this error
if (e instanceof DOMException && e.name === "InvalidStateError") {
@ -337,11 +342,32 @@ function MSEPlayer({
return video.buffered.end(video.buffered.length - 1) - video.currentTime;
};
const jumpToLive = () => {
if (!videoRef.current) return;
const now = Date.now();
// we either recently just started streaming or recently
// jumped to live, so don't jump to live again right away
if (now - lastJumpTimeRef.current < BUFFERING_COOLDOWN_TIMEOUT) {
return;
}
const buffered = videoRef.current.buffered;
if (buffered.length > 0) {
const liveEdge = buffered.end(buffered.length - 1);
// Jump to the live edge
videoRef.current.currentTime = liveEdge;
lastJumpTimeRef.current = now;
console.log(camera, "jumped to live");
}
};
const calculateAdaptiveBufferThreshold = () => {
const filledEntries = bufferTimes.current.length;
const sum = bufferTimes.current.reduce((a, b) => a + b, 0);
const averageBufferTime = filledEntries ? sum / filledEntries : 0;
return averageBufferTime * 1.5;
return averageBufferTime * (isSafari || isIOS ? 2 : 1.5);
};
const calculateAdaptivePlaybackRate = (
@ -496,14 +522,21 @@ function MSEPlayer({
// if we're above our rolling average threshold or have > 3 seconds of
// buffered data and we're playing, we may have drifted from actual live
// time, so increase playback rate to compensate
// time, so increase playback rate to compensate - non safari/ios only
if (
videoRef.current &&
isPlaying &&
playbackEnabled &&
Date.now() - lastJumpTimeRef.current > BUFFERING_COOLDOWN_TIMEOUT
) {
videoRef.current.playbackRate = playbackRate;
// Jump to live on Safari/iOS due to a change of playback rate causing re-buffering
if (isSafari || isIOS) {
if (bufferTime > bufferThreshold) {
jumpToLive();
}
} else {
videoRef.current.playbackRate = playbackRate;
}
}
console.log(