@camera.ui/camera-ui-homekit 0.0.2

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 (49) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/CONTRIBUTING.md +1 -0
  3. package/LICENSE.md +22 -0
  4. package/README.md +1 -0
  5. package/config.schema.json +15 -0
  6. package/dist/camera/accessory.d.ts +27 -0
  7. package/dist/camera/accessory.js +327 -0
  8. package/dist/camera/accessory.js.map +1 -0
  9. package/dist/camera/recordingDelegate.d.ts +27 -0
  10. package/dist/camera/recordingDelegate.js +263 -0
  11. package/dist/camera/recordingDelegate.js.map +1 -0
  12. package/dist/camera/services.d.ts +22 -0
  13. package/dist/camera/services.js +171 -0
  14. package/dist/camera/services.js.map +1 -0
  15. package/dist/camera/sessionWrapper.d.ts +25 -0
  16. package/dist/camera/sessionWrapper.js +287 -0
  17. package/dist/camera/sessionWrapper.js.map +1 -0
  18. package/dist/camera/streamingDelegate.d.ts +13 -0
  19. package/dist/camera/streamingDelegate.js +96 -0
  20. package/dist/camera/streamingDelegate.js.map +1 -0
  21. package/dist/camera/streamingServer.d.ts +24 -0
  22. package/dist/camera/streamingServer.js +143 -0
  23. package/dist/camera/streamingServer.js.map +1 -0
  24. package/dist/crypto.d.ts +1 -0
  25. package/dist/crypto.js +29 -0
  26. package/dist/crypto.js.map +1 -0
  27. package/dist/index.d.ts +19 -0
  28. package/dist/index.js +57 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/types.d.ts +10 -0
  31. package/dist/types.js +2 -0
  32. package/dist/types.js.map +1 -0
  33. package/dist/utils/codecs.d.ts +1 -0
  34. package/dist/utils/codecs.js +2 -0
  35. package/dist/utils/codecs.js.map +1 -0
  36. package/dist/utils/ffmpeg.d.ts +11 -0
  37. package/dist/utils/ffmpeg.js +66 -0
  38. package/dist/utils/ffmpeg.js.map +1 -0
  39. package/dist/utils/mac.d.ts +4 -0
  40. package/dist/utils/mac.js +19 -0
  41. package/dist/utils/mac.js.map +1 -0
  42. package/dist/utils/opus-repacketizer.d.ts +7 -0
  43. package/dist/utils/opus-repacketizer.js +163 -0
  44. package/dist/utils/opus-repacketizer.js.map +1 -0
  45. package/media/cameraOffline.png +0 -0
  46. package/media/maxStreams.png +0 -0
  47. package/media/noSnapshot.png +0 -0
  48. package/media/privacyMode.png +0 -0
  49. package/package.json +62 -0
