@voltkit-rtc/client 0.3.0 → 0.5.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/README.md +196 -24
  3. package/dist/cjs/chat.d.ts +2 -0
  4. package/dist/cjs/chat.d.ts.map +1 -1
  5. package/dist/cjs/chat.js +23 -4
  6. package/dist/cjs/chat.js.map +1 -1
  7. package/dist/cjs/device.d.ts +85 -0
  8. package/dist/cjs/device.d.ts.map +1 -0
  9. package/dist/cjs/device.js +134 -0
  10. package/dist/cjs/device.js.map +1 -0
  11. package/dist/cjs/index.d.ts +212 -6
  12. package/dist/cjs/index.d.ts.map +1 -1
  13. package/dist/cjs/index.js +822 -52
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/cjs/music.d.ts +1 -1
  16. package/dist/cjs/music.d.ts.map +1 -1
  17. package/dist/cjs/quality.d.ts +43 -16
  18. package/dist/cjs/quality.d.ts.map +1 -1
  19. package/dist/cjs/quality.js +81 -31
  20. package/dist/cjs/quality.js.map +1 -1
  21. package/dist/cjs/stats.d.ts +151 -0
  22. package/dist/cjs/stats.d.ts.map +1 -0
  23. package/dist/cjs/stats.js +243 -0
  24. package/dist/cjs/stats.js.map +1 -0
  25. package/dist/esm/chat.d.ts +2 -0
  26. package/dist/esm/chat.d.ts.map +1 -1
  27. package/dist/esm/chat.js +23 -4
  28. package/dist/esm/chat.js.map +1 -1
  29. package/dist/esm/device.d.ts +85 -0
  30. package/dist/esm/device.d.ts.map +1 -0
  31. package/dist/esm/device.js +122 -0
  32. package/dist/esm/device.js.map +1 -0
  33. package/dist/esm/index.d.ts +212 -6
  34. package/dist/esm/index.d.ts.map +1 -1
  35. package/dist/esm/index.js +823 -53
  36. package/dist/esm/index.js.map +1 -1
  37. package/dist/esm/music.d.ts +1 -1
  38. package/dist/esm/music.d.ts.map +1 -1
  39. package/dist/esm/quality.d.ts +43 -16
  40. package/dist/esm/quality.d.ts.map +1 -1
  41. package/dist/esm/quality.js +76 -31
  42. package/dist/esm/quality.js.map +1 -1
  43. package/dist/esm/stats.d.ts +151 -0
  44. package/dist/esm/stats.d.ts.map +1 -0
  45. package/dist/esm/stats.js +232 -0
  46. package/dist/esm/stats.js.map +1 -0
  47. package/package.json +1 -1
  48. package/src/chat.ts +21 -4
  49. package/src/device.ts +168 -0
  50. package/src/index.ts +879 -58
  51. package/src/music.ts +1 -1
  52. package/src/quality.ts +96 -32
  53. package/src/stats.ts +328 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,115 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0
