homebridge-eufy-security 4.4.2-beta.2 → 4.4.2-beta.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/FUNDING.yml +1 -0
  3. package/README.md +14 -17
  4. package/dist/accessories/AutoSyncStationAccessory.js +26 -30
  5. package/dist/accessories/AutoSyncStationAccessory.js.map +1 -1
  6. package/dist/accessories/BaseAccessory.js +33 -46
  7. package/dist/accessories/BaseAccessory.js.map +1 -1
  8. package/dist/accessories/CameraAccessory.js +92 -167
  9. package/dist/accessories/CameraAccessory.js.map +1 -1
  10. package/dist/accessories/Device.js +11 -15
  11. package/dist/accessories/Device.js.map +1 -1
  12. package/dist/accessories/EntrySensorAccessory.js +7 -12
  13. package/dist/accessories/EntrySensorAccessory.js.map +1 -1
  14. package/dist/accessories/LockAccessory.js +20 -24
  15. package/dist/accessories/LockAccessory.js.map +1 -1
  16. package/dist/accessories/MotionSensorAccessory.js +7 -12
  17. package/dist/accessories/MotionSensorAccessory.js.map +1 -1
  18. package/dist/accessories/StationAccessory.js +40 -45
  19. package/dist/accessories/StationAccessory.js.map +1 -1
  20. package/dist/config.js +1 -4
  21. package/dist/config.js.map +1 -1
  22. package/dist/controller/LocalLivestreamManager.js +85 -89
  23. package/dist/controller/LocalLivestreamManager.js.map +1 -1
  24. package/dist/controller/recordingDelegate.js +116 -108
  25. package/dist/controller/recordingDelegate.js.map +1 -1
  26. package/dist/controller/snapshotDelegate.js +379 -0
  27. package/dist/controller/snapshotDelegate.js.map +1 -0
  28. package/dist/controller/streamingDelegate.js +202 -207
  29. package/dist/controller/streamingDelegate.js.map +1 -1
  30. package/dist/index.js +9 -7
  31. package/dist/index.js.map +1 -1
  32. package/dist/interfaces.js +1 -2
  33. package/dist/interfaces.js.map +1 -1
  34. package/dist/platform.js +145 -165
  35. package/dist/platform.js.map +1 -1
  36. package/dist/settings.js +26 -19
  37. package/dist/settings.js.map +1 -1
  38. package/dist/utils/Talkback.js +9 -13
  39. package/dist/utils/Talkback.js.map +1 -1
  40. package/dist/utils/configTypes.js +12 -7
  41. package/dist/utils/configTypes.js.map +1 -1
  42. package/dist/utils/ffmpeg.js +44 -52
  43. package/dist/utils/ffmpeg.js.map +1 -1
  44. package/dist/utils/interfaces.js +1 -5
  45. package/dist/utils/interfaces.js.map +1 -1
  46. package/dist/utils/utils.js +32 -134
  47. package/dist/utils/utils.js.map +1 -1
  48. package/dist/version.js +1 -4
  49. package/dist/version.js.map +1 -1
  50. package/eslint.config.mjs +25 -47
  51. package/homebridge-eufy-security.png +0 -0
  52. package/homebridge-ui/public/app.js +221 -0
  53. package/homebridge-ui/public/assets/devices/eufycam3pro_large.png +0 -0
  54. package/homebridge-ui/public/assets/devices/homebase3_large.png +0 -0
  55. package/homebridge-ui/public/assets/devices/homebasemini_large.jpg +0 -0
  56. package/homebridge-ui/public/assets/devices/indoorcamC210_large.png +0 -0
  57. package/homebridge-ui/public/assets/devices/indoorcamC220_large.png +0 -0
  58. package/homebridge-ui/public/assets/devices/indoorcamE30_large.png +0 -0
  59. package/homebridge-ui/public/assets/devices/solocamc35_large.png +0 -0
  60. package/homebridge-ui/public/assets/devices/solocame30_large.png +0 -0
  61. package/homebridge-ui/public/components/device-card.js +141 -0
  62. package/homebridge-ui/public/components/guard-modes.js +88 -0
  63. package/homebridge-ui/public/components/number-input.js +121 -0
  64. package/homebridge-ui/public/components/select.js +73 -0
  65. package/homebridge-ui/public/components/toggle.js +68 -0
  66. package/homebridge-ui/public/index.html +24 -14
  67. package/homebridge-ui/public/services/api.js +129 -0
  68. package/homebridge-ui/public/services/config.js +144 -0
  69. package/homebridge-ui/public/style.css +705 -0
  70. package/homebridge-ui/public/utils/countries.js +73 -0
  71. package/homebridge-ui/public/utils/device-images.js +69 -0
  72. package/homebridge-ui/public/utils/helpers.js +47 -0
  73. package/homebridge-ui/public/views/dashboard.js +211 -0
  74. package/homebridge-ui/public/views/device-detail.js +631 -0
  75. package/homebridge-ui/public/views/login.js +625 -0
  76. package/homebridge-ui/public/views/settings.js +389 -0
  77. package/homebridge-ui/public/views/unsupported-detail.js +216 -0
  78. package/homebridge-ui/server.js +567 -450
  79. package/package.json +19 -59
  80. package/dist/accessories/AutoSyncStationAccessory.d.ts +0 -42
  81. package/dist/accessories/AutoSyncStationAccessory.d.ts.map +0 -1
  82. package/dist/accessories/BaseAccessory.d.ts +0 -56
  83. package/dist/accessories/BaseAccessory.d.ts.map +0 -1
  84. package/dist/accessories/CameraAccessory.d.ts +0 -84
  85. package/dist/accessories/CameraAccessory.d.ts.map +0 -1
  86. package/dist/accessories/Device.d.ts +0 -19
  87. package/dist/accessories/Device.d.ts.map +0 -1
  88. package/dist/accessories/EntrySensorAccessory.d.ts +0 -25
  89. package/dist/accessories/EntrySensorAccessory.d.ts.map +0 -1
  90. package/dist/accessories/LockAccessory.d.ts +0 -45
  91. package/dist/accessories/LockAccessory.d.ts.map +0 -1
  92. package/dist/accessories/MotionSensorAccessory.d.ts +0 -25
  93. package/dist/accessories/MotionSensorAccessory.d.ts.map +0 -1
  94. package/dist/accessories/StationAccessory.d.ts +0 -86
  95. package/dist/accessories/StationAccessory.d.ts.map +0 -1
  96. package/dist/config.d.ts +0 -31
  97. package/dist/config.d.ts.map +0 -1
  98. package/dist/controller/LocalLivestreamManager.d.ts +0 -31
  99. package/dist/controller/LocalLivestreamManager.d.ts.map +0 -1
  100. package/dist/controller/SnapshotManager.d.ts +0 -64
  101. package/dist/controller/SnapshotManager.d.ts.map +0 -1
  102. package/dist/controller/SnapshotManager.js +0 -434
  103. package/dist/controller/SnapshotManager.js.map +0 -1
  104. package/dist/controller/recordingDelegate.d.ts +0 -27
  105. package/dist/controller/recordingDelegate.d.ts.map +0 -1
  106. package/dist/controller/streamingDelegate.d.ts +0 -52
  107. package/dist/controller/streamingDelegate.d.ts.map +0 -1
  108. package/dist/index.d.ts +0 -7
  109. package/dist/index.d.ts.map +0 -1
  110. package/dist/interfaces.d.ts +0 -15
  111. package/dist/interfaces.d.ts.map +0 -1
  112. package/dist/platform.d.ts +0 -94
  113. package/dist/platform.d.ts.map +0 -1
  114. package/dist/settings.d.ts +0 -23
  115. package/dist/settings.d.ts.map +0 -1
  116. package/dist/utils/Talkback.d.ts +0 -21
  117. package/dist/utils/Talkback.d.ts.map +0 -1
  118. package/dist/utils/configTypes.d.ts +0 -68
  119. package/dist/utils/configTypes.d.ts.map +0 -1
  120. package/dist/utils/ffmpeg.d.ts +0 -111
  121. package/dist/utils/ffmpeg.d.ts.map +0 -1
  122. package/dist/utils/interfaces.d.ts +0 -8
  123. package/dist/utils/interfaces.d.ts.map +0 -1
  124. package/dist/utils/utils.d.ts +0 -35
  125. package/dist/utils/utils.d.ts.map +0 -1
  126. package/dist/version.d.ts +0 -2
  127. package/dist/version.d.ts.map +0 -1
  128. package/homebridge-ui/configui/app/util/types.d.ts +0 -65
  129. package/homebridge-ui/configui/app/util/types.d.ts.map +0 -1
  130. package/homebridge-ui/configui/app/util/types.js +0 -18
  131. package/homebridge-ui/configui/app/util/types.js.map +0 -1
  132. package/homebridge-ui/public/3rdpartylicenses.txt +0 -561
  133. package/homebridge-ui/public/assets/devices/homebase2_large.jpg +0 -0
  134. package/homebridge-ui/public/assets/devices/homebase3_large.jpg +0 -0
  135. package/homebridge-ui/public/assets/images/homebridge-eufy-security.png +0 -0
  136. package/homebridge-ui/public/favicon.ico +0 -0
  137. package/homebridge-ui/public/main.f6423287e0411c87.js +0 -1
  138. package/homebridge-ui/public/polyfills.efa2f09ba3e49167.js +0 -1
  139. package/homebridge-ui/public/runtime.ccde331d62c423b3.js +0 -1
  140. package/homebridge-ui/public/styles.13e635bf7a488639.css +0 -5
  141. package/homebridge-ui/server.d.ts +0 -2
  142. package/homebridge-ui/server.d.ts.map +0 -1
  143. package/homebridge-ui/server.js.map +0 -1
  144. package/homebridge-ui/version.d.ts +0 -2
  145. package/homebridge-ui/version.d.ts.map +0 -1
  146. package/homebridge-ui/version.js +0 -5
  147. package/homebridge-ui/version.js.map +0 -1
