ring-client-api 11.0.2-beta.0 → 11.0.2-beta.1

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [11.0.2-beta.1](https://github.com/dgreif/ring/compare/v11.0.2-beta.0...v11.0.2-beta.1) (2022-05-21)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **api:** prevent duplicate events from `onCallEnded` ([75696d5](https://github.com/dgreif/ring/commit/75696d510969f706248a0f83e98fb1c99fc07213)), closes [#941](https://github.com/dgreif/ring/issues/941)
11
+ * handle pcmu return audio ([ce29fb5](https://github.com/dgreif/ring/commit/ce29fb5638bc488c515518a0fadcaca900ebe750)), closes [#930](https://github.com/dgreif/ring/issues/930)
12
+
5
13
  ### [11.0.2-beta.0](https://github.com/dgreif/ring/compare/v11.0.1...v11.0.2-beta.0) (2022-05-21)
6
14
 
7
15
 
@@ -20,6 +20,7 @@ export declare class StreamingSession extends Subscribed {
20
20
  readonly onAudioRtp: Subject<RtpPacket>;
21
21
  private readonly audioSplitter;
22
22
  private readonly videoSplitter;
23
+ private readonly returnAudioSplitter;
23
24
  constructor(camera: RingCamera, connection: RingEdgeConnection | WebrtcConnection);
24
25
  private bindToConnection;
25
26
  activated: boolean;
@@ -27,7 +28,12 @@ export declare class StreamingSession extends Subscribed {
27
28
  cameraSpeakerActivated: boolean;
28
29
  activateCameraSpeaker(): Promise<void>;
29
30
  reservePort(bufferPorts?: number): Promise<number>;
31
+ get isUsingOpus(): Promise<boolean>;
30
32
  startTranscoding(ffmpegOptions: FfmpegOptions): Promise<void>;
33
+ transcodeReturnAudio(ffmpegOptions: {
34
+ input: SpawnInput[];
35
+ }): Promise<void>;
36
+ private hasEnded;
31
37
  private callEnded;
32
38
  stop(): void;
33
39
  sendAudioPacket(rtp: RtpPacket): void;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StreamingSession = void 0;
4
+ const werift_1 = require("werift");
4
5
  const camera_utils_1 = require("@homebridge/camera-utils");
5
6
  const rxjs_1 = require("rxjs");
6
7
  const ffmpeg_1 = require("../ffmpeg");
@@ -26,8 +27,10 @@ class StreamingSession extends subscribed_1.Subscribed {
26
27
  this.onAudioRtp = new rxjs_1.Subject();
27
28
  this.audioSplitter = new camera_utils_1.RtpSplitter();
28
29
  this.videoSplitter = new camera_utils_1.RtpSplitter();
30
+ this.returnAudioSplitter = new camera_utils_1.RtpSplitter();
29
31
  this.activated = false;
30
32
  this.cameraSpeakerActivated = false;
33
+ this.hasEnded = false;
31
34
  this.bindToConnection(connection);
32
35
  }
33
36
  bindToConnection(connection) {
@@ -36,14 +39,14 @@ class StreamingSession extends subscribed_1.Subscribed {
36
39
  }));
37
40
  }
38
41
  async activate() {
39
- if (this.activated) {
42
+ if (this.activated || this.hasEnded) {
40
43
  return;
41
44
  }
42
45
  this.activated = true;
43
46
  await this.connection.activate();
44
47
  }
45
48
  async activateCameraSpeaker() {
46
- if (this.cameraSpeakerActivated) {
49
+ if (this.cameraSpeakerActivated || this.hasEnded) {
47
50
  return;
48
51
  }
49
52
  this.cameraSpeakerActivated = true;
@@ -53,8 +56,14 @@ class StreamingSession extends subscribed_1.Subscribed {
53
56
  const ports = await (0, camera_utils_1.reservePorts)({ count: bufferPorts + 1 });
54
57
  return ports[0];
55
58
  }
59
+ get isUsingOpus() {
60
+ return (0, rxjs_1.firstValueFrom)(this.onUsingOpus);
61
+ }
56
62
  async startTranscoding(ffmpegOptions) {
57
- const videoPort = await this.reservePort(1), audioPort = await this.reservePort(1), transcodeVideoStream = ffmpegOptions.video !== false, ringSdp = await (0, rxjs_1.firstValueFrom)(this.connection.onCallAnswered), usingOpus = await (0, rxjs_1.firstValueFrom)(this.onUsingOpus), ffmpegInputArguments = [
63
+ if (this.hasEnded) {
64
+ return;
65
+ }
66
+ const videoPort = await this.reservePort(1), audioPort = await this.reservePort(1), transcodeVideoStream = ffmpegOptions.video !== false, ringSdp = await (0, rxjs_1.firstValueFrom)(this.connection.onCallAnswered), usingOpus = await this.isUsingOpus, ffmpegInputArguments = [
58
67
  '-hide_banner',
59
68
  '-protocol_whitelist',
60
69
  'pipe,udp,rtp,file,crypto',
@@ -100,17 +109,61 @@ class StreamingSession extends subscribed_1.Subscribed {
100
109
  // Activate the stream now that ffmpeg is ready to receive
101
110
  await this.activate();
102
111
  }
112
+ async transcodeReturnAudio(ffmpegOptions) {
113
+ if (this.hasEnded) {
114
+ return;
115
+ }
116
+ const audioOutForwarder = new camera_utils_1.RtpSplitter(({ message }) => {
117
+ const rtp = werift_1.RtpPacket.deSerialize(message);
118
+ this.connection.sendAudioPacket(rtp);
119
+ return null;
120
+ }), usingOpus = await this.isUsingOpus, ff = new camera_utils_1.FfmpegProcess({
121
+ ffmpegArgs: [
122
+ '-hide_banner',
123
+ '-protocol_whitelist',
124
+ 'pipe,udp,rtp,file,crypto',
125
+ '-re',
126
+ '-i',
127
+ ...ffmpegOptions.input,
128
+ '-acodec',
129
+ ...(usingOpus
130
+ ? ['libopus', '-ac', 2, '-ar', '48k']
131
+ : ['pcm_mulaw', '-ac', 1, '-ar', '8k']),
132
+ '-flags',
133
+ '+global_header',
134
+ '-f',
135
+ 'rtp',
136
+ `rtp://127.0.0.1:${await audioOutForwarder.portPromise}`,
137
+ ],
138
+ ffmpegPath: (0, ffmpeg_1.getFfmpegPath)(),
139
+ exitCallback: () => this.callEnded(),
140
+ logLabel: `Return Audio (${this.camera.name})`,
141
+ logger: {
142
+ error: util_1.logError,
143
+ info: util_1.logDebug,
144
+ },
145
+ });
146
+ this.onCallEnded.subscribe(() => ff.stop());
147
+ }
103
148
  callEnded() {
149
+ if (this.hasEnded) {
150
+ return;
151
+ }
152
+ this.hasEnded = true;
104
153
  this.unsubscribe();
105
154
  this.onCallEnded.next();
106
155
  this.connection.stop();
107
156
  this.audioSplitter.close();
108
157
  this.videoSplitter.close();
158
+ this.returnAudioSplitter.close();
109
159
  }
110
160
  stop() {
111
161
  this.callEnded();
112
162
  }
113
163
  sendAudioPacket(rtp) {
164
+ if (this.hasEnded) {
165
+ return;
166
+ }
114
167
  this.connection.sendAudioPacket(rtp);
115
168
  }
116
169
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ring-client-api",
3
- "version": "11.0.2-beta.0",
3
+ "version": "11.0.2-beta.1",
4
4
  "description": "Unofficial API for Ring doorbells, cameras, security alarm system and smart lighting",
5
5
  "main": "lib/api/index.js",
6
6
  "bin": {