webrtc: add flag that forces opus audio

This commit is contained in:
Koushik Dutta
2024-10-10 10:27:07 -07:00
parent cb955f403d
commit 005efbfe82
6 changed files with 46 additions and 24 deletions

View File

@@ -1,4 +1,4 @@
{
"scrypted.debugHost": "127.0.0.1",
"scrypted.debugHost": "scrypted-nvr",
}

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/webrtc",
"version": "0.2.52",
"version": "0.2.53",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@scrypted/webrtc",
"version": "0.2.52",
"version": "0.2.53",
"dependencies": {
"@scrypted/common": "file:../../common",
"@scrypted/sdk": "file:../../sdk",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/webrtc",
"version": "0.2.52",
"version": "0.2.53",
"scripts": {
"scrypted-setup-project": "scrypted-setup-project",
"prescrypted-setup-project": "scrypted-package-json",

View File

@@ -3,7 +3,7 @@ import { MediaStreamTrack, PeerConfig, RTCPeerConnection, RTCRtpCodecParameters,
import { Deferred } from "@scrypted/common/src/deferred";
import sdk, { FFmpegInput, FFmpegTranscodeStream, Intercom, MediaObject, MediaStreamDestination, MediaStreamFeedback, RequestMediaStream, RTCAVSignalingSetup, RTCConnectionManagement, RTCInputMediaObjectTrack, RTCOutputMediaObjectTrack, RTCSignalingOptions, RTCSignalingSession, ScryptedDevice, ScryptedMimeTypes } from "@scrypted/sdk";
import { ScryptedSessionControl } from "./session-control";
import { requiredAudioCodecs, requiredVideoCodec } from "./webrtc-required-codecs";
import { opusAudioCodecOnly, requiredAudioCodecs, requiredVideoCodec } from "./webrtc-required-codecs";
import { logIsLocalIceTransport } from "./werift-util";
import { addVideoFilterArguments } from "@scrypted/common/src/ffmpeg-helpers";
@@ -481,6 +481,7 @@ export class WebRTCConnectionManagement implements RTCConnectionManagement {
closed = false;
constructor(public console: Console, public clientSession: RTCSignalingSession,
public requireOpus: boolean,
public maximumCompatibilityMode: boolean,
public clientOptions: RTCSignalingOptions,
public options: {
@@ -494,7 +495,7 @@ export class WebRTCConnectionManagement implements RTCConnectionManagement {
// the cameras and alexa targets will also provide externally reachable addresses.
codecs: {
audio: [
...requiredAudioCodecs,
...(requireOpus ? opusAudioCodecOnly : requiredAudioCodecs),
],
video: [
requiredVideoCodec,
@@ -660,6 +661,7 @@ export async function createRTCPeerConnectionSink(
console: Console,
intercom: ScryptedDevice & Intercom,
mo: MediaObject,
requireOpus: boolean,
maximumCompatibilityMode: boolean,
configuration: RTCConfiguration,
weriftConfiguration: Partial<PeerConfig>,
@@ -668,7 +670,7 @@ export async function createRTCPeerConnectionSink(
const clientOptions = await legacyGetSignalingSessionOptions(clientSignalingSession);
// console.log('remote options', clientOptions);
const connection = new WebRTCConnectionManagement(console, clientSignalingSession, maximumCompatibilityMode, clientOptions, {
const connection = new WebRTCConnectionManagement(console, clientSignalingSession, requireOpus, maximumCompatibilityMode, clientOptions, {
configuration,
weriftConfiguration,
});

View File

@@ -54,6 +54,7 @@ class WebRTCMixin extends SettingsMixinDeviceBase<RTCSignalingClient & VideoCame
this.console,
undefined,
media,
this.plugin.storageSettings.values.requireOpus,
this.plugin.storageSettings.values.maximumCompatibilityMode,
this.plugin.getRTCConfiguration(),
await this.plugin.getWeriftConfiguration(),
@@ -127,6 +128,7 @@ class WebRTCMixin extends SettingsMixinDeviceBase<RTCSignalingClient & VideoCame
this.console,
hasIntercom ? device : undefined,
mo,
this.plugin.storageSettings.values.requireOpus,
this.plugin.storageSettings.values.maximumCompatibilityMode,
this.plugin.getRTCConfiguration(),
await this.plugin.getWeriftConfiguration(options?.disableTurn),
@@ -202,10 +204,15 @@ export class WebRTCPlugin extends AutoenableMixinProvider implements DeviceCreat
],
defaultValue: 'Default',
},
requireOpus: {
group: 'Advanced',
title: 'Require Opus Audio Codec',
type: 'boolean',
},
maximumCompatibilityMode: {
group: 'Advanced',
title: 'Maximum Compatibility Mode',
description: 'Enables maximum compatibility with WebRTC clients by using the most conservative transcode options.',
description: 'Debug: Enables maximum compatibility with WebRTC clients by transcoding to known safe reference codecs. This setting will automatically reset when the plugin or Scrypted restarts.',
defaultValue: false,
type: 'boolean',
},
@@ -226,20 +233,6 @@ export class WebRTCPlugin extends AutoenableMixinProvider implements DeviceCreat
}
},
},
rtcConfiguration: {
title: "Custom Client RTC Configuration",
type: 'textarea',
description: "RTCConfiguration that can be used to specify custom TURN and STUN servers. https://gist.github.com/koush/f7dafec7dbca04982a76db8243abc57e",
},
weriftConfiguration: {
title: "Custom Server RTC Configuration",
type: 'textarea',
description: "RTCConfiguration that can be used to specify custom TURN and STUN servers. https://gist.github.com/koush/631d38ac8647a86baaac7b22d863f010",
},
debugLog: {
title: 'Debug Log',
type: 'boolean',
},
ipv4Ban: {
group: 'Advanced',
title: '6to4 Ban',
@@ -252,7 +245,24 @@ export class WebRTCPlugin extends AutoenableMixinProvider implements DeviceCreat
],
combobox: true,
multiple: true,
}
},
debugLog: {
group: 'Advanced',
title: 'Debug Log',
type: 'boolean',
},
rtcConfiguration: {
group: 'Advanced',
title: "Custom Client RTC Configuration",
type: 'textarea',
description: "RTCConfiguration that can be used to specify custom TURN and STUN servers. https://gist.github.com/koush/f7dafec7dbca04982a76db8243abc57e",
},
weriftConfiguration: {
group: 'Advanced',
title: "Custom Server RTC Configuration",
type: 'textarea',
description: "RTCConfiguration that can be used to specify custom TURN and STUN servers. https://gist.github.com/koush/631d38ac8647a86baaac7b22d863f010",
},
});
activeConnections = 0;
@@ -291,6 +301,7 @@ export class WebRTCPlugin extends AutoenableMixinProvider implements DeviceCreat
return createRTCPeerConnectionSink(session, console,
undefined,
mo,
plugin.storageSettings.values.requireOpus,
plugin.storageSettings.values.maximumCompatibilityMode,
plugin.getRTCConfiguration(),
await plugin.getWeriftConfiguration(),
@@ -308,6 +319,7 @@ export class WebRTCPlugin extends AutoenableMixinProvider implements DeviceCreat
return createRTCPeerConnectionSink(session, console,
undefined,
mo,
plugin.storageSettings.values.requireOpus,
plugin.storageSettings.values.maximumCompatibilityMode,
plugin.getRTCConfiguration(),
await plugin.getWeriftConfiguration(),
@@ -653,7 +665,7 @@ export async function fork() {
const cleanup = new Deferred<string>();
cleanup.promise.catch(e => this.console.log('cleaning up rtc connection:', e.message));
const connection = new WebRTCConnectionManagement(console, clientSession, maximumCompatibilityMode, clientOptions, options);
const connection = new WebRTCConnectionManagement(console, clientSession, this.storageSettings.values.requireOpus, maximumCompatibilityMode, clientOptions, options);
cleanup.promise.finally(() => connection.close().catch(() => { }));
const { pc } = connection;
waitClosed(pc).then(() => cleanup.resolve('peer connection closed'));

View File

@@ -41,6 +41,14 @@ export const requiredAudioCodecs = [
}),
];
export const opusAudioCodecOnly = [
new RTCRtpCodecParameters({
mimeType: "audio/opus",
clockRate: 48000,
channels: 2,
payloadType: 111,
}),
];
export function getAudioCodec(outputCodecParameters: RTCRtpCodecParameters) {
if (outputCodecParameters.name === 'PCMA') {