diff --git a/plugins/homekit/src/types/camera.ts b/plugins/homekit/src/types/camera.ts index 8cccbb1c1..0f2576438 100644 --- a/plugins/homekit/src/types/camera.ts +++ b/plugins/homekit/src/types/camera.ts @@ -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, diff --git a/plugins/homekit/src/types/camera/camera-recording.ts b/plugins/homekit/src/types/camera/camera-recording.ts index b8094de9a..09b69eb74 100644 --- a/plugins/homekit/src/types/camera/camera-recording.ts +++ b/plugins/homekit/src/types/camera/camera-recording.ts @@ -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}` diff --git a/plugins/homekit/src/types/camera/camera-streaming-ffmpeg.ts b/plugins/homekit/src/types/camera/camera-streaming-ffmpeg.ts index c28b3f1ae..c2db02116 100644 --- a/plugins/homekit/src/types/camera/camera-streaming-ffmpeg.ts +++ b/plugins/homekit/src/types/camera/camera-streaming-ffmpeg.ts @@ -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 diff --git a/plugins/homekit/src/types/camera/camera-streaming.ts b/plugins/homekit/src/types/camera/camera-streaming.ts index 4cbe00a87..d3fe3aa10 100644 --- a/plugins/homekit/src/types/camera/camera-streaming.ts +++ b/plugins/homekit/src/types/camera/camera-streaming.ts @@ -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));