Skip to content

Commit a672e76

Browse files
committed
Still working on HKSV compatibility
1 parent 61ff3bc commit a672e76

File tree

1 file changed

+53
-13
lines changed

1 file changed

+53
-13
lines changed

src/recordingDelegate.ts

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,39 @@ export class RecordingDelegate implements CameraRecordingDelegate {
165165
closeRecordingStream(streamId: number, reason: HDSProtocolSpecificErrorReason | undefined): void {
166166
this.log.info(`Recording stream closed for stream ID: ${streamId}, reason: ${reason}`, this.cameraName)
167167

168+
// Enhanced reason code diagnostics for HKSV debugging
169+
switch (reason) {
170+
case 0:
171+
this.log.info(`✅ HKSV: Recording ended normally (reason 0)`, this.cameraName)
172+
break
173+
case 1:
174+
this.log.warn(`⚠️ HKSV: Recording ended due to generic error (reason 1)`, this.cameraName)
175+
break
176+
case 2:
177+
this.log.warn(`⚠️ HKSV: Recording ended due to network issues (reason 2)`, this.cameraName)
178+
break
179+
case 3:
180+
this.log.warn(`⚠️ HKSV: Recording ended due to insufficient resources (reason 3)`, this.cameraName)
181+
break
182+
case 4:
183+
this.log.warn(`⚠️ HKSV: Recording ended due to HomeKit busy (reason 4)`, this.cameraName)
184+
break
185+
case 5:
186+
this.log.warn(`⚠️ HKSV: Recording ended due to insufficient buffer space (reason 5)`, this.cameraName)
187+
break
188+
case 6:
189+
this.log.warn(`❌ HKSV: Recording ended due to STREAM FORMAT INCOMPATIBILITY (reason 6) - Check H.264 parameters!`, this.cameraName)
190+
break
191+
case 7:
192+
this.log.warn(`⚠️ HKSV: Recording ended due to maximum recording time exceeded (reason 7)`, this.cameraName)
193+
break
194+
case 8:
195+
this.log.warn(`⚠️ HKSV: Recording ended due to HomeKit storage full (reason 8)`, this.cameraName)
196+
break
197+
default:
198+
this.log.warn(`❓ HKSV: Unknown reason ${reason}`, this.cameraName)
199+
}
200+
168201
// Abort the stream generator
169202
const abortController = this.streamAbortControllers.get(streamId)
170203
if (abortController) {
@@ -262,7 +295,7 @@ export class RecordingDelegate implements CameraRecordingDelegate {
262295
'1',
263296
]
264297

265-
// Universal encoding for HKSV compatibility - works with any input source
298+
// Enhanced H.264 encoding for maximum HKSV compatibility
266299
const videoArgs: Array<string> = [
267300
// Only disable audio if explicitly disabled in config
268301
...(this.videoConfig?.audio === false ? ['-an'] : []),
@@ -277,23 +310,29 @@ export class RecordingDelegate implements CameraRecordingDelegate {
277310
'-level:v',
278311
'3.1', // Force level 3.1 for HKSV compatibility
279312
'-preset',
280-
'ultrafast',
313+
'fast', // Changed from ultrafast for better quality/compatibility balance
281314
'-tune',
282315
'zerolatency',
316+
'-x264opts',
317+
'no-scenecut', // Disable scene cut detection for consistent GOP
283318
'-g',
284-
'60',
319+
'30', // Shorter GOP for better HKSV compatibility (was 60)
285320
'-keyint_min',
286-
'60',
321+
'30', // Match GOP size
287322
'-sc_threshold',
288-
'0',
323+
'0', // Disable scene change detection
289324
'-force_key_frames',
290-
'expr:gte(t,n_forced*4)',
325+
'expr:gte(t,n_forced*2)', // Every 2 seconds instead of 4
326+
'-refs',
327+
'1', // Use single reference frame for baseline
291328
'-b:v',
292-
'800k',
329+
'600k', // Lower bitrate for better reliability (was 800k)
293330
'-maxrate',
294-
'1000k',
331+
'800k', // Lower max rate (was 1000k)
295332
'-bufsize',
296-
'1000k',
333+
'600k', // Match bitrate for consistent rate control
334+
'-r',
335+
'15', // Fixed 15fps for more stable recording
297336
]
298337

299338
const ffmpegInput: Array<string> = []
@@ -337,6 +376,9 @@ export class RecordingDelegate implements CameraRecordingDelegate {
337376
const { header, type, length, data } = box
338377

339378
pending.push(header, data)
379+
380+
// Enhanced MP4 box logging for HKSV debugging
381+
this.log.debug(`📦 HKSV DEBUG: Received MP4 box type '${type}', length: ${length}`, this.cameraName)
340382

341383
// HKSV requires specific MP4 structure:
342384
// 1. First packet: ftyp + moov (initialization data)
@@ -348,7 +390,7 @@ export class RecordingDelegate implements CameraRecordingDelegate {
348390
filebuffer = Buffer.concat([filebuffer, fragment])
349391
pending = []
350392
isFirstFragment = false
351-
this.log.debug(`HKSV: Sending initialization segment (ftyp+moov), size: ${fragment.length}`, this.cameraName)
393+
this.log.info(`🚀 HKSV: Sending initialization segment (ftyp+moov), size: ${fragment.length}`, this.cameraName)
352394
yield fragment
353395
}
354396
} else {
@@ -357,12 +399,10 @@ export class RecordingDelegate implements CameraRecordingDelegate {
357399
const fragment = Buffer.concat(pending)
358400
filebuffer = Buffer.concat([filebuffer, fragment])
359401
pending = []
360-
this.log.debug(`HKSV: Sending media fragment (moof+mdat), size: ${fragment.length}`, this.cameraName)
402+
this.log.info(`📹 HKSV: Sending media fragment (moof+mdat), size: ${fragment.length}`, this.cameraName)
361403
yield fragment
362404
}
363405
}
364-
365-
this.log.debug(`mp4 box type ${type} and length: ${length}`, this.cameraName)
366406
}
367407
} catch (e) {
368408
this.log.info(`Recording completed. ${e}`, this.cameraName)

0 commit comments

Comments
 (0)