Skip to content

Commit

Permalink
fix (SUP-46985): Replay button unresponsive when PiP is activated (#809)
Browse files Browse the repository at this point in the history
Issue:
On safari, when PiP is open, video ends and try to play it again with
start over, nothing happened.
Safari PiP locks the video in an "ended" state, preventing .play() from
restarting playback unless the video is explicitly paused and its
currentTime is reset.
Unlike Chrome, Safari doesn't automatically reset currentTime to 0 when
a video ends.
 
Fix:
Added a browser check to detect Safari using the user agent.
Applied a conditional reset of the video (pause() and currentTime = 0)
only when:
The browser is Safari.
The video is in Picture-in-Picture (PiP) mode.

solved [SUP-46985](https://kaltura.atlassian.net/browse/SUP-46985)

[SUP-46985]:
https://kaltura.atlassian.net/browse/SUP-46985?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
  • Loading branch information
yambenari24 authored Feb 25, 2025
1 parent 8c6422c commit 41798fd
Showing 1 changed file with 21 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/engines/html5/html5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { CapabilityResult, ICapability } from '../../types';
import { PKABRRestrictionObject, PKDrmConfigObject, PKDrmDataObject, PKMediaSourceObject, PKVideoElementStore } from '../../types';
import { IEngine } from '../../types';
import Track from '../../track/track';
import Env from '../../../src/utils/env';

const SHORT_BUFFERING_TIMEOUT: number = 200;

Expand Down Expand Up @@ -513,12 +514,32 @@ export default class Html5 extends FakeEventTarget implements IEngine {
return this._mediaSourceAdapter ? this._mediaSourceAdapter.isLive() : false;
}

/**
* Checks if the video playback has ended and resets it if necessary.
* Specifically handles Safari in Picture-in-Picture mode for non-live streams.
*
* @private
* @returns {void}
*/
private resetIfPlaybackEnded(): void {
const currentTimeMs = Math.round(this._el.currentTime * 1000);
const durationMs = Math.round(this._el.duration * 1000);

if (currentTimeMs >= durationMs || this._el.ended) {
this._el.currentTime = 0;
}
}

/**
* Start/resume playback.
* @public
* @returns {?Promise<*>} - play promise
*/
public play(): Promise<void> {
if (Env.isSafari && this.isInPictureInPicture && !this.isLive()) {
this.resetIfPlaybackEnded();
}

const playPromise = this._el.play();
if (playPromise) {
playPromise.catch((err) => this.dispatchEvent(new FakeEvent(CustomEventType.PLAY_FAILED, { error: err })));
Expand Down

0 comments on commit 41798fd

Please sign in to comment.