homekit: switch to opus by default!

This commit is contained in:
Koushik Dutta
2022-02-18 21:46:46 -08:00
parent 09490a709e
commit ef3088489b
4 changed files with 22 additions and 14 deletions

View File

@@ -1,6 +1,6 @@
import { Camera, MotionSensor, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, VideoCamera, AudioSensor, Intercom, ObjectsDetected, VideoCameraConfiguration, OnOff } from '@scrypted/sdk'
import { addSupportedType, bindCharacteristic, DummyDevice, HomeKitSession } from '../common'
import { CameraRecordingDelegate, AudioRecordingCodec, AudioRecordingCodecType, AudioRecordingSamplerate, CameraRecordingOptions, RecordingManagement, OccupancySensor, CharacteristicEventTypes, DataStreamConnection, Service, WithUUID , AudioStreamingCodec, AudioStreamingCodecType, AudioStreamingSamplerate, CameraController, CameraStreamingOptions, Characteristic, VideoCodecType, H264Level, H264Profile, SRTPCryptoSuites } from '../hap';
import { CameraRecordingDelegate, AudioRecordingCodec, AudioRecordingCodecType, AudioRecordingSamplerate, CameraRecordingOptions, RecordingManagement, OccupancySensor, CharacteristicEventTypes, DataStreamConnection, Service, WithUUID, AudioStreamingCodec, AudioStreamingCodecType, AudioStreamingSamplerate, CameraController, CameraStreamingOptions, Characteristic, VideoCodecType, H264Level, H264Profile, SRTPCryptoSuites } from '../hap';
import { makeAccessory } from './common';
import sdk from '@scrypted/sdk';
@@ -27,13 +27,14 @@ addSupportedType({
// webrtc cameras (like ring and nest) must provide opus.
// use this hint to force opus usage. even if opus is not returned,
// for whatever reason, it will be transcoded to opus and that path will be used.
const forceOpus = device.interfaces.includes(ScryptedInterface.RTCSignalingChannel);
const forceOpus = true;
const codecs: AudioStreamingCodec[] = [];
// homekit seems to prefer AAC_ELD if it is offered.
// so forcing opus must be done by not offering AAC_ELD.
for (const type of [
AudioStreamingCodecType.OPUS,
...(forceOpus ? [] : [AudioStreamingCodecType.AAC_ELD])
// AudioStreamingCodecType.AAC_ELD,
]) {
for (const samplerate of [AudioStreamingSamplerate.KHZ_8, AudioStreamingSamplerate.KHZ_16, AudioStreamingSamplerate.KHZ_24]) {
codecs.push({
@@ -102,7 +103,12 @@ addSupportedType({
samplerate.push(sr);
}
for (const type of [AudioRecordingCodecType.AAC_LC]) {
// homekit seems to prefer AAC_ELD if it is offered.
// so forcing AAC_LC must be done by not offering AAC_ELD.
for (const type of [
AudioRecordingCodecType.AAC_LC,
// AudioRecordingCodecType.AAC_ELD,
]) {
const entry: AudioRecordingCodec = {
type,
bitrateMode: 0,
@@ -118,7 +124,7 @@ addSupportedType({
const h265Support = storage.getItem('h265Support') === 'true';
const codecType = h265Support ? VideoCodecType.H265 : VideoCodecType.H264
recordingOptions = {
motionService: true,
prebufferLength: numberPrebufferSegments * iframeIntervalSeconds * 1000,

View File

@@ -91,10 +91,9 @@ export async function* handleFragmentsRequests(device: ScryptedDevice & VideoCam
if (!(noAudio || transcodeRecording))
console.warn('Recording audio is not explicitly AAC, forcing transcoding. Setting audio output to AAC is recommended.', audioCodec);
audioArgs = [
'-acodec', 'libfdk_aac',
...(configuration.audioCodec.type === AudioRecordingCodecType.AAC_LC ?
['-profile:a', 'aac_low'] :
['-profile:a', 'aac_eld']),
['-acodec', 'aac', '-profile:a', 'aac_low'] :
['-acodec', 'libfdk_aac', '-profile:a', 'aac_eld']),
'-ar', `${AudioRecordingSamplerateValues[configuration.audioCodec.samplerate]}k`,
'-b:a', `${configuration.audioCodec.bitrate}k`,
'-ac', `${configuration.audioCodec.audioChannels}`

View File

@@ -114,18 +114,18 @@ export async function startCameraStreamFfmpeg(device: ScryptedDevice & VideoCame
"-vn", '-sn', '-dn',
);
// homekit live streaming seems extremely picky about aac output.
// be extremely sure that this is compatible.
// homekit live streaming seems extremely picky about audio formats.
// sending the incorrect packet time or bitrate, etc, can cause streaming
// to fail altogether. these parameters can also change between LAN and LTE.
const perfectAac = audioCodec === AudioStreamingCodecType.AAC_ELD
&& mso?.audio?.codec === 'aac'
&& mso?.audio?.encoder === 'libfdk_aac';
&& mso?.audio?.encoder === 'scrypted';
const requestedOpus = audioCodec === AudioStreamingCodecType.OPUS;
// homekit opus does not need to be perfect, i don't think. need to test.
const perfectOpus = requestedOpus
&& mso?.audio?.codec === 'opus'
&& mso?.audio?.encoder === 'opusenc';
&& mso?.audio?.encoder === 'scrypted';
let hasAudio = true;
if (!transcodeStreaming

View File

@@ -164,7 +164,6 @@ export function createCameraStreamingDelegate(device: ScryptedDevice & VideoCame
const msos = await device.getVideoStreamOptions();
selectedStream = msos.find(mso => mso.name === streamingChannel);
}
console.log('isHomeKitHub', session.isHomeKitHub, 'selected stream', selectedStream?.name || 'Default/undefined');
const tryReconfigureBitrate = () => {
if (!session.isHomeKitHub)
@@ -198,6 +197,10 @@ export function createCameraStreamingDelegate(device: ScryptedDevice & VideoCame
}
tryReconfigureBitrate();
console.log('isHomeKitHub:', session.isHomeKitHub,
'selected stream:', selectedStream?.name || 'Default/undefined',
'audio.packet_time:', session.startRequest.audio.packet_time);
try {
if (CAMERA_STREAM_FORCE_OPUS) {
await startCameraStreamSrtp(device, console, selectedStream, session, () => killSession(request.sessionID));