@@ -0,0 +1,19 @@
1
+ import './crypto';
2
+ import type { BasePlugin, CameraDevice, FormSubmitResponse, PluginAPI, PluginLogger } from '@camera.ui/types';
3
+ import type { Accessory, MacAddress } from 'hap-nodejs';
4
+ import type { Config } from './types.js';
5
+ export default class HomeKit implements BasePlugin {
6
+ config: Config;
7
+ publishedExternalAccessories: Map<MacAddress, Accessory>;
8
+ logger: PluginLogger;
9
+ api: PluginAPI;
10
+ private readonly cameras;
11
+ private accessories;
12
+ constructor(logger: PluginLogger, api: PluginAPI);
13
+ configureCameras(cameras: CameraDevice[]): void;
14
+ onFormSubmit(actionId: string, payload: any): Promise<FormSubmitResponse | void>;
15
+ private start;
16
+ private stop;
17
+ private configureCamera;
18
+ private removeCamera;
19
+ }
package/dist/index.js ADDED
@@ -0,0 +1,57 @@
1
+ import './crypto';
2
+ import { HAPStorage } from 'hap-nodejs';
3
+ import { resolve } from 'node:path';
4
+ import { CameraAccessory } from './camera/accessory.js';
5
+ export default class HomeKit {
6
+ config;
7
+ publishedExternalAccessories = new Map();
8
+ logger;
9
+ api;
10
+ cameras = new Map();
11
+ accessories = new Map();
12
+ constructor(logger, api) {
13
+ this.logger = logger;
14
+ this.api = api;
15
+ this.config = api.configService.all();
16
+ this.config.advertiser = api.configService.get('advertiser', "ciao" /* MDNSAdvertiser.CIAO */, (value) => ["ciao" /* MDNSAdvertiser.CIAO */, "bonjour-hap" /* MDNSAdvertiser.BONJOUR */, "avahi" /* MDNSAdvertiser.AVAHI */, "resolved" /* MDNSAdvertiser.RESOLVED */].includes(value), false, true);
17
+ HAPStorage.setCustomStoragePath(resolve(this.api.storagePath, 'accessories'));
18
+ this.logger.debug('Configured mDNS advertiser:', this.config.advertiser);
19
+ this.api.on('finishLaunching', this.start.bind(this));
20
+ this.api.on('shutdown', this.stop.bind(this));
21
+ }
22
+ configureCameras(cameras) {
23
+ for (const camera of cameras) {
24
+ this.configureCamera(camera);
25
+ }
26
+ }
27
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
28
+ async onFormSubmit(actionId, payload) { }
29
+ async start() {
30
+ this.api.deviceManager.on('cameraSelected', async (cameraDevice) => {
31
+ await this.configureCamera(cameraDevice);
32
+ });
33
+ this.api.deviceManager.on('cameraDeselected', async (cameraId) => {
34
+ await this.removeCamera(cameraId);
35
+ });
36
+ }
37
+ async stop() {
38
+ await Promise.all(Array.from(this.accessories.values()).map((accessory) => accessory.teardown()));
39
+ }
40
+ async configureCamera(cameraDevice) {
41
+ this.logger.log('Configuring camera:', cameraDevice.name);
42
+ const cameraAccessory = new CameraAccessory(this, cameraDevice);
43
+ this.cameras.set(cameraDevice.id, cameraDevice);
44
+ this.accessories.set(cameraDevice.id, cameraAccessory);
45
+ }
46
+ async removeCamera(cameraId) {
47
+ const cameraDevice = this.cameras.get(cameraId);
48
+ if (cameraDevice) {
49
+ this.logger.log('Removing camera:', cameraDevice.name);
50
+ await this.accessories.get(cameraId)?.teardown();
51
+ this.cameras.delete(cameraId);
52
+ this.accessories.delete(cameraId);
53
+ this.api.storageController.removeCameraStorage(cameraId);
54
+ }
55
+ }
56
+ }
57
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { MDNSAdvertiser } from 'hap-nodejs';
2
+ export interface Config {
3
+ advertiser: MDNSAdvertiser;
4
+ }
5
+ export type MP4Atom = {
6
+ header: Buffer;
7
+ length: number;
8
+ type: string;
9
+ data: Buffer;
10
+ };
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export declare const baseAudioCodecs: string[];
@@ -0,0 +1,2 @@
1
+ export const baseAudioCodecs = ['libopus', 'pcm_alaw', 'pcm_mulaw'];
2
+ //# sourceMappingURL=codecs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codecs.js","sourceRoot":"","sources":["../../src/utils/codecs.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare const NAL_TYPE_STAP_A = 24;
2
+ export declare const NAL_TYPE_FU_A = 28;
3
+ export declare const NAL_TYPE_NON_IDR = 1;
4
+ export declare const NAL_TYPE_IDR = 5;
5
+ export declare const NAL_TYPE_SEI = 6;
6
+ export declare const NAL_TYPE_SPS = 7;
7
+ export declare const NAL_TYPE_PPS = 8;
8
+ export declare const NAL_TYPE_DELIMITER = 9;
9
+ export declare const allowedNaluTypes: number[];
10
+ export declare function timeoutPromise<T>(timeout: number, promise: Promise<T>): Promise<T>;
11
+ export declare function checkMp4StartsWithKeyFrame(mp4: Buffer, ffmpegPath: string): Promise<boolean>;
@@ -0,0 +1,66 @@
1
+ import { spawn } from 'node:child_process';
2
+ // https://yumichan.net/video-processing/video-compression/introduction-to-h264-nal-unit/
3
+ export const NAL_TYPE_STAP_A = 24;
4
+ export const NAL_TYPE_FU_A = 28;
5
+ export const NAL_TYPE_NON_IDR = 1;
6
+ export const NAL_TYPE_IDR = 5;
7
+ export const NAL_TYPE_SEI = 6;
8
+ export const NAL_TYPE_SPS = 7;
9
+ export const NAL_TYPE_PPS = 8;
10
+ export const NAL_TYPE_DELIMITER = 9;
11
+ export const allowedNaluTypes = [NAL_TYPE_STAP_A, NAL_TYPE_SPS, NAL_TYPE_PPS, NAL_TYPE_SEI, NAL_TYPE_DELIMITER];
12
+ export function timeoutPromise(timeout, promise) {
13
+ return new Promise((resolve, reject) => {
14
+ const t = setTimeout(() => reject(new Error('Operation timed out')), timeout);
15
+ promise
16
+ .then((v) => {
17
+ clearTimeout(t);
18
+ resolve(v);
19
+ })
20
+ .catch((e) => {
21
+ clearTimeout(t);
22
+ reject(e);
23
+ });
24
+ });
25
+ }
26
+ export async function checkMp4StartsWithKeyFrame(mp4, ffmpegPath) {
27
+ const cp = spawn(ffmpegPath, ['-hide_banner', '-f', 'mp4', '-i', 'pipe:3', '-vcodec', 'copy', '-f', 'h264', 'pipe:4'], {
28
+ stdio: ['pipe', 'pipe', 'pipe', 'pipe', 'pipe'],
29
+ });
30
+ const input = cp.stdio[3];
31
+ const output = cp.stdio[4];
32
+ const buffers = [];
33
+ input.write(mp4);
34
+ input.end();
35
+ output.on('data', (data) => buffers.push(data));
36
+ try {
37
+ await timeoutPromise(1000, new Promise((resolve) => cp.on('exit', resolve)));
38
+ const h264 = Buffer.concat(buffers);
39
+ let offset = 0;
40
+ while (offset < h264.length - 6) {
41
+ if (h264.readInt32BE(offset) !== 1) {
42
+ offset++;
43
+ continue;
44
+ }
45
+ offset += 4;
46
+ let naluType = h264.readUInt8(offset) & 0x1f;
47
+ if (naluType === NAL_TYPE_FU_A) {
48
+ offset++;
49
+ naluType = h264.readUInt8(offset) & 0x1f;
50
+ }
51
+ if (naluType === NAL_TYPE_IDR) {
52
+ return true;
53
+ }
54
+ if (allowedNaluTypes.includes(naluType)) {
55
+ offset++;
56
+ continue;
57
+ }
58
+ return false;
59
+ }
60
+ return false;
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ }
66
+ //# sourceMappingURL=ffmpeg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ffmpeg.js","sourceRoot":"","sources":["../../src/utils/ffmpeg.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export type MacAddress = string;
2
+ export declare function validMacAddress(address: string): boolean;
3
+ export declare function generate(data: string | Buffer | NodeJS.TypedArray | DataView): MacAddress;
4
+ export declare function randomPinCode(): string;
@@ -0,0 +1,19 @@
1
+ import crypto from 'node:crypto';
2
+ const validMac = /^([0-9A-F]{2}:){5}([0-9A-F]{2})$/;
3
+ function rd() {
4
+ return Math.round(Math.random() * 100000) % 10;
5
+ }
6
+ export function validMacAddress(address) {
7
+ return validMac.test(address);
8
+ }
9
+ export function generate(data) {
10
+ const sha1sum = crypto.createHash('sha1');
11
+ sha1sum.update(data);
12
+ const s = sha1sum.digest('hex');
13
+ let i = 0;
14
+ return 'xx:xx:xx:xx:xx:xx'.replace(/[x]/g, () => s[i++]).toUpperCase();
15
+ }
16
+ export function randomPinCode() {
17
+ return `${rd()}${rd()}${rd()}-${rd()}${rd()}-${rd()}${rd()}${rd()}`;
18
+ }
19
+ //# sourceMappingURL=mac.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mac.js","sourceRoot":"","sources":["../../src/utils/mac.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,MAAM,QAAQ,GAAG,kCAAkC,CAAC;AAEpD,SAAS,EAAE;IACT,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC;AACjD,CAAC;AAID,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAoD;IAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC1C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACrB,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEhC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,mBAAmB,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;AACtE,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { RtpPacket } from 'werift';
2
+ export declare class OpusRepacketizer {
3
+ framesPerPacket: number;
4
+ depacketized: Buffer[];
5
+ constructor(framesPerPacket: number);
6
+ repacketize(packet: RtpPacket): RtpPacket | undefined;
7
+ }
@@ -0,0 +1,163 @@
1
+ // OpusRepacketizer is borrowed from scrypted
2
+ // Original source: https://github.com/koush/scrypted/blob/3150a3033515a3886af1e6b35a0ba7432b63e02b/plugins/homekit/src/types/camera/opus-repacketizer.ts
3
+ // https://datatracker.ietf.org/doc/html/rfc6716
4
+ // INPUT (for single frame sample, see RFC for other 4 code values)
5
+ // 0 1 2 3
6
+ // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
7
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8
+ // | config |s|0|0| |
9
+ // +-+-+-+-+-+-+-+-+ |
10
+ // | Compressed frame 1 (N-1 bytes)... :
11
+ // : |
12
+ // | |
13
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14
+ // OUTPUT
15
+ // 0 1 2 3
16
+ // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
17
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18
+ // | config |s|1|1|1|p| M | Padding length (Optional) :
19
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20
+ // : N1 (1-2 bytes): N2 (1-2 bytes): ... : N[M-1] |
21
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22
+ // | |
23
+ // : Compressed frame 1 (N1 bytes)... :
24
+ // | |
25
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26
+ // | |
27
+ // : Compressed frame 2 (N2 bytes)... :
28
+ // | |
29
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30
+ // | |
31
+ // : ... :
32
+ // | |
33
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34
+ // | |
35
+ // : Compressed frame M... :
36
+ // | |
37
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38
+ // : Opus Padding (Optional)... |
39
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40
+ // Figure 6: A CBR Code 3 Packet
41
+ // In the VBR case, the (optional) padding length is followed by M-1
42
+ // frame lengths (indicated by "N1" to "N[M-1]" in Figure 7), each
43
+ // encoded in a one- or two-byte sequence as described above. The
44
+ // packet MUST contain enough data for the M-1 lengths after removing
45
+ // the (optional) padding, and the sum of these lengths MUST be no
46
+ // larger than the number of bytes remaining in the packet after
47
+ // decoding them [R7]. The compressed data for all M frames follows,
48
+ // each frame consisting of the indicated number of bytes, with the
49
+ // final frame consuming any remaining bytes before the final padding,
50
+ // as illustrated in Figure 6. The number of header bytes (TOC byte,
51
+ // frame count byte, padding length bytes, and frame length bytes), plus
52
+ // the signaled length of the first M-1 frames themselves, plus the
53
+ // signaled length of the padding MUST be no larger than N, the total
54
+ // size of the packet.
55
+ export class OpusRepacketizer {
56
+ framesPerPacket;
57
+ depacketized = [];
58
+ constructor(framesPerPacket) {
59
+ this.framesPerPacket = framesPerPacket;
60
+ }
61
+ // repacketize a packet with a single frame into a packet with multiple frames.
62
+ repacketize(packet) {
63
+ const code = packet.payload[0] & 0b00000011;
64
+ let offset;
65
+ // see Frame Length Coding in RFC
66
+ const decodeFrameLength = () => {
67
+ let frameLength = packet.payload.readUInt8(offset);
68
+ if (frameLength >= 252) {
69
+ offset++;
70
+ frameLength += packet.payload.readUInt8(offset) * 4;
71
+ }
72
+ return frameLength;
73
+ };
74
+ // code 0: cbr, 1 packet
75
+ // code 1: cbr, 2 packets
76
+ // code 2: vbr, 2 packets
77
+ // code 3: cbr/vbr signaled, variable packets
78
+ if (code === 0) {
79
+ if (this.framesPerPacket === 1 && !this.depacketized.length)
80
+ return packet;
81
+ // depacketize by stripping off the config byte
82
+ this.depacketized.push(packet.payload.subarray(1));
83
+ }
84
+ else if (code === 1) {
85
+ if (this.framesPerPacket === 2 && !this.depacketized.length)
86
+ return packet;
87
+ // depacketize by dividing the remaining payload into two equal sized frames
88
+ const remaining = packet.payload.length - 1;
89
+ if (remaining % 2) {
90
+ throw new Error('expected equal sized opus packets (code 1)');
91
+ }
92
+ const frameLength = remaining / 2;
93
+ this.depacketized.push(packet.payload.subarray(1, 1 + frameLength));
94
+ this.depacketized.push(packet.payload.subarray(1 + frameLength));
95
+ }
96
+ else if (code === 2) {
97
+ if (this.framesPerPacket === 2 && !this.depacketized.length)
98
+ return packet;
99
+ offset = 1;
100
+ // depacketize by dividing the remaining payload into two inequal sized frames
101
+ const frameLength = decodeFrameLength();
102
+ this.depacketized.push(packet.payload.subarray(offset, offset + frameLength));
103
+ this.depacketized.push(packet.payload.subarray(offset + frameLength));
104
+ }
105
+ else if (code === 3) {
106
+ // code 3 packet will have a frame count and padding indicator, and whether the packets
107
+ // are equal size or not.
108
+ const frameCountByte = packet.payload[1], packetFrameCount = frameCountByte & 0b00111111, vbr = frameCountByte & 0b10000000;
109
+ if (this.framesPerPacket === packetFrameCount && !this.depacketized.length) {
110
+ return packet;
111
+ }
112
+ const paddingIndicator = frameCountByte & 0b01000000;
113
+ offset = 2;
114
+ let padding = 0;
115
+ if (paddingIndicator) {
116
+ padding = packet.payload.readUInt8(offset);
117
+ offset++;
118
+ if (padding === 255) {
119
+ padding = 254 + packet.payload.readUInt8(offset);
120
+ offset++;
121
+ }
122
+ }
123
+ if (!vbr) {
124
+ const remaining = packet.payload.length - offset - padding;
125
+ if (remaining % packetFrameCount) {
126
+ throw new Error('expected equal sized opus packets (code 3)');
127
+ }
128
+ const frameLength = remaining / packetFrameCount;
129
+ for (let i = 0; i < packetFrameCount; i++) {
130
+ const start = offset + i * frameLength, end = start + frameLength;
131
+ this.depacketized.push(packet.payload.subarray(start, end));
132
+ }
133
+ }
134
+ else {
135
+ const frameLengths = [];
136
+ for (let i = 0; i < packetFrameCount; i++) {
137
+ const frameLength = decodeFrameLength();
138
+ frameLengths.push(frameLength);
139
+ }
140
+ for (let i = 0; i < packetFrameCount; i++) {
141
+ const frameLength = frameLengths[i], start = offset;
142
+ offset += frameLength;
143
+ this.depacketized.push(packet.payload.subarray(start, offset));
144
+ }
145
+ }
146
+ }
147
+ if (this.depacketized.length < this.framesPerPacket)
148
+ return;
149
+ const depacketized = this.depacketized.slice(0, this.framesPerPacket);
150
+ this.depacketized = this.depacketized.slice(this.framesPerPacket);
151
+ // reuse the config and stereo indicator, but change the code to 3.
152
+ let toc = packet.payload[0];
153
+ toc |= 0b00000011;
154
+ // vbr | padding indicator | packet count
155
+ const frameCountByte = 0b10000000 | this.framesPerPacket, newHeader = [toc, frameCountByte];
156
+ // M-1 length bytes
157
+ newHeader.push(...depacketized.slice(0, -1).map((data) => data.length));
158
+ const headerBuffer = Buffer.from(newHeader), payload = Buffer.concat([headerBuffer, ...depacketized]);
159
+ packet.payload = payload;
160
+ return packet;
161
+ }
162
+ }
163
+ //# sourceMappingURL=opus-repacketizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opus-repacketizer.js","sourceRoot":"","sources":["../../src/utils/opus-repacketizer.ts"],"names":[],"mappings":"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"}
Binary file
Binary file
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "displayName": "HomeKit",
3
+ "name": "@camera.ui/camera-ui-homekit",
4
+ "version": "0.0.2",
5
+ "description": "camera.ui homekit plugin",
6
+ "author": "seydx (https://github.com/seydx/camera.ui)",
7
+ "main": "./dist/index.js",
8
+ "type": "module",
9
+ "scripts": {
10
+ "build": "rimraf dist && tsc",
11
+ "format": "prettier --write 'src/' --ignore-unknown --no-error-on-unmatched-pattern",
12
+ "lint": "eslint --fix --ext .js,.ts .",
13
+ "update": "updates --update ./",
14
+ "install-updates": "npm i --save",
15
+ "prepublishOnly": "npm i --package-lock-only && npm run lint && npm run format && npm run build"
16
+ },
17
+ "dependencies": {
18
+ "@homebridge/camera-utils": "^2.2.6",
19
+ "chacha": "^2.1.0",
20
+ "hap-nodejs": "^1.1.0",
21
+ "rxjs": "^7.8.1",
22
+ "werift": "^0.19.4"
23
+ },
24
+ "devDependencies": {
25
+ "@camera.ui/types": "^0.0.54",
26
+ "@rushstack/eslint-patch": "^1.10.4",
27
+ "@types/node": "^22.1.0",
28
+ "@types/ws": "^8.5.12",
29
+ "@typescript-eslint/eslint-plugin": "^8.0.1",
30
+ "@typescript-eslint/parser": "^8.0.1",
31
+ "concurrently": "^8.2.2",
32
+ "eslint": "8.57.0",
33
+ "eslint-config-prettier": "^9.1.0",
34
+ "eslint-plugin-prettier": "^5.2.1",
35
+ "prettier": "^3.3.3",
36
+ "rimraf": "^6.0.1",
37
+ "typescript": "^5.5.4",
38
+ "updates": "^16.3.7"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/seydx/camera.ui/issues"
42
+ },
43
+ "engines": {
44
+ "camera.ui": ">=0.0.1",
45
+ "node": ">=18.12.0"
46
+ },
47
+ "homepage": "https://github.com/seydx/camera.ui#readme",
48
+ "keywords": [
49
+ "camera-ui-plugin",
50
+ "ring",
51
+ "webrtc"
52
+ ],
53
+ "license": "MIT",
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "git+https://github.com/seydx/camera.ui.git"
57
+ },
58
+ "camera.ui": {
59
+ "extension": "hub",
60
+ "dependencies": []
61
+ }
62
+ }