4
+
5
+ - All video tiers included by default: 1080p, 720p and 480p. Per-project restrictions still apply.
6
+ - Authoritative 30 fps ladder: 6/3/1.2 Mbps top layers, 1080p lower layers 0.4/2 Mbps, 720p lower layers 0.2/0.8 Mbps. Phone/tablet defaults remain two layers.
7
+ - `PublishOptions.frameRate` and `setVideoFrameRate(30 | 60)`. At 60 fps only the top layer rises to 9/4.5/1.8 Mbps; smaller layers stay at 30. Low capture fps or sustained device/upload limitation falls back to 30 with `frame-rate-fallback` on `error`.
8
+ - Camera start bitrate is 2000 kbps.
9
+ - The 60 fps monitor allows encoder/bitrate warm-up before counting sustained limitation, so the intentional 30 fps lower layers during startup do not immediately trigger fallback.
10
+ - `publishScreen` / `unpublishScreen`, `ScreenPublishOptions`, `screenShareStarted` / `screenShareEnded`, separate `screen-audio`, native-size detail/motion ladders and reconnect restoration. Screen, camera, mic and music controls remain independent. Browser stop-sharing and interrupted capture clean up both screen producers.
11
+ - `setReceiveQuality(producerId, 'auto' | '1080p' | '720p' | '480p')`, `ReceiveQuality` and producer `videoLayers` metadata. Presets follow actual dimensions; Auto clears both layer ceilings; reconnect restores the choice. Older publishers without metadata report `quality-unavailable` for explicit presets.
12
+ - Same-size `replaceVideoTrack` stays smooth. A change in dimensions republishes camera video so advertised layer dimensions remain accurate.
13
+ - `raiseHand(metadata?)`, `lowerHand(identity?)`, hand-event metadata/reason and roster `handMetadata` support role requests and moderated responses.
14
+ - `participantMuted` normalizes moderation locks to `{ identity, kind, paused }`; `ParticipantInfo.videoBlocked` seeds camera locks on reconnect. Demotion while disconnected releases retained capture, and rejected unmute calls keep the device paused.
15
+ - A screen-share republish that fails halfway cleans up that share while the camera continues.
16
+ - No package publishing is part of this source update.
17
+
18
+ ## 0.4.0
19
+
20
+ Sharper video, above all from phones. Nothing to change to upgrade: every 0.3.0
21
+ call works as before, with new defaults.
22
+
23
+ - **Higher bitrates.** Each layer gets about 4 Mbps at 1080p, 2.5 Mbps at
24
+ 720p, 1.5 Mbps at 540p, 1 Mbps at 480p, 700 kbps at 360p and 400 kbps at
25
+ 240p (were 2.5 Mbps, 1.8 Mbps, 1.2 Mbps, 750, 600 and 250 kbps). At 720p
26
+ that brought VP8's quantiser down from about 64 to 55: finer detail, most
27
+ of all in motion. A new stream's bandwidth estimate starts at 1.5 Mbps (was
28
+ 1 Mbps). The service's per-publisher caps rose to match (4 Mbps up to 720p,
29
+ 7 Mbps with 1080p), and viewers of 720p now start on the top layer instead
30
+ of taking about 15 s to climb to it.
31
+ - **Phones keep the full picture.** New `PublishOptions.layers` (1, 2 or 3).
32
+ Phones and tablets now send two layers (half and full size) by default,
33
+ computers three as before. A busy phone shrinks its picture and then sends
34
+ fewer layers, dropping the top one: from three, viewers of a 720p phone got
35
+ 180×320; from two, the full picture survives.
36
+ - **H.264 on phones.** New `PublishOptions.codec`: `'auto'` (the default)
37
+ sends H.264 on phones and tablets that encode it in hardware and VP8
38
+ everywhere else; `'vp8'` and `'h264'` force one. If H.264 cannot be used,
39
+ VP8 is sent and the publish goes on; a forced `'h264'` that falls back also
40
+ fires `error`. A viewer whose browser cannot decode H.264 (rare: a few
41
+ browser builds leave it out) cannot watch a phone sending it: force `'vp8'`
42
+ if your audience uses such browsers.
43
+ - New `PublishOptions.degradationPreference`: what the encoder gives up first
44
+ on a busy device. Unset leaves the browser's default.
45
+ - **`getVideoStats()`**: what the camera is sending, layer by layer, and why
46
+ it is less than asked (`qualityLimitation`: `cpu` is the device,
47
+ `bandwidth` the upload). **`getReceiveStats(producerId)`**: what this client
48
+ receives of someone's video.
49
+ - **`videoLimited` event**: the camera video is being held back by the device
50
+ (`cpu`), the upload (`bandwidth`) or something else (`other`), or that has
51
+ cleared (`none`). It fires once a reason has held for about 4 s, and is
52
+ checked only while you listen. Tell the publisher, so they know it is their
53
+ device or connection.
54
+ - **`replaceVideoTrack(track)`**: send another video track, such as a canvas
55
+ with effects or the raw camera again. Viewers see no pause when the new
56
+ track takes the same layers. Your own stream is never modified, and a
57
+ track replaced while the camera was paused comes back to you switched on.
58
+ - **`setPreferredLayers(producerId, spatialLayer, temporalLayer?)`**: receive
59
+ a smaller copy of someone's video for a small tile, as the Flutter and
60
+ native SDKs already could. Layer 0 is the smallest copy sent; at 720p the
61
+ 640×360 copy needs about 0.76 Mbps instead of 2.6 for the full picture. The
62
+ choice is kept across reconnects and forgotten when the track ends.
63
+ - `setVideoQuality`, `replaceVideoTrack` and publishing now change the camera
64
+ producer one at a time, so quick changes cannot leave two of them, and an
65
+ `unpublish()` in the middle of one leaves none.
66
+ - Upload needed rises with the bitrates: about 3.4 Mbps for 720p from a
67
+ computer (3.2 from a phone), 6 Mbps for 1080p (5.5 from a phone) and
68
+ 1.4 Mbps for 480p.
69
+ - New exports: the `LayerCount`, `CodecPreference`, `VideoSendStats`,
70
+ `VideoLayerStats`, `VideoReceiveStats`, `VideoLimitedEvent` and
71
+ `VideoLimitReason` types. `videoEncodings` takes the most layers to send as
72
+ an optional fourth argument.
73
+ - **Fix: reconnecting gives up when it should.** The attempt count restarted
74
+ whenever the socket opened, so a join refused with a code worth retrying
75
+ (`no-capacity`, `no-node`, `internal`) was retried about twice a second,
76
+ forever, and `closed` with `gave-up` never came: in a full cluster every
77
+ client kept at it. The count now restarts only once a join succeeds, the
78
+ gaps keep growing (half a second, doubling to 15 s), and after eight failed
79
+ attempts in a row the client stops with `closed` (`gave-up`). A connection
80
+ that drops again while a reconnect is restoring the session is retried
81
+ too; it was left disconnected, with no `closed`. `ChatClient` counted the
82
+ same way and is fixed the same way.
83
+ - **Fix: a camera that is off stays off, on both ends.** A track handed to
84
+ `publish()` switched off, a camera switched off before a reconnect, or a
85
+ quality change or track swap to other layers could leave the camera paused
86
+ in the client but live on the server, so viewers got black video under a
87
+ camera shown as on (and silence, for a microphone or music switched off
88
+ before a reconnect). The server is now paused too; a camera producer that
89
+ is replaced starts in the camera's state, and while the camera is off no
90
+ frame of the new track is sent; a track swapped in during a reconnect, and
91
+ devices a reconnect has to ask for again, keep a camera that was off, off.
92
+ `camEnabled`, `micEnabled` and `localMediaChanged` report as before.
93
+ - **Fix:** `unpublish()` while `publish()` or `publishMusic()` is still
94
+ making the microphone or music producer no longer leaves it published; the
95
+ camera was already covered. What was being made is closed and that call
96
+ rejects. A reconnect's republish under way when `unpublish()` runs
97
+ publishes nothing either.
98
+ - **Fix: `unpublish()` forgets the devices.** It kept the capture constraints
99
+ given to `publish()`, so after `unpublish()` and then `publishMusic()`, a
100
+ reconnect asked for the camera and microphone again and published them.
101
+ Music published after `unpublish()` now reconnects alone.
102
+ - **Fix:** `publish()` and `unpublish()` act in the order they are called. A
103
+ `publish()` or `publishMusic()` called while an `unpublish()` was still
104
+ waiting on the server had its new stream stopped and its state cleared when
105
+ that `unpublish()` finished. `unpublish()` now makes all its changes at once
106
+ and only then waits for the server.
107
+ - **Fix:** a first `connect()` that fails at the join closes its socket and
108
+ starts no reconnect loop; only a session that has joined is reconnected.
109
+ Before, the server's join deadline closed that socket about 15 s later, and
110
+ the client began reconnecting a session the app had already been told had
111
+ failed. `ChatClient` too.
112
+
3
113
  ## 0.3.0
