Skip to content

Commit

Permalink
fix(signed-language-output): use managed media source on iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
AmitMY committed Feb 2, 2024
1 parent 0eb06f0 commit 7860466
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 4 deletions.
1 change: 1 addition & 0 deletions capacitor.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const config: CapacitorConfig = {
},
ios: {
path: 'ios',
webContentsDebuggingEnabled: true,
},
android: {
path: 'android',
Expand Down
24 changes: 22 additions & 2 deletions src/app/pages/translate/pose-viewers/playable-video-encoder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
import type {ArrayBufferTarget as WebmArrayBufferTarget, Muxer as WebmMuxer} from 'webm-muxer';
import type {ArrayBufferTarget as Mp4ArrayBufferTarget, Muxer as Mp4Muxer} from 'mp4-muxer';

export function getMediaSourceClass(): typeof MediaSource {
if ('ManagedMediaSource' in window) {
return window.ManagedMediaSource as any;
}
if ('MediaSource' in window) {
return MediaSource;
}
if ('WebKitMediaSource' in window) {
return window['WebKitMediaSource'] as any;
}

console.warn('Both ManagedMediaSource and MediaSource are not supported on this device');

return null;
}

export class PlayableVideoEncoder {
muxer: WebmMuxer<WebmArrayBufferTarget> | Mp4Muxer<Mp4ArrayBufferTarget>;
videoEncoder: VideoEncoder;
Expand All @@ -23,7 +39,6 @@ export class PlayableVideoEncoder {
async init() {
await this.createWebMMuxer();
let playable = await this.isPlayable();

if (!playable) {
// If WebM is not playable or undetermined, fall back to MP4
await this.createMP4Muxer();
Expand All @@ -38,8 +53,13 @@ export class PlayableVideoEncoder {
}

if (!('mediaCapabilities' in navigator)) {
const mediaSourceClass = getMediaSourceClass();
if (!mediaSourceClass) {
return false;
}

const mimeType = `video/${this.container}; codecs="${this.codec}"`;
return MediaSource.isTypeSupported(mimeType);
return mediaSourceClass.isTypeSupported(mimeType);
}

const videoConfig = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import {PoseViewerSetting} from '../../../../modules/settings/settings.state';
import {DomSanitizer, SafeUrl} from '@angular/platform-browser';
import {Store} from '@ngxs/store';
import {takeUntil, tap} from 'rxjs/operators';
import {isIOS, isMacLike} from '../../../../core/constants';
import {
CopySignedLanguageVideo,
DownloadSignedLanguageVideo,
ShareSignedLanguageVideo,
} from '../../../../modules/translate/translate.actions';
import {BaseComponent} from '../../../../components/base/base.component';
import {Capacitor} from '@capacitor/core';
import {getMediaSourceClass} from '../../pose-viewers/playable-video-encoder';

@Component({
selector: 'app-signed-language-output',
Expand Down Expand Up @@ -72,7 +72,12 @@ export class SignedLanguageOutputComponent extends BaseComponent implements OnIn
const res = await fetch(this.videoUrl);
const blob = await res.blob();

const mediaSource = new MediaSource();
const mediaSourceClass = getMediaSourceClass();
if (!mediaSourceClass) {
return null;
}

const mediaSource = new mediaSourceClass();
mediaSource.addEventListener('sourceopen', async () => {
const sourceBuffer = mediaSource.addSourceBuffer(blob.type);
sourceBuffer.addEventListener('updateend', () => {
Expand All @@ -96,6 +101,7 @@ export class SignedLanguageOutputComponent extends BaseComponent implements OnIn
if (!video.srcObject) {
// Fallback behavior to make sure the browser can play the video
this.safeVideoUrl = null;
video.disableRemotePlayback = true; // Disable AirPlay, must be used for ManagedMediaSource
video.srcObject = await this.createVideoMediaSource();
}
}
Expand Down

0 comments on commit 7860466

Please sign in to comment.