@@ -1,117 +1,113 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LocalLivestreamManager = void 0;
4
- const stream_1 = require("stream");
5
- // Define a class for the local livestream manager.
6
- class LocalLivestreamManager extends stream_1.EventEmitter {
7
- camera;
8
- CONNECTION_ESTABLISHED_TIMEOUT = 5;
1
+ import { Deferred } from '../utils/utils.js';
2
+ const P2P_TIMEOUT_MS = 15_000;
3
+ const DUPLICATE_STREAM_GUARD_S = 5;
4
+ export class LocalLivestreamManager {
9
5
  stationStream = null;
10
- livestreamStartedAt = null;
11
- livestreamIsStarting = false;
6
+ pending = null;
12
7
  eufyClient;
13
8
  log;
14
- serial_number;
9
+ serialNumber;
15
10
  constructor(camera) {
16
- super();
17
- this.camera = camera;
18
11
  this.eufyClient = camera.platform.eufyClient;
19
- this.serial_number = camera.device.getSerial();
12
+ this.serialNumber = camera.device.getSerial();
20
13
  this.log = camera.log;
21
- this.initialize();
22
- this.eufyClient.on('station livestream start', this.onStationLivestreamStart.bind(this));
23
- this.eufyClient.on('station livestream stop', this.onStationLivestreamStop.bind(this));
14
+ this.log.debug(`LocalLivestreamManager initialized for ${camera.device.getName()} (serial: ${this.serialNumber})`);
15
+ this.eufyClient.on('station livestream start', this.onStationLivestreamStart);
16
+ this.eufyClient.on('station livestream stop', this.onStationLivestreamStop);
24
17
  }
25
- // Initialize the manager.
26
- initialize() {
18
+ /** Destroy active streams and reset state. */
19
+ destroyStreams() {
27
20
  if (this.stationStream) {
28
21
  this.stationStream.audiostream.unpipe();
29
22
  this.stationStream.audiostream.destroy();
30
23
  this.stationStream.videostream.unpipe();
31
24
  this.stationStream.videostream.destroy();
25
+ this.stationStream = null;
32
26
  }
33
- this.stationStream = null;
34
- this.livestreamStartedAt = null;
35
27
  }
36
- // Get the local livestream.
37
- async getLocalLivestream() {
38
- this.log.debug('New instance requests livestream.');
28
+ /** Return the active livestream, or start a new one. Concurrent callers share the same pending request. */
29
+ async getLocalLiveStream() {
39
30
  if (this.stationStream) {
40
- const runtime = (Date.now() - this.livestreamStartedAt) / 1000;
41
- this.log.debug('Using livestream that was started ' + runtime + ' seconds ago.');
31
+ const runtime = ((Date.now() - this.stationStream.createdAt) / 1000).toFixed(1);
32
+ this.log.debug(`Reusing livestream started ${runtime}s ago.`);
42
33
  return this.stationStream;
43
34
  }
44
- else {
45
- return await this.startAndGetLocalLiveStream();
35
+ return this.startLocalLiveStream();
36
+ }
37
+ /**
38
+ * Requests a P2P livestream from the eufy station and waits for the
39
+ * 'station livestream start' event. If a start is already in progress,
40
+ * the caller piggy-backs on the existing promise instead of issuing a
41
+ * duplicate request.
42
+ */
43
+ startLocalLiveStream() {
44
+ if (this.pending) {
45
+ this.log.debug('Livestream already starting — waiting on existing request.');
46
+ return this.pending.deferred.promise;
47
+ }
48
+ this.log.debug(`Starting station livestream for serial: ${this.serialNumber}...`);
49
+ const deferred = new Deferred();
50
+ const timer = setTimeout(() => {
51
+ this.log.error(`Livestream timeout: no P2P stream event received within ${P2P_TIMEOUT_MS / 1000}s for serial ${this.serialNumber}.`);
52
+ this.log.warn('If using a recent Node.js version, try enabling "Embedded PKCS1 Support" in the plugin settings.');
53
+ this.settlePending('reject', 'Livestream timeout — try enabling Embedded PKCS1 Support in settings.');
54
+ }, P2P_TIMEOUT_MS);
55
+ this.pending = { deferred, timer };
56
+ try {
57
+ this.eufyClient.startStationLivestream(this.serialNumber);
46
58
  }
59
+ catch (err) {
60
+ this.log.error(`startStationLivestream threw: ${err}`);
61
+ this.settlePending('reject', err);
62
+ }
63
+ return deferred.promise;
47
64
  }
48
- // Start and get the local livestream.
49
- async startAndGetLocalLiveStream() {
50
- return new Promise((resolve, reject) => {
51
- this.log.debug('Start new station livestream...');
52
- if (!this.livestreamIsStarting) { // prevent multiple stream starts from eufy station
53
- this.livestreamIsStarting = true;
54
- this.eufyClient.startStationLivestream(this.serial_number);
55
- }
56
- else {
57
- this.log.debug('stream is already starting. waiting...');
58
- }
59
- // Hard stop
60
- const hardStop = setTimeout(() => {
61
- this.log.error('Livestream timeout: No livestream emitted within the expected timeframe.');
62
- const problematicNodeVersions = ['18.19.1', '20.11.1', '21.6.2'];
63
- this.log.warn(`If you are using Node.js version ${problematicNodeVersions.join(', ')} or newer, this might be related to RSA_PKCS1_PADDING support removal.`);
64
- this.log.warn('Please try enabling "Embedded PKCS1 Support" in the plugin settings to resolve this issue.');
65
- this.stopLocalLiveStream();
66
- this.livestreamIsStarting = false;
67
- reject('No livestream emitted... This may be due to Node.js compatibility issues. Try enabling Embedded PKCS1 Support in settings.');
68
- }, 15 * 1000 // After 15 seconds, Apple HomeKit may disconnect, invalidating the livestream setup.
69
- );
70
- this.once('livestream start', async () => {
71
- if (this.stationStream !== null) {
72
- this.log.debug('New livestream started.');
73
- clearTimeout(hardStop);
74
- this.livestreamIsStarting = false;
75
- resolve(this.stationStream);
76
- }
77
- else {
78
- reject('no started livestream found');
79
- }
80
- });
81
- });
65
+ settlePending(action, payload) {
66
+ const p = this.pending;
67
+ if (!p)
68
+ return;
69
+ clearTimeout(p.timer);
70
+ this.pending = null;
71
+ if (action === 'resolve') {
72
+ p.deferred.resolve(payload);
73
+ }
74
+ else {
75
+ p.deferred.reject(payload instanceof Error ? payload : new Error(String(payload)));
76
+ this.stopLocalLiveStream();
77
+ }
82
78
  }
83
- // Stop the local livestream.
84
79
  stopLocalLiveStream() {
85
80
  this.log.debug('Stopping station livestream.');
86
- this.eufyClient.stopStationLivestream(this.serial_number);
87
- this.initialize();
81
+ this.eufyClient.stopStationLivestream(this.serialNumber);
82
+ this.destroyStreams();
88
83
  }
89
- // Handle the station livestream stop event.
90
- onStationLivestreamStop(station, device) {
91
- if (device.getSerial() === this.serial_number) {
92
- this.log.debug(`${station.getName()} station livestream for ${device.getName()} has stopped.`);
93
- this.initialize();
94
- }
84
+ /** True when the event belongs to this camera instance. */
85
+ isOwnDevice(device) {
86
+ return device.getSerial() === this.serialNumber;
95
87
  }
96
- // Handle the station livestream start event.
97
- async onStationLivestreamStart(station, device, metadata, videostream, audiostream) {
98
- if (device.getSerial() === this.serial_number) {
99
- if (this.stationStream) {
100
- const diff = (Date.now() - this.stationStream.createdAt) / 1000;
101
- if (diff < 5) {
102
- this.log.warn('Second livestream was started from station. Ignore.');
103
- return;
104
- }
88
+ onStationLivestreamStop = (_station, device) => {
89
+ if (!this.isOwnDevice(device))
90
+ return;
91
+ this.log.debug(`Station livestream for ${device.getName()} has stopped.`);
92
+ this.destroyStreams();
93
+ };
94
+ onStationLivestreamStart = (station, device, metadata, videostream, audiostream) => {
95
+ if (!this.isOwnDevice(device))
96
+ return;
97
+ // Guard against duplicate events fired in quick succession.
98
+ if (this.stationStream) {
99
+ const elapsed = (Date.now() - this.stationStream.createdAt) / 1000;
100
+ if (elapsed < DUPLICATE_STREAM_GUARD_S) {
101
+ this.log.warn('Duplicate livestream event received — ignoring.');
102
+ return;
105
103
  }
106
- this.initialize(); // important to prevent unwanted behaviour when the eufy station emits the 'livestream start' event multiple times
107
- this.log.debug(station.getName() + ' station livestream (P2P session) for ' + device.getName() + ' has started.');
108
- this.livestreamStartedAt = Date.now();
109
- const createdAt = Date.now();
110
- this.stationStream = { station, device, metadata, videostream, audiostream, createdAt };
111
- this.log.debug('Stream metadata: ', this.stationStream.metadata);
112
- this.emit('livestream start');
113
104
  }
114
- }
105
+ // Tear down any prior stream before storing the new one.
106
+ this.destroyStreams();
107
+ this.log.debug(`${station.getName()} P2P livestream for ${device.getName()} started.`);
108
+ this.log.debug('Stream metadata:', JSON.stringify(metadata));
109
+ this.stationStream = { videostream, audiostream, createdAt: Date.now() };
110
+ this.settlePending('resolve', this.stationStream);
111
+ };
115
112
  }
116
- exports.LocalLivestreamManager = LocalLivestreamManager;
117
113
  //# sourceMappingURL=LocalLivestreamManager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LocalLivestreamManager.js","sourceRoot":"","sources":["../../src/plugin/controller/LocalLivestreamManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LocalLivestreamManager.js","sourceRoot":"","sources":["../../src/controller/LocalLivestreamManager.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,6 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RecordingDelegate = void 0;
4
- const eufy_security_client_1 = require("eufy-security-client");
5
- const ffmpeg_1 = require("../utils/ffmpeg");
6
- const utils_1 = require("../utils/utils");
1
+ import { PropertyName } from 'eufy-security-client';
2
+ import { FFmpeg, FFmpegParameters } from '../utils/ffmpeg.js';
3
+ import { CHAR, SERV, isRtspReady, log } from '../utils/utils.js';
7
4
  const MAX_RECORDING_MINUTES = 1; // should never be used
8
5
  const HKSVQuitReason = [
9
6
  'Normal',
@@ -17,7 +14,7 @@ const HKSVQuitReason = [
17
14
  'Protocol error',
18
15
  'Invalid Configuration',
19
16
  ];
20
- class RecordingDelegate {
17
+ export class RecordingDelegate {
21
18
  platform;
22
19
  accessory;
23
20
  camera;
@@ -42,149 +39,160 @@ class RecordingDelegate {
42
39
  isRecording() {
43
40
  return this.handlingStreamingRequest;
44
41
  }
42
+ resetMotionSensor() {
43
+ const motionDetected = this.accessory
44
+ .getService(SERV.MotionSensor)?.getCharacteristic(CHAR.MotionDetected).value;
45
+ if (motionDetected) {
46
+ this.accessory
47
+ .getService(SERV.MotionSensor)?.getCharacteristic(CHAR.MotionDetected)
48
+ .updateValue(false);
49
+ }
50
+ }
51
+ clearForceStopTimeout() {
52
+ if (this.forceStopTimeout) {
53
+ clearTimeout(this.forceStopTimeout);
54
+ this.forceStopTimeout = undefined;
55
+ }
56
+ }
57
+ isMotionDetected() {
58
+ return !!this.accessory
59
+ .getService(SERV.MotionSensor)?.getCharacteristic(CHAR.MotionDetected).value;
60
+ }
61
+ async configureInputSource(videoParams, audioParams) {
62
+ if (isRtspReady(this.camera, this.cameraConfig)) {
63
+ const url = this.camera.getPropertyValue(PropertyName.DeviceRTSPStreamUrl);
64
+ log.debug(this.camera.getName(), 'RTSP URL: ' + url);
65
+ videoParams.setInputSource(url);
66
+ audioParams.setInputSource(url);
67
+ }
68
+ else {
69
+ const streamData = await this.localLivestreamManager.getLocalLiveStream();
70
+ await videoParams.setInputStream(streamData.videostream);
71
+ await audioParams.setInputStream(streamData.audiostream);
72
+ }
73
+ }
45
74
  async *handleRecordingStreamRequest() {
46
75
  this.handlingStreamingRequest = true;
47
- utils_1.log.info(this.camera.getName(), 'requesting recording for HomeKit Secure Video.');
48
- let pending = [];
49
- let filebuffer = Buffer.alloc(0);
76
+ this.closeReason = undefined;
77
+ log.info(this.camera.getName(), 'requesting recording for HomeKit Secure Video.');
50
78
  try {
51
- const audioEnabled = this.controller?.recordingManagement?.recordingManagementService.getCharacteristic(utils_1.CHAR.RecordingAudioActive).value;
52
- if (audioEnabled) {
53
- utils_1.log.debug('HKSV and plugin are set to record audio.');
54
- }
55
- else {
56
- utils_1.log.debug('HKSV and plugin are set to omit audio recording.');
79
+ if (!this.configuration) {
80
+ log.error(this.camera.getName(), 'No recording configuration available. Aborting.');
81
+ yield { data: Buffer.alloc(0), isLast: true };
82
+ return;
57
83
  }
58
- const videoParams = await ffmpeg_1.FFmpegParameters.forVideoRecording();
59
- const audioParams = await ffmpeg_1.FFmpegParameters.forAudioRecording();
84
+ const audioEnabled = this.controller?.recordingManagement?.recordingManagementService.getCharacteristic(CHAR.RecordingAudioActive).value;
85
+ log.debug(this.camera.getName(), `HKSV audio recording: ${audioEnabled ? 'enabled' : 'disabled'}.`);
86
+ const videoParams = await FFmpegParameters.forVideoRecording();
87
+ const audioParams = await FFmpegParameters.forAudioRecording();
60
88
  const videoConfig = this.cameraConfig.videoConfig ?? {};
61
- if (this.cameraConfig.videoConfig && this.cameraConfig.videoConfig.videoProcessor) {
62
- videoConfig.videoProcessor = this.cameraConfig.videoConfig.videoProcessor;
63
- }
64
89
  videoParams.setupForRecording(videoConfig, this.configuration);
65
90
  audioParams.setupForRecording(videoConfig, this.configuration);
66
- const rtsp = (0, utils_1.is_rtsp_ready)(this.camera, this.cameraConfig);
67
- if (rtsp) {
68
- const url = this.camera.getPropertyValue(eufy_security_client_1.PropertyName.DeviceRTSPStreamUrl);
69
- utils_1.log.debug(this.camera.getName(), 'RTSP URL: ' + url);
70
- videoParams.setInputSource(url);
71
- audioParams.setInputSource(url);
72
- }
73
- else {
74
- const streamData = await this.localLivestreamManager.getLocalLivestream().catch((error) => {
75
- throw error;
76
- });
77
- await videoParams.setInputStream(streamData.videostream);
78
- await audioParams.setInputStream(streamData.audiostream);
79
- }
80
- const ffmpeg = new ffmpeg_1.FFmpeg(`[${this.camera.getName()}] [HSV Recording Process]`, audioEnabled ? [videoParams, audioParams] : videoParams);
91
+ await this.configureInputSource(videoParams, audioParams);
92
+ const ffmpeg = new FFmpeg(`[${this.camera.getName()}] [HSV Recording Process]`, audioEnabled ? [videoParams, audioParams] : videoParams);
81
93
  this.session = await ffmpeg.startFragmentedMP4Session();
82
- let timer = this.cameraConfig.hsvRecordingDuration ?? MAX_RECORDING_MINUTES * 60;
83
- if (this.platform.config.CameraMaxLivestreamDuration < timer) {
84
- timer = this.platform.config.CameraMaxLivestreamDuration;
85
- }
86
- if (timer > 0) {
94
+ const maxDuration = Math.min(this.cameraConfig.hsvRecordingDuration ?? MAX_RECORDING_MINUTES * 60, this.platform.config.CameraMaxLivestreamDuration);
95
+ if (maxDuration > 0) {
87
96
  this.forceStopTimeout = setTimeout(() => {
88
- utils_1.log.warn(this.camera.getName(), `The recording process has been running for ${timer} seconds and is now being forced closed!`);
89
- this.accessory
90
- .getService(utils_1.SERV.MotionSensor)?.getCharacteristic(utils_1.CHAR.MotionDetected)
91
- .updateValue(false);
92
- }, timer * 1000);
93
- }
94
- for await (const box of this.session.generator) {
95
- if (!this.handlingStreamingRequest) {
96
- utils_1.log.debug(this.camera.getName(), 'Recording was ended prematurely.');
97
- break;
98
- }
99
- const { header, type, data } = box;
100
- pending.push(header, data);
101
- const motionDetected = this.accessory
102
- .getService(utils_1.SERV.MotionSensor)?.getCharacteristic(utils_1.CHAR.MotionDetected).value;
103
- if (type === 'moov' || type === 'mdat') {
104
- const fragment = Buffer.concat(pending);
105
- filebuffer = Buffer.concat([filebuffer, Buffer.concat(pending)]);
106
- pending = [];
107
- yield {
108
- data: fragment,
109
- isLast: !motionDetected,
110
- };
111
- if (!motionDetected) {
112
- utils_1.log.debug(this.camera.getName(), 'Ending recording session due to motion stopped!');
113
- break;
114
- }
115
- }
97
+ log.warn(this.camera.getName(), `Recording force-stopped after ${maxDuration}s.`);
98
+ this.resetMotionSensor();
99
+ }, maxDuration * 1000);
116
100
  }
101
+ yield* this.generateFragments(this.session.generator);
117
102
  }
118
103
  catch (error) {
119
104
  if (!this.handlingStreamingRequest && this.closeReason && this.closeReason === 3 /* HDSProtocolSpecificErrorReason.CANCELLED */) {
120
- utils_1.log.debug(this.camera.getName(), 'Recording encountered an error but that is expected, as the recording was canceled beforehand. Error: ' + error);
105
+ log.debug(this.camera.getName(), 'Recording encountered an error but that is expected, as the recording was canceled beforehand. Error: ' + error);
121
106
  }
122
107
  else {
123
- utils_1.log.error(this.camera.getName(), 'Error while recording: ' + error);
108
+ log.error(this.camera.getName(), 'Error while recording: ' + error);
124
109
  }
125
110
  }
126
111
  finally {
127
- if (this.closeReason &&
128
- this.closeReason !== 0 /* HDSProtocolSpecificErrorReason.NORMAL */ && this.closeReason !== 3 /* HDSProtocolSpecificErrorReason.CANCELLED */) {
129
- utils_1.log.warn(this.camera.getName(), `The recording process was aborted by HSV with reason "${HKSVQuitReason[this.closeReason]}"`);
130
- }
131
- if (this.closeReason && this.closeReason === 3 /* HDSProtocolSpecificErrorReason.CANCELLED */) {
132
- utils_1.log.debug(this.camera.getName(), 'The recording process was canceled by the HomeKit Controller."');
112
+ this.logCloseReason();
113
+ this.clearForceStopTimeout();
114
+ this.resetMotionSensor();
115
+ this.localLivestreamManager.stopLocalLiveStream();
116
+ }
117
+ }
118
+ logCloseReason() {
119
+ if (!this.closeReason) {
120
+ return;
121
+ }
122
+ if (this.closeReason === 3 /* HDSProtocolSpecificErrorReason.CANCELLED */) {
123
+ log.debug(this.camera.getName(), 'The recording process was canceled by the HomeKit Controller.');
124
+ }
125
+ else if (this.closeReason !== 0 /* HDSProtocolSpecificErrorReason.NORMAL */) {
126
+ log.warn(this.camera.getName(), `The recording process was aborted by HSV with reason "${HKSVQuitReason[this.closeReason]}"`);
127
+ }
128
+ }
129
+ /**
130
+ * Assembles fragmented MP4 boxes into HKSV-compatible recording packets.
131
+ * Yields an initialization segment (ftyp+moov), then paired moof+mdat fragments.
132
+ */
133
+ async *generateFragments(generator) {
134
+ const cameraName = this.camera.getName();
135
+ let initPending = [];
136
+ let moofBuffer = null;
137
+ let isInit = true;
138
+ let fragmentCount = 0;
139
+ for await (const { header, type, data } of generator) {
140
+ if (!this.handlingStreamingRequest) {
141
+ log.debug(cameraName, 'Recording was ended prematurely.');
142
+ break;
133
143
  }
134
- if (filebuffer.length > 0) {
135
- utils_1.log.debug(this.camera.getName(), 'Recording completed (HSV). Send ' + filebuffer.length + ' bytes.');
144
+ if (isInit) {
145
+ initPending.push(header, data);
146
+ if (type === 'moov') {
147
+ const fragment = Buffer.concat(initPending);
148
+ initPending = [];
149
+ isInit = false;
150
+ log.debug(cameraName, `HKSV: Sending initialization segment, size: ${fragment.length}`);
151
+ yield { data: fragment, isLast: false };
152
+ }
153
+ continue;
136
154
  }
137
- if (this.forceStopTimeout) {
138
- clearTimeout(this.forceStopTimeout);
139
- this.forceStopTimeout = undefined;
155
+ if (type === 'moof') {
156
+ moofBuffer = Buffer.concat([header, data]);
140
157
  }
141
- // check whether motion is still in progress
142
- const motionDetected = this.accessory
143
- .getService(utils_1.SERV.MotionSensor)?.getCharacteristic(utils_1.CHAR.MotionDetected).value;
144
- if (motionDetected) {
145
- this.accessory
146
- .getService(utils_1.SERV.MotionSensor)?.getCharacteristic(utils_1.CHAR.MotionDetected)
147
- .updateValue(false);
158
+ else if (type === 'mdat' && moofBuffer) {
159
+ const fragment = Buffer.concat([moofBuffer, header, data]);
160
+ moofBuffer = null;
161
+ fragmentCount++;
162
+ log.debug(cameraName, `HKSV: Fragment #${fragmentCount}, size: ${fragment.length}`);
163
+ yield { data: fragment, isLast: false };
164
+ if (!this.isMotionDetected()) {
165
+ log.debug(cameraName, 'Ending recording session due to motion stopped.');
166
+ break;
167
+ }
148
168
  }
149
- this.localLivestreamManager.stopLocalLiveStream();
150
169
  }
151
170
  }
152
171
  updateRecordingActive(active) {
153
- utils_1.log.debug(`Recording: ${active}`, this.accessory.displayName);
172
+ log.debug(`Recording: ${active}`, this.accessory.displayName);
154
173
  }
155
174
  updateRecordingConfiguration(configuration) {
156
175
  this.configuration = configuration;
157
176
  }
158
177
  closeRecordingStream(streamId, reason) {
159
- utils_1.log.info(this.camera.getName(), 'Closing recording process');
178
+ log.info(this.camera.getName(), 'Closing recording process');
160
179
  if (this.session) {
161
- utils_1.log.debug(this.camera.getName(), 'Stopping recording session.');
180
+ log.debug(this.camera.getName(), 'Stopping recording session.');
162
181
  this.session.socket?.destroy();
163
182
  this.session.process?.kill('SIGKILL');
164
183
  this.session = undefined;
165
184
  }
166
185
  else {
167
- utils_1.log.warn('Recording session could not be closed gracefully.');
168
- }
169
- if (this.forceStopTimeout) {
170
- clearTimeout(this.forceStopTimeout);
171
- this.forceStopTimeout = undefined;
172
- }
173
- // check whether motion is still in progress
174
- const motionDetected = this.accessory
175
- .getService(utils_1.SERV.MotionSensor)?.getCharacteristic(utils_1.CHAR.MotionDetected).value;
176
- if (motionDetected) {
177
- this.accessory
178
- .getService(utils_1.SERV.MotionSensor)?.getCharacteristic(utils_1.CHAR.MotionDetected)
179
- .updateValue(false);
186
+ log.warn('Recording session could not be closed gracefully.');
180
187
  }
188
+ this.clearForceStopTimeout();
189
+ this.resetMotionSensor();
181
190
  this.closeReason = reason;
182
191
  this.handlingStreamingRequest = false;
183
192
  }
184
193
  acknowledgeStream(streamId) {
185
- utils_1.log.debug('end of recording acknowledged!');
194
+ log.debug('end of recording acknowledged!');
186
195
  this.closeRecordingStream(streamId, undefined);
187
196
  }
188
197
  }
189
- exports.RecordingDelegate = RecordingDelegate;
190
198
  //# sourceMappingURL=recordingDelegate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"recordingDelegate.js","sourceRoot":"","sources":["../../src/plugin/controller/recordingDelegate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"recordingDelegate.js","sourceRoot":"","sources":["../../src/controller/recordingDelegate.ts"],"names":[],"mappings":"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"}