4
114
 
5
115
  - **Video quality.** `publish(stream, constraints, { quality })` takes
package/README.md CHANGED
@@ -48,7 +48,7 @@ const joined = await client.connect();
48
48
 
49
49
  if (joined.role === 'host' || joined.role === 'cohost') {
50
50
  const media = await navigator.mediaDevices.getUserMedia({ audio: true, video: { width: 1280, height: 720 } });
51
- await client.publish(media); // 720p, sent as 3 simulcast layers
51
+ await client.publish(media); // 720p: 3 simulcast layers from a computer, 2 from a phone
52
52
  }
53
53
  ```
54
54
 
@@ -69,6 +69,40 @@ client.publishing; client.micEnabled; client.camEnabled; client.local; // curr
69
69
  A `viewer` cannot publish. That is enforced at the media server, not in this
70
70
  package — a tampered client gets an error, not a stream.
71
71
 
72
+ `publish(media, constraints, options)` takes these options. The defaults suit
73
+ phones and computers alike; they are kept for a reconnect's republish.
74
+
75
+ | Option | Default | What it does |
76
+ | --- | --- | --- |
77
+ | `quality` | the highest the project allows | `'1080p'`, `'720p'` or `'480p'`; see [Video quality](#video-quality) |
78
+ | `frameRate` | `30` | `30` or `60`; only the top layer runs at 60 fps; capture at 60 too |
79
+ | `layers` | `2` on phones and tablets, `3` elsewhere | the most simulcast layers to send. When a phone is too busy, the browser shrinks the picture and may then send fewer layers, dropping the top one: asked for two, it keeps the full picture; asked for three, viewers were left with a quarter of it |
80
+ | `codec` | `'auto'` | `'auto'` sends H.264 on phones and tablets that encode it in hardware, VP8 elsewhere. `'vp8'` or `'h264'` forces one; a forced H.264 the browser cannot send is VP8, and fires `error` |
81
+ | `degradationPreference` | the browser's | what the encoder gives up first on a busy device: `'maintain-resolution'` (frame rate goes first), `'maintain-framerate'` or `'balanced'` |
82
+
83
+ ```ts
84
+ await client.publish(media, undefined, { quality: '720p', layers: 2, codec: 'auto', degradationPreference: 'maintain-resolution' });
85
+ ```
86
+
87
+ Chrome also reads the trade-off from the track itself:
88
+ `track.contentHint = 'detail'` keeps the resolution, `'motion'` the frame rate.
89
+ A viewer whose browser cannot decode the codec cannot watch, so force `'vp8'`
90
+ if your audience uses browsers without H.264 (rare).
91
+
92
+ To send another video track while live, such as a canvas with effects drawn on
93
+ it or the raw camera again:
94
+
95
+ ```ts
96
+ await client.replaceVideoTrack(canvas.captureStream(30).getVideoTracks()[0]);
97
+ ```
98
+
99
+ When the new track has the same dimensions and layers as the old one, viewers see no pause; otherwise the camera's producer is replaced
100
+ and they see a brief one. A paused camera stays paused. Your own stream is not
101
+ modified: the client keeps one of its own (`client.local`, announced by
102
+ `localStreamChanged`) with the new track, and a reconnect republishes that. The
103
+ track you replaced is yours again: it is not stopped, and if pausing the camera
104
+ had switched it off, it is switched back on.
105
+
72
106
  ### Video quality
73
107
 
74
108
  Choose 1080p, 720p or 480p when publishing, or change it while live:
@@ -78,30 +112,163 @@ const media = await navigator.mediaDevices.getUserMedia({ audio: true, video: {
78
112
  await client.publish(media, undefined, { quality: '1080p' });
79
113
  await client.setVideoQuality('480p'); // resolves to the quality actually used
80
114
 
81
- client.videoPolicy; // { maxQuality: '720p' | '1080p', maxBitrate } for this project
115
+ client.videoPolicy; // { maxQuality: '480p' | '720p' | '1080p', maxFrameRate, maxBitrate } for this project
82
116
  client.videoQuality; // what is being sent now
83
117
  ```
