mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Support ManagedMediaSource and update docs to reflect iOS 17.1+ supports MSE (#8160)
* Refactor media source handling in MsePlayer.js and Birdseye.jsx to support ManagedMediaSource * lint * Update docs to reflect iOS supporting mse --------- Co-authored-by: Sergey Krashevich <svk@svk.su>
This commit is contained in:
parent
4c7ea01137
commit
fa6c6c50d0
@ -9,11 +9,11 @@ Frigate has different live view options, some of which require the bundled `go2r
|
|||||||
|
|
||||||
Live view options can be selected while viewing the live stream. The options are:
|
Live view options can be selected while viewing the live stream. The options are:
|
||||||
|
|
||||||
| Source | Latency | Frame Rate | Resolution | Audio | Requires go2rtc | Other Limitations |
|
| Source | Latency | Frame Rate | Resolution | Audio | Requires go2rtc | Other Limitations |
|
||||||
| ------ | ------- | ------------------------------------- | -------------- | ---------------------------- | --------------- | -------------------------------------------- |
|
| ------ | ------- | ------------------------------------- | -------------- | ---------------------------- | --------------- | ------------------------------------------------- |
|
||||||
| jsmpeg | low | same as `detect -> fps`, capped at 10 | same as detect | no | no | none |
|
| jsmpeg | low | same as `detect -> fps`, capped at 10 | same as detect | no | no | none |
|
||||||
| mse | low | native | native | yes (depends on audio codec) | yes | not supported on iOS, Firefox is h.264 only |
|
| mse | low | native | native | yes (depends on audio codec) | yes | iPhone requires iOS 17.1+, Firefox is h.264 only |
|
||||||
| webrtc | lowest | native | native | yes (depends on audio codec) | yes | requires extra config, doesn't support h.265 |
|
| webrtc | lowest | native | native | yes (depends on audio codec) | yes | requires extra config, doesn't support h.265 |
|
||||||
|
|
||||||
### Audio Support
|
### Audio Support
|
||||||
|
|
||||||
|
@ -157,12 +157,9 @@ class VideoRTC extends HTMLElement {
|
|||||||
if (this.ws) this.ws.send(JSON.stringify(value));
|
if (this.ws) this.ws.send(JSON.stringify(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
codecs(type) {
|
/** @param {Function} isSupported */
|
||||||
const test =
|
codecs(isSupported) {
|
||||||
type === 'mse'
|
return this.CODECS.filter(codec => isSupported(`video/mp4; codecs="${codec}"`)).join();
|
||||||
? (codec) => MediaSource.isTypeSupported(`video/mp4; codecs="${codec}"`)
|
|
||||||
: (codec) => this.video.canPlayType(`video/mp4; codecs="${codec}"`);
|
|
||||||
return this.CODECS.filter(test).join();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -311,7 +308,7 @@ class VideoRTC extends HTMLElement {
|
|||||||
|
|
||||||
const modes = [];
|
const modes = [];
|
||||||
|
|
||||||
if (this.mode.indexOf('mse') >= 0 && 'MediaSource' in window) {
|
if (this.mode.indexOf('mse') >= 0 && ('MediaSource' in window || 'ManagedMediaSource' in window)) {
|
||||||
// iPhone
|
// iPhone
|
||||||
modes.push('mse');
|
modes.push('mse');
|
||||||
this.onmse();
|
this.onmse();
|
||||||
@ -363,18 +360,29 @@ class VideoRTC extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onmse() {
|
onmse() {
|
||||||
const ms = new MediaSource();
|
/** @type {MediaSource} */
|
||||||
ms.addEventListener(
|
let ms;
|
||||||
'sourceopen',
|
|
||||||
() => {
|
|
||||||
URL.revokeObjectURL(this.video.src);
|
|
||||||
this.send({ type: 'mse', value: this.codecs('mse') });
|
|
||||||
},
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
this.video.src = URL.createObjectURL(ms);
|
if ('ManagedMediaSource' in window) {
|
||||||
this.video.srcObject = null;
|
const MediaSource = window.ManagedMediaSource;
|
||||||
|
|
||||||
|
ms = new MediaSource();
|
||||||
|
ms.addEventListener('sourceopen', () => {
|
||||||
|
this.send({type: 'mse', value: this.codecs(MediaSource.isTypeSupported)});
|
||||||
|
}, {once: true});
|
||||||
|
|
||||||
|
this.video.disableRemotePlayback = true;
|
||||||
|
this.video.srcObject = ms;
|
||||||
|
} else {
|
||||||
|
ms = new MediaSource();
|
||||||
|
ms.addEventListener('sourceopen', () => {
|
||||||
|
URL.revokeObjectURL(this.video.src);
|
||||||
|
this.send({type: 'mse', value: this.codecs(MediaSource.isTypeSupported)});
|
||||||
|
}, {once: true});
|
||||||
|
|
||||||
|
this.video.src = URL.createObjectURL(ms);
|
||||||
|
this.video.srcObject = null;
|
||||||
|
}
|
||||||
this.play();
|
this.play();
|
||||||
|
|
||||||
this.mseCodecs = '';
|
this.mseCodecs = '';
|
||||||
@ -580,7 +588,7 @@ class VideoRTC extends HTMLElement {
|
|||||||
video2.src = `data:video/mp4;base64,${VideoRTC.btoa(data)}`;
|
video2.src = `data:video/mp4;base64,${VideoRTC.btoa(data)}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.send({ type: 'mp4', value: this.codecs('mp4') });
|
this.send({ type: 'mp4', value: this.codecs(this.video.canPlayType) });
|
||||||
}
|
}
|
||||||
|
|
||||||
static btoa(buffer) {
|
static btoa(buffer) {
|
||||||
|
@ -35,7 +35,7 @@ export default function Birdseye() {
|
|||||||
let player;
|
let player;
|
||||||
const playerClass = ptzCameras.length || isMaxWidth ? 'w-full' : 'max-w-5xl xl:w-1/2';
|
const playerClass = ptzCameras.length || isMaxWidth ? 'w-full' : 'max-w-5xl xl:w-1/2';
|
||||||
if (viewSource == 'mse' && config.birdseye.restream) {
|
if (viewSource == 'mse' && config.birdseye.restream) {
|
||||||
if ('MediaSource' in window) {
|
if ('MediaSource' in window || 'ManagedMediaSource' in window) {
|
||||||
player = (
|
player = (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className={playerClass}>
|
<div className={playerClass}>
|
||||||
@ -50,7 +50,7 @@ export default function Birdseye() {
|
|||||||
player = (
|
player = (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className="w-5xl text-center text-sm">
|
<div className="w-5xl text-center text-sm">
|
||||||
MSE is not supported on iOS devices. You'll need to use jsmpeg or webRTC. See the docs for more info.
|
MSE is only supported on iOS 17.1+. You'll need to update if available or use jsmpeg / webRTC streams. See the docs for more info.
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
@ -116,7 +116,7 @@ export default function Camera({ camera }) {
|
|||||||
let player;
|
let player;
|
||||||
if (viewMode === 'live') {
|
if (viewMode === 'live') {
|
||||||
if (viewSource == 'mse' && restreamEnabled) {
|
if (viewSource == 'mse' && restreamEnabled) {
|
||||||
if ('MediaSource' in window) {
|
if ('MediaSource' in window || 'ManagedMediaSource' in window) {
|
||||||
player = (
|
player = (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className="max-w-5xl">
|
<div className="max-w-5xl">
|
||||||
@ -133,7 +133,7 @@ export default function Camera({ camera }) {
|
|||||||
player = (
|
player = (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className="w-5xl text-center text-sm">
|
<div className="w-5xl text-center text-sm">
|
||||||
MSE is not supported on iOS devices. You'll need to use jsmpeg or webRTC. See the docs for more info.
|
MSE is only supported on iOS 17.1+. You'll need to update if available or use jsmpeg / webRTC streams. See the docs for more info.
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user