diff --git a/src/engines/html5/html5.ts b/src/engines/html5/html5.ts index 96eefae3..333380dd 100644 --- a/src/engines/html5/html5.ts +++ b/src/engines/html5/html5.ts @@ -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; @@ -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 { + 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 })));