@droponair/sdk-js 0.15.0 → 0.16.0
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 +12 -0
- package/README.md +23 -0
- package/dist/core/messaging-client.d.ts +4 -0
- package/dist/core/messaging-client.js +13 -0
- package/dist/core/types.d.ts +7 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,18 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [0.16.0], 2026-05-21
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Call recording signal.** `startRecording(callId)` / `stopRecording(callId)` / `markRecordingAvailable(callId, location)` for group and room calls. The SDK signals recording state; your app owns the media capture and uploads the file to your own storage (the same split as screen sharing - the platform never holds media). The platform broadcasts the signal to every participant, including late joiners, and fires `recording.started` / `recording.stopped` / `recording.available` webhooks. New `GROUP_CALL_RECORDING_*` event types.
|
|
14
|
+
|
|
15
|
+
### Notes
|
|
16
|
+
|
|
17
|
+
- A recording is always signaled to every participant - that transparency is enforced server-side and is not optional. Control-plane signaling only; no proto change.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
9
21
|
## [0.15.0], 2026-05-21
|
|
10
22
|
|
|
11
23
|
### Added
|
package/README.md
CHANGED
|
@@ -362,6 +362,29 @@ client.onGroupCallEvent((e) => {
|
|
|
362
362
|
|
|
363
363
|
Audience members are receive-only by convention: on `GROUP_CALL_ROLE_CHANGED` to `AUDIENCE`, your app simply does not publish a local media track. The platform signals the role; your app owns the WebRTC tracks.
|
|
364
364
|
|
|
365
|
+
### Call Recording
|
|
366
|
+
|
|
367
|
+
Available since SDK `0.16.0`. The SDK **signals** recording state on a group or room call; your app does the actual media capture (`MediaRecorder`) and uploads the file to your own storage — the platform never holds the media. The recording signal is broadcast to every participant (including anyone who joins later); that transparency is enforced server-side.
|
|
368
|
+
|
|
369
|
+
| Method | Description |
|
|
370
|
+
|--------|-------------|
|
|
371
|
+
| `startRecording(callId)` | Signal that you started recording |
|
|
372
|
+
| `stopRecording(callId)` | Signal that you stopped recording |
|
|
373
|
+
| `markRecordingAvailable(callId, location)` | Announce an uploaded recording (`location` references it in your storage) |
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
client.startRecording(callId);
|
|
377
|
+
// ... your app records the streams and uploads the file ...
|
|
378
|
+
client.markRecordingAvailable(callId, 's3://my-bucket/recordings/call-123.webm');
|
|
379
|
+
client.stopRecording(callId);
|
|
380
|
+
|
|
381
|
+
client.onGroupCallEvent((e) => {
|
|
382
|
+
if (e.type === 'GROUP_CALL_RECORDING_STARTED') showRecordingBanner(e.payload); // recorder userId
|
|
383
|
+
});
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
The platform also fires `recording.started` / `recording.stopped` / `recording.available` webhooks. For E2EE calls, recording stays on the client (the platform has no media plane); a server-side SFU recording mode is a future option.
|
|
387
|
+
|
|
365
388
|
### Screen Sharing
|
|
366
389
|
|
|
367
390
|
Available since SDK `0.6.0`. The SDK only signals start/stop - capture (via the browser's `getDisplayMedia()`) and adding the resulting `MediaStreamTrack` to the existing peer connection are the app's responsibility.
|
|
@@ -294,6 +294,10 @@ export declare class MessagingClient implements DropOnAirClient {
|
|
|
294
294
|
promoteToSpeaker(callId: string, userId: string): void;
|
|
295
295
|
demoteToAudience(callId: string, userId: string): void;
|
|
296
296
|
submitStageQuestion(callId: string, text: string): void;
|
|
297
|
+
startRecording(callId: string): void;
|
|
298
|
+
stopRecording(callId: string): void;
|
|
299
|
+
/** Announce an uploaded recording; `location` is a reference into your storage. */
|
|
300
|
+
markRecordingAvailable(callId: string, location: string): void;
|
|
297
301
|
private sendGroupCallFrame;
|
|
298
302
|
/**
|
|
299
303
|
* Initiate an outgoing call.
|
|
@@ -1336,6 +1336,19 @@ class MessagingClient {
|
|
|
1336
1336
|
submitStageQuestion(callId, text) {
|
|
1337
1337
|
this.sendGroupCallFrame({ type: 'GROUP_CALL_STAGE_QUESTION', callId, groupId: '', payload: text });
|
|
1338
1338
|
}
|
|
1339
|
+
// Call recording (Feature 3.5a). These SIGNAL recording state; the actual
|
|
1340
|
+
// media capture + upload to your storage is your app's job (same split as
|
|
1341
|
+
// screen sharing). The platform broadcasts the signal to every participant.
|
|
1342
|
+
startRecording(callId) {
|
|
1343
|
+
this.sendGroupCallFrame({ type: 'GROUP_CALL_RECORDING_STARTED', callId, groupId: '' });
|
|
1344
|
+
}
|
|
1345
|
+
stopRecording(callId) {
|
|
1346
|
+
this.sendGroupCallFrame({ type: 'GROUP_CALL_RECORDING_STOPPED', callId, groupId: '' });
|
|
1347
|
+
}
|
|
1348
|
+
/** Announce an uploaded recording; `location` is a reference into your storage. */
|
|
1349
|
+
markRecordingAvailable(callId, location) {
|
|
1350
|
+
this.sendGroupCallFrame({ type: 'GROUP_CALL_RECORDING_AVAILABLE', callId, groupId: '', payload: location });
|
|
1351
|
+
}
|
|
1339
1352
|
sendGroupCallFrame(frame) {
|
|
1340
1353
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
1341
1354
|
throw new Error('DropOnAir websocket is not connected');
|
package/dist/core/types.d.ts
CHANGED
|
@@ -135,7 +135,7 @@ export interface DecryptedGroupMessage {
|
|
|
135
135
|
plaintext: string;
|
|
136
136
|
}
|
|
137
137
|
export type GroupMessageCallback = (message: DecryptedGroupMessage) => void;
|
|
138
|
-
export type GroupCallEventType = 'GROUP_CALL_INVITE' | 'GROUP_CALL_RINGING' | 'GROUP_CALL_JOIN' | 'GROUP_CALL_LEAVE' | 'GROUP_CALL_END' | 'GROUP_CALL_ENDED' | 'GROUP_CALL_PARTICIPANT_JOINED' | 'GROUP_CALL_PARTICIPANT_LEFT' | 'GROUP_CALL_PARTICIPANT_REMOVED' | 'GROUP_CALL_ALREADY_ACTIVE' | 'GROUP_CALL_SDP_OFFER' | 'GROUP_CALL_SDP_ANSWER' | 'GROUP_CALL_ICE_CANDIDATE' | 'GROUP_CALL_SCREEN_SHARE_STARTED' | 'GROUP_CALL_SCREEN_SHARE_STOPPED' | 'GROUP_CALL_HOST_TRANSFER' | 'GROUP_CALL_COHOST_APPOINT' | 'GROUP_CALL_COHOST_REVOKE' | 'GROUP_CALL_ROLE_CHANGED' | 'GROUP_CALL_MUTE_PARTICIPANT' | 'GROUP_CALL_REMOVE_PARTICIPANT' | 'GROUP_CALL_WAITING_ROOM_REQUEST' | 'GROUP_CALL_WAITING_ROOM_JOINED' | 'GROUP_CALL_WAITING_ROOM_ADMIT' | 'GROUP_CALL_WAITING_ROOM_ADMITTED' | 'GROUP_CALL_WAITING_ROOM_REJECT' | 'GROUP_CALL_WAITING_ROOM_REJECTED' | 'GROUP_CALL_JOINED' | 'GROUP_CALL_WAITING_ROOM_PENDING' | 'GROUP_CALL_HOST_REQUIRED' | 'GROUP_CALL_ROOM_CLOSED' | 'GROUP_CALL_STAGE_HAND_RAISED' | 'GROUP_CALL_STAGE_HAND_LOWERED' | 'GROUP_CALL_STAGE_PROMOTE' | 'GROUP_CALL_STAGE_DEMOTE' | 'GROUP_CALL_STAGE_QUESTION';
|
|
138
|
+
export type GroupCallEventType = 'GROUP_CALL_INVITE' | 'GROUP_CALL_RINGING' | 'GROUP_CALL_JOIN' | 'GROUP_CALL_LEAVE' | 'GROUP_CALL_END' | 'GROUP_CALL_ENDED' | 'GROUP_CALL_PARTICIPANT_JOINED' | 'GROUP_CALL_PARTICIPANT_LEFT' | 'GROUP_CALL_PARTICIPANT_REMOVED' | 'GROUP_CALL_ALREADY_ACTIVE' | 'GROUP_CALL_SDP_OFFER' | 'GROUP_CALL_SDP_ANSWER' | 'GROUP_CALL_ICE_CANDIDATE' | 'GROUP_CALL_SCREEN_SHARE_STARTED' | 'GROUP_CALL_SCREEN_SHARE_STOPPED' | 'GROUP_CALL_HOST_TRANSFER' | 'GROUP_CALL_COHOST_APPOINT' | 'GROUP_CALL_COHOST_REVOKE' | 'GROUP_CALL_ROLE_CHANGED' | 'GROUP_CALL_MUTE_PARTICIPANT' | 'GROUP_CALL_REMOVE_PARTICIPANT' | 'GROUP_CALL_WAITING_ROOM_REQUEST' | 'GROUP_CALL_WAITING_ROOM_JOINED' | 'GROUP_CALL_WAITING_ROOM_ADMIT' | 'GROUP_CALL_WAITING_ROOM_ADMITTED' | 'GROUP_CALL_WAITING_ROOM_REJECT' | 'GROUP_CALL_WAITING_ROOM_REJECTED' | 'GROUP_CALL_JOINED' | 'GROUP_CALL_WAITING_ROOM_PENDING' | 'GROUP_CALL_HOST_REQUIRED' | 'GROUP_CALL_ROOM_CLOSED' | 'GROUP_CALL_STAGE_HAND_RAISED' | 'GROUP_CALL_STAGE_HAND_LOWERED' | 'GROUP_CALL_STAGE_PROMOTE' | 'GROUP_CALL_STAGE_DEMOTE' | 'GROUP_CALL_STAGE_QUESTION' | 'GROUP_CALL_RECORDING_STARTED' | 'GROUP_CALL_RECORDING_STOPPED' | 'GROUP_CALL_RECORDING_AVAILABLE';
|
|
139
139
|
export interface GroupCallEvent {
|
|
140
140
|
type: GroupCallEventType | string;
|
|
141
141
|
callId: string;
|
|
@@ -502,4 +502,10 @@ export interface DropOnAirClient {
|
|
|
502
502
|
demoteToAudience(callId: string, userId: string): void;
|
|
503
503
|
/** Submit a text question; relayed to the stage's speakers. */
|
|
504
504
|
submitStageQuestion(callId: string, text: string): void;
|
|
505
|
+
/** Signal that you have started recording the call. */
|
|
506
|
+
startRecording(callId: string): void;
|
|
507
|
+
/** Signal that you have stopped recording. */
|
|
508
|
+
stopRecording(callId: string): void;
|
|
509
|
+
/** Announce an uploaded recording; `location` references it in your storage. */
|
|
510
|
+
markRecordingAvailable(callId: string, location: string): void;
|
|
505
511
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* MINOR, additive feature (e.g. multi-device payloads, new call event type)
|
|
8
8
|
* PATCH, bug-fix / perf improvement with no wire or API change
|
|
9
9
|
*/
|
|
10
|
-
export declare const SDK_VERSION = "0.
|
|
10
|
+
export declare const SDK_VERSION = "0.16.0";
|
|
11
11
|
/**
|
|
12
12
|
* Binary encrypted-payload format version.
|
|
13
13
|
* Included as the first byte of every encrypted payload so receivers can
|
package/dist/version.js
CHANGED
|
@@ -10,7 +10,7 @@ exports.PROTOCOL_VERSION = exports.PAYLOAD_FORMAT_VERSION = exports.SDK_VERSION
|
|
|
10
10
|
* MINOR, additive feature (e.g. multi-device payloads, new call event type)
|
|
11
11
|
* PATCH, bug-fix / perf improvement with no wire or API change
|
|
12
12
|
*/
|
|
13
|
-
exports.SDK_VERSION = '0.
|
|
13
|
+
exports.SDK_VERSION = '0.16.0';
|
|
14
14
|
/**
|
|
15
15
|
* Binary encrypted-payload format version.
|
|
16
16
|
* Included as the first byte of every encrypted payload so receivers can
|