feat(spf): basic ManagedMediaSource support for Safari (#843)

This commit is contained in:
Christian Pillsbury
2026-03-10 07:56:54 -07:00
committed by GitHub
parent f50d509749
commit 4bd287515f
4 changed files with 16 additions and 7 deletions
@@ -62,11 +62,9 @@ export function setupMediaSource({
settingUp = true;
abortController = new AbortController();
// Create MediaSource
// Note: ManagedMediaSource (Safari) requires disableRemotePlayback and
// startstreaming/endstreaming event handling that SPF doesn't yet implement.
// Use standard MediaSource until ManagedMediaSource support is added.
const mediaSource = createMediaSource();
// Prefer ManagedMediaSource when available (Safari 17+). attachMediaSource
// handles the srcObject path and sets disableRemotePlayback automatically.
const mediaSource = createMediaSource({ preferManaged: true });
// Attach to element
attachMediaSource(mediaSource, currentOwners.mediaElement!);
@@ -106,7 +106,7 @@ describe('setupMediaSource', () => {
// Wait for async operation
await vi.waitFor(() => {
expect(createMediaSource).toHaveBeenCalledWith();
expect(createMediaSource).toHaveBeenCalledWith({ preferManaged: true });
});
cleanup();
@@ -88,6 +88,10 @@ export function attachMediaSource(mediaSource: MediaSource, mediaElement: HTMLMe
const isManagedMediaSource = supportsManagedMediaSource() && mediaSource instanceof ManagedMediaSource!;
if (isManagedMediaSource) {
// ManagedMediaSource requires disableRemotePlayback — without it Safari
// will not fire sourceopen.
(mediaElement as HTMLMediaElement & { disableRemotePlayback: boolean }).disableRemotePlayback = true;
// Use srcObject for ManagedMediaSource
(mediaElement as HTMLMediaElement & { srcObject: MediaSource | null }).srcObject = mediaSource;
+8 -1
View File
@@ -7,7 +7,14 @@
* Provides better lifecycle management for background tabs and picture-in-picture.
*/
declare global {
interface ManagedMediaSource extends MediaSource {}
interface ManagedMediaSource extends MediaSource {
/** True when the browser wants the app to be streaming data. */
readonly streaming: boolean;
addEventListener(type: 'startstreaming', listener: EventListener): void;
addEventListener(type: 'endstreaming', listener: EventListener): void;
removeEventListener(type: 'startstreaming', listener: EventListener): void;
removeEventListener(type: 'endstreaming', listener: EventListener): void;
}
const ManagedMediaSource:
| {