84
118
 
85
- | Quality | Layers sent (simulcast) | Top layer |
86
- |---|---|---|
87
- | 1080p | 480×270 · 960×540 · 1920×1080 | 2.5 Mbps |
88
- | 720p | 320×180 · 640×360 · 1280×720 | 1.8 Mbps |
89
- | 480p | 427×240 · 854×480 | 750 kbps |
90
-
91
- - 720p and 480p are available to every project. 1080p is available during the
92
- free trial, and after that to projects that have it enabled (request it from
93
- your project's Settings in the VoltKit dashboard). Asking for more than the project
94
- allows sends the highest it does allow.
95
- - The default is the highest the project allows. The picture is scaled down to
96
- the quality, never up: capture at least that size for the full picture.
97
- - The layers follow the picture's real size (a portrait phone, a 4:3 webcam),
98
- so the browser sends every layer requested.
99
- - The server caps each publisher's incoming bitrate for the project's tier
100
- (3.2 Mbps up to 720p, 5 Mbps with 1080p), whatever client is used.
101
-
102
- The full guide, with data use and troubleshooting:
119
+ | Quality | Layers from a computer at 30 fps | From a phone or tablet | Video upload |
120
+ |---|---|---|---|
121
+ | 1080p | 480×270 @ 0.4 Mbps · 960×540 @ 2 Mbps · 1920×1080 @ **6 Mbps** | the top two | about 8.4 Mbps (phone 8) |
122
+ | 720p | 320×180 @ 0.2 Mbps · 640×360 @ 0.8 Mbps · 1280×720 @ **3 Mbps** | the top two | about 4 Mbps (phone 3.8) |
123
+ | 480p | 427×240 @ 0.4 Mbps · 854×480 @ **1.2 Mbps** | the same two | about 1.6 Mbps |
124
+
125
+ All qualities are included on every plan. The default policy allows 1080p and
126
+ 60 fps, with a 25 Mbps incoming safety cap per publisher. A project can have
127
+ an explicit administrative restriction; `videoPolicy` describes it.
128
+ The picture is scaled down to the chosen quality, never up. Portrait phones
129
+ keep their shape, for example 360×640 and 720×1280. Adaptive reception is the
130
+ default: viewers receive the best layer their connection can carry. Viewers
131
+ start with a 4 Mbps estimate, enough for 720p; 1080p ramps up as bandwidth allows.
132
+
133
+ 30 fps is the default. For 60 fps, capture at 60 and opt in:
134
+
135
+ ```ts
136
+ await client.publish(media, undefined, { quality: '1080p', frameRate: 60 });
137
+ const effectiveFps = await client.setVideoFrameRate(30); // camera only, other tracks continue
138
+ ```
139
+
140
+ Only the top layer uses 60 fps: 1080p is **9 Mbps**, 720p **4.5 Mbps**, and
141
+ 480p **1.8 Mbps**; smaller layers stay at 30. This means roughly 1.5× the top
142
+ layer's data and twice the encoding work. Phones can heat up and use more
143
+ battery, and many front cameras capture only 30. If capture is below 50 fps,
144
+ a project restricts it, or sustained device/upload limitation prevents 60,
145
+ the SDK uses 30 and emits `error` with `code: 'frame-rate-fallback'` as a warning.
146
+ `setVideoFrameRate(60)` retries the preference while preserving a paused camera.
147
+
148
+ The full guide, with data use:
103
149
  [voltkit.in/docs/video-quality](https://voltkit.in/docs/video-quality).
104
150
 
151
+ ### When the picture is soft
152
+
153
+ A soft or stuttering picture usually comes from the publisher's device (too
154
+ busy to encode) or their upload (too slow for the top layer), not from the
155
+ service. The client can tell you which.
156
+
157
+ ```ts
158
+ const stats = await client.getVideoStats(); // null when no camera is published
159
+ // { codec: 'H264', quality: '720p', width: 720, height: 1280, fps: 30, bitrate: 2400000,
160
+ // qualityLimitation: 'none', availableOutgoingBitrate: 3900000, layers: [ ... ] }
161
+ ```
162
+
163
+ The top-level fields describe the biggest layer going out; `layers` lists each
164
+ one (`active`, size, frame rate, bitrate). `qualityLimitation` is the browser's
165
+ reason for sending less than asked: `cpu` is the device, `bandwidth` the
166
+ upload, `none` neither (then look at the camera and the light). Bitrates are
167
+ averaged since your previous call, so call it every second or two; the first
168
+ call reports 0.
169
+
170
+ `videoLimited` tells you when that changes, so you can tell the publisher:
171
+
172
+ ```ts
173
+ client.on('videoLimited', ({ reason }) => {
174
+ if (reason === 'cpu') showNotice('Your device is busy, so the stream is softer. Turn off effects or switch to 480p.');
175
+ else if (reason === 'bandwidth') showNotice('Your upload is slow, so viewers get a lighter picture.');
176
+ else hideNotice(); // 'none': cleared; 'other': rare
177
+ });
178
+ ```
179
+
180
+ It fires once a new reason has held for about 4 seconds, so brief spikes stay
181
+ quiet, and never fires `none` first. The client checks every 2 seconds, and
182
+ while a camera is published and something listens, or while 60 fps needs fallback monitoring. `unpublish()` fires
183
+ `none` if a limitation was showing.
184
+
185
+ On a viewer, `getReceiveStats(producerId)` (the `producerId` from the `track`
186
+ event) says what arrives: size, frame rate, bitrate, `packetsLost`, `jitter`
187
+ and, where the browser counts them, `freezeCount`. A viewer receiving a
188
+ smaller picture than the publisher's biggest layer is on a lower one, picked
189
+ for their own connection; if every viewer is, look at the publisher's
190
+ `getVideoStats()`.
191
+
192
+ The [troubleshooting guide](https://voltkit.in/docs/troubleshooting) lists the
193
+ usual causes and what to do about each.
194
+
195
+ ### Small tiles
196
+
197
+ Each viewer gets the biggest layer their connection carries, which a thumbnail
198
+ or a row of co-host tiles does not need. Ask for a smaller one with the
199
+ `producerId` from the `track` event:
200
+
201
+ ```ts
202
+ client.on('track', ({ kind, producerId, track }) => {
203
+ if (kind !== 'video') return;
204
+ showVideo(producerId, track);
205
+ if (isSmallTile(producerId)) client.setPreferredLayers(producerId, 0).catch(console.warn);
206
+ });
207
+
208
+ await client.setPreferredLayers(producerId, 2); // the tile grew: the biggest layer again
209
+ ```
210
+
211
+ Layer 0 is the smallest copy the publisher sends. At 720p a computer sends
212
+ three (320×180, 640×360 and 1280×720) and a phone two (640×360 and 1280×720);
213
+ a layer above the biggest means the biggest. The 640×360 copy needs about
214
+ 0.9 Mbps including audio, the full picture about 3.1. An optional third argument, the
215
+ temporal layer, lowers the frame rate as well; without it the full frame rate
216
+ is kept. It is the most this viewer is sent: a connection that cannot carry it
217
+ still gets less. The choice is kept across reconnects and forgotten when the
218
+ track ends, and `setPreferredLayers` rejects for a video this client is not
219
+ receiving.
220
+
221
+ ### Receive quality
222
+
223
+ ```ts
224
+ await client.setReceiveQuality(producerId, '480p');
225
+ await client.setReceiveQuality(producerId, 'auto'); // recommended; clears spatial AND temporal ceilings
226
+ ```
227
+
228
+ Offer **Auto (recommended) / 1080p / 720p / 480p**. The `ReceiveQuality` helper
229
+ maps the request to the producer's actual `videoLayers` dimensions, including
230
+ portrait phones, two-layer cameras and screen tracks. It chooses the largest
231
+ available copy within the ceiling, or the smallest available if none fits.
232
+ It never creates a missing resolution: a 1080p screen with 540p and 1080p copies
233
+ uses 540p for the 480p choice. Connection adaptation still applies below the
234
+ ceiling. The preference is remembered across reconnects and ends with that
235
+ producer. Without layer metadata, explicit choices reject `quality-unavailable`;
236
+ Auto and the numeric `setPreferredLayers` API still work.
237
+
238
+ ### Screen sharing
239
+
240
+ Hosts and cohosts can share a screen beside their camera in SDK 0.5.0:
241
+
242
+ ```ts
243
+ client.on('screenShareStarted', ({ stream, mode }) => showScreenPreview(stream, mode));
244
+ client.on('screenShareEnded', ({ reason }) => hideScreenPreview(reason));
245
+ await client.publishScreen({ mode: 'detail', audio: true }); // from a button click
246
+ await client.unpublishScreen(); // camera, mic and music continue
247
+ ```
248
+
249
+ `ScreenPublishOptions` accepts `mode: 'detail' | 'motion'` (default `detail`),
250
+ `audio?: boolean` and `stream?: MediaStream`. Without `stream`, the SDK opens
251
+ `getDisplayMedia` and returns its `MediaStream`; capture audio defaults to
252
+ false. An existing stream's audio is used unless `audio: false` is supplied.
253
+ The SDK stops the supplied screen tracks when sharing ends.
254
+
255
+ Detail sends up to native 1920×1080 at 15 fps and 2.5 Mbps plus a half-size
256
+ 0.6 Mbps copy. Motion uses 30 fps, 6 Mbps plus 0.6 Mbps. Capture is never
257
+ upscaled. Optional tab/system audio is separate, `source: 'screen-audio'`,
258
+ 128 kbps stereo. Viewers play it like `music`; screen video arrives with
259
+ `source: 'screen'`. A browser may grant video without granting audio.
260
+
261
+ The browser's **Stop sharing** automatically unpublishes and emits
262
+ `screenShareEnded({ reason: 'track-ended' })`. Calling `unpublishScreen` emits
263
+ `reason: 'stopped'`. A reconnect republishes a still-live screen without another
264
+ picker. `unpublish()` and `close()` stop all local media. Unsupported capture
265
+ (most mobile browsers) rejects `screen-share-unsupported`; overlapping shares
266
+ reject `screen-share-active`; missing live video rejects `screen-share-no-video`.
267
+ Browser cancellation retains its `NotAllowedError`. Capture requires HTTPS,
268
+ a user gesture and permission; in iframes, also allow `display-capture`.
269
+
270
+ [Setup, modes, native platforms and troubleshooting](https://voltkit.in/docs/screen-sharing).
271
+
105
272
  ### Music
106
273
 
107
274
  A host can play music to the room from inside the page. It does not go through
@@ -146,6 +313,8 @@ musicAudio.muted = true; // "mute the music" for this viewer only
146
313
  ```ts
147
314
  await client.raiseHand();
148
315
  await client.lowerHand();
316
+ await client.raiseHand({ requestRole: 'cohost' }); // metadata also supports 'moderator'
317
+ await client.lowerHand(identity); // host/moderator: decline that raised hand
149
318
  await client.muteParticipant(identity); // moderating roles: asks them to mute
150
319
  await client.forceMute(identity, 'video'); // moderating roles: camera off, locked until released
151
320
  await client.forceMute(identity, 'video', false); // release
@@ -159,19 +328,22 @@ await client.getRoomState();
159
328
 
160
329
  | Event | Fires when |
161
330
  | --- | --- |
162
- | `track` / `trackEnded` | someone's audio or video is ready to render, or went away; `source` is `mic`, `music`, `camera` or `screen` |
331
+ | `track` / `trackEnded` | someone's audio or video is ready to render, or went away; `source` is `mic`, `music`, `camera`, `screen` or `screen-audio` |
163
332
  | `trackMuted` | someone paused or resumed a track — muted their mic, switched their music off |
164
333
  | `participantJoined` / `participantLeft` | roster changes |
334
+ | `participantMuted` | moderation lock changed: `{ identity, kind, paused }`; reconnect roster `muted` / `videoBlocked` seed the locks |
165
335
  | `roleChanged` | someone was promoted or demoted |
166
- | `handRaised` | a hand went up or down |
336
+ | `handRaised` | a hand went up or down, with optional `metadata` and `reason`; reconnect rosters include `handMetadata` |
337
+ | `screenShareStarted` / `screenShareEnded` | local screen capture began (`stream`, `mode`) or stopped (`reason`) |
167
338
  | `forceMuted` | a moderator switched **your** mic or camera off |
168
339
  | `streamInterrupted` | media stopped but the connection is fine — the publisher is reconnecting |
169
340
  | `localMediaChanged` / `localStreamChanged` | your own mic, camera or stream changed |
170
341
  | `connected` / `disconnected` | the socket came up or dropped; reconnection is automatic |
171
342
  | `kicked` / `roomClosed` | you were removed, or the host ended the room |
172
- | `error` | something failed that the SDK could not recover from by itself |
343
+ | `error` | a failure or recoverable warning such as `frame-rate-fallback`; inspect its code |
173
344
  | `usageLimit` | your project ran out of minutes or hit a usage limit; the session ends at `endsAt` unless it is topped up |
174
- | `closed` | terminal — `replaced`, `kicked`, `room-closed` or `gave-up`; your own `close()` does not fire it |
345
+ | `videoLimited` | your camera video is held back by this device (`cpu`) or the upload (`bandwidth`), or that cleared (`none`) |
346
+ | `closed` | terminal — `replaced`, `kicked`, `room-closed` or `gave-up`, or `left` when your own `close()` ends the session |
175
347
 
176
348
  `on()` returns a function that removes the listener.
177
349
 
@@ -104,6 +104,8 @@ export declare class ChatClient {
104
104
  private closedByUs;
105
105
  private reconnecting;
106
106
  private reconnectAttempt;
107
+ /** Set by the first successful join. Only a session that has joined is reconnected. */
108
+ private joinedOnce;
107
109
  constructor(wsUrl: string, token: string);
108
110
  on<K extends keyof ChatClientEvents>(event: K, fn: ChatClientEvents[K]): () => void;
109
111
  private emit;
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/chat.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/chat.ts"],"names":[],"mappings":"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"}
package/dist/cjs/chat.js CHANGED
@@ -39,6 +39,8 @@ class ChatClient {
39
39
  closedByUs = false;
40
40
  reconnecting = false;
41
41
  reconnectAttempt = 0;
42
+ /** Set by the first successful join. Only a session that has joined is reconnected. */
43
+ joinedOnce = false;
42
44
  constructor(wsUrl, token) {
43
45
  this.wsUrl = wsUrl;
44
46
  this.token = token;
@@ -67,8 +69,24 @@ class ChatClient {
67
69
  return this.joinResult;
68
70
  }
69
71
  async connect() {
70
- await this.openSocket();
71
- const result = (await this.rpc('join', { token: this.token }));
72
+ let result;
73
+ try {
74
+ await this.openSocket();
75
+ result = (await this.rpc('join', { token: this.token }));
76
+ }
77
+ catch (err) {
78
+ // Never joined: the app has the error. Left open, the socket would be
79
+ // closed by the server's join deadline, and that would start
80
+ // reconnecting a session that never began.
81
+ if (!this.joinedOnce)
82
+ this.detachSocket();
83
+ throw err;
84
+ }
85
+ // Joined: the next drop gets every reconnect attempt again. Not when the
86
+ // socket opens, or a join refused with a code worth retrying never uses
87
+ // them up and is retried about twice a second, forever.
88
+ this.reconnectAttempt = 0;
89
+ this.joinedOnce = true;
72
90
  this.joinResult = result;
73
91
  this.emit('joined', result);
74
92
  return result;
@@ -82,7 +100,6 @@ class ChatClient {
82
100
  this.ws = ws;
83
101
  const onError = () => reject(new Error('websocket failed to open'));
84
102
  ws.addEventListener('open', () => {
85
- this.reconnectAttempt = 0;
86
103
  this.emit('connected');
87
104
  resolve();
88
105
  }, { once: true });
@@ -105,7 +122,9 @@ class ChatClient {
105
122
  this.emit('closed', 'ended');
106
123
  return;
107
124
  }
108
- if (!this.closedByUs)
125
+ // Before a first join the app is still waiting on connect(), which
126
+ // reports the failure; there is no session to restore.
127
+ if (!this.closedByUs && this.joinedOnce)
109
128
  void this.scheduleReconnect();
110
129
  });
111
130
  });
@@ -1 +1 @@
1
- {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/chat.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/chat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * What kind of device is publishing, and which video codec it should send.
3
+ *
4
+ * Phones and tablets get different defaults from computers: each simulcast
5
+ * layer is a separate encode, and a phone encoding VP8 does it in software.
6
+ * Under that load Chrome shrinks the picture, and with three layers asked for
7
+ * it then sends only two and drops the TOP one: viewers got 180×320 from a
8
+ * 720p phone. Two layers in hardware H.264 keep the full picture.
9
+ *
10
+ * Everything here reads the browser through small injectable parameters, so
11
+ * tests can stand in for any device.
12
+ */
13
+ import type { types as ms } from 'mediasoup-client';
14
+ type RtpCodecCapability = ms.RtpCodecCapability;
15
+ /** What the SDK reads about the browser to choose its defaults. */
16
+ export interface DeviceEnv {
17
+ userAgent: string;
18
+ /** `navigator.userAgentData.mobile`, where the browser has it (Chromium). */
19
+ uaMobile?: boolean;
20
+ maxTouchPoints: number;
21
+ }
22
+ /** The browser this runs in; an empty desktop-like one outside a browser. */
23
+ export declare function currentEnv(): DeviceEnv;
24
+ /**
25
+ * A phone or a tablet. `userAgentData.mobile` is false on Android tablets, so
26
+ * the user agent is checked as well.
27
+ */
28
+ export declare function isPhoneOrTablet(env?: DeviceEnv): boolean;
29
+ /** An iPhone, iPad or iPod: every one of them encodes H.264 in hardware. */
30
+ export declare function isAppleMobile(env?: DeviceEnv): boolean;
31
+ /** Two layers on phones and tablets, three elsewhere. */
32
+ export declare function defaultLayerCount(env?: DeviceEnv): 2 | 3;
33
+ /** `navigator.mediaCapabilities.encodingInfo`, or a stand-in for tests. */
34
+ export type EncodingInfoProbe = (configuration: MediaEncodingConfiguration) => Promise<MediaCapabilitiesEncodingInfo>;
35
+ /** The browser's own probe, when it has one. */
36
+ export declare function currentProbe(): EncodingInfoProbe | undefined;
37
+ /** The H.264 the media server takes: constrained baseline, packetization mode 1. */
38
+ export declare const H264_CONTENT_TYPE = "video/H264;profile-level-id=42e01f;packetization-mode=1";
39
+ /**
40
+ * Whether this browser encodes H.264 at this size and bitrate in hardware:
41
+ * true or false when it says so, null when it cannot say (no
42
+ * `mediaCapabilities`, no `webrtc` support in it, an error, or no answer in
43
+ * time). Publishing never waits on it for more than a moment.
44
+ */
45
+ export declare function h264HardwareEncode(video: {
46
+ width: number;
47
+ height: number;
48
+ bitrate: number;
49
+ }, probe?: EncodingInfoProbe | undefined, timeoutMs?: number): Promise<boolean | null>;
50
+ /** What `PublishOptions.codec` may say. */
51
+ export type CodecPreference = 'auto' | 'vp8' | 'h264';
52
+ /** 'vp8' or 'h264' in any case; anything else, including nothing, is 'auto'. */
53
+ export declare function normalizeCodec(codec: unknown): CodecPreference;
54
+ export interface CodecChoiceInput {
55
+ requested: CodecPreference;
56
+ phoneOrTablet: boolean;
57
+ appleMobile: boolean;
58
+ /** This browser can send H.264 to this server (it is in the device's send capabilities). */
59
+ h264Available: boolean;
60
+ /** What the hardware probe said; null when it could not say. Only asked for 'auto' on phones and tablets. */
61
+ h264Hardware: boolean | null;
62
+ }
63
+ export interface CodecChoice {
64
+ codec: 'vp8' | 'h264';
65
+ /** Set when the codec asked for cannot be used: report it, and publish anyway. */
66
+ warning?: string;
67
+ }
68
+ /**
69
+ * The codec to publish with.
70
+ *
71
+ * 'auto' is H.264 on a phone or tablet that encodes it in hardware, and VP8
72
+ * everywhere else: computers encode VP8 well, and a few desktop browsers
73
+ * cannot decode H.264. When the probe cannot say, an Apple device is taken to
74
+ * have hardware H.264 (they all do) and anything else is not.
75
+ */
76
+ export declare function chooseCodec(input: CodecChoiceInput): CodecChoice;
77
+ /**
78
+ * The device's own capability entry for a codec, to hand to `produce()`.
79
+ * Only ever pass `produce()` an entry from the device's send capabilities:
80
+ * mediasoup-client adds the transceiver before it checks the codec, so one it
81
+ * cannot match leaves a transceiver behind that breaks every later produce.
82
+ */
83
+ export declare function findCodec(codecs: readonly RtpCodecCapability[] | undefined, codec: 'vp8' | 'h264'): RtpCodecCapability | undefined;
84
+ export {};
85
+ //# sourceMappingURL=device.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../src/device.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,KAAK,IAAI,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAEpD,KAAK,kBAAkB,GAAG,EAAE,CAAC,kBAAkB,CAAC;AAEhD,mEAAmE;AACnE,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,IAAI,SAAS,CAStC;AAMD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,SAAwB,GAAG,OAAO,CAItE;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,GAAG,GAAE,SAAwB,GAAG,OAAO,CAEpE;AAED,yDAAyD;AACzD,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,SAAwB,GAAG,CAAC,GAAG,CAAC,CAEtE;AAED,2EAA2E;AAC3E,MAAM,MAAM,iBAAiB,GAAG,CAAC,aAAa,EAAE,0BAA0B,KAAK,OAAO,CAAC,6BAA6B,CAAC,CAAC;AAEtH,gDAAgD;AAChD,wBAAgB,YAAY,IAAI,iBAAiB,GAAG,SAAS,CAK5D;AAED,oFAAoF;AACpF,eAAO,MAAM,iBAAiB,4DAA4D,CAAC;AAI3F;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EACzD,KAAK,GAAE,iBAAiB,GAAG,SAA0B,EACrD,SAAS,SAAmB,GAC3B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAyBzB;AAED,2CAA2C;AAC3C,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAEtD,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAG9D;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,eAAe,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,4FAA4F;IAC5F,aAAa,EAAE,OAAO,CAAC;IACvB,6GAA6G;IAC7G,YAAY,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC;IACtB,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAShE;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAIlI"}