Skip to content

Commit 1065124

Browse files
authored
Implement Dynacast and AdaptiveStream (#102)
* Update protocol, switch to using it as submodule * Implements Dynacast. Renamed autoManageVideo -> adaptiveStream
1 parent d9e9b6c commit 1065124

19 files changed

+883
-88
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "protocol"]
2+
path = protocol
3+
url = https://github.com/livekit/protocol

README.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@ import {
4747

4848
// creates a new room with options
4949
const room = new Room({
50-
// automatically manage video quality
51-
autoManageVideo: true,
50+
// automatically manage subscribed video quality
51+
adaptiveStream: true,
52+
53+
// optimize publishing bandwidth and CPU for simulcasted tracks
54+
dynacast: true,
5255

5356
// default capture settings
5457
videoCaptureDefaults: {
@@ -152,7 +155,21 @@ if (p) {
152155
}
153156
```
154157

155-
### Advanced track manipulation
158+
### Creating a track prior to creating a room
159+
160+
In some cases, it may be useful to create a track before creating a room. For
161+
example, when building a staging area so the user may check their own camera.
162+
163+
You can use our global track creation functions for this:
164+
165+
```typescript
166+
const tracks = await createLocalTracks({
167+
audio: true,
168+
video: true,
169+
});
170+
```
171+
172+
### Publish tracks from any source
156173

157174
LiveKit lets you publish any track as long as it can be represented by a MediaStreamTrack. You can specify a name on the track in order to identify it later.
158175

example/index.html

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,22 @@ <h2>Livekit Sample App</h2>
7272
<input
7373
type="checkbox"
7474
class="form-check-input"
75-
id="adaptive-video"
75+
id="dynacast"
7676
checked
7777
/>
78-
<label for="adaptive-video" class="form-check-label">
79-
Adaptive video
78+
<label for="dynacast" class="form-check-label">
79+
Dynacast
80+
</label>
81+
</div>
82+
<div>
83+
<input
84+
type="checkbox"
85+
class="form-check-input"
86+
id="adaptive-stream"
87+
checked
88+
/>
89+
<label for="adaptive-stream" class="form-check-label">
90+
AdaptiveStream
8091
</label>
8192
</div>
8293
<div>

example/sample.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,16 @@ const appActions = {
2626
const url = (<HTMLInputElement>$('url')).value;
2727
const token = (<HTMLInputElement>$('token')).value;
2828
const simulcast = (<HTMLInputElement>$('simulcast')).checked;
29+
const dynacast = (<HTMLInputElement>$('dynacast')).checked;
2930
const forceTURN = (<HTMLInputElement>$('force-turn')).checked;
30-
const adaptiveVideo = (<HTMLInputElement>$('adaptive-video')).checked;
31+
const adaptiveStream = (<HTMLInputElement>$('adaptive-stream')).checked;
3132
const shouldPublish = (<HTMLInputElement>$('publish-option')).checked;
3233

3334
setLogLevel('debug');
3435

3536
const roomOpts: RoomOptions = {
36-
autoManageVideo: adaptiveVideo,
37+
adaptiveStream,
38+
dynacast,
3739
publishDefaults: {
3840
simulcast,
3941
},

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"scripts": {
1212
"build": "yarn exec tsc",
1313
"build-docs": "yarn exec typedoc",
14-
"proto": "protoc --plugin=node_modules/ts-proto/protoc-gen-ts_proto --ts_proto_opt=esModuleInterop=true --ts_proto_out=./src/proto --ts_proto_opt=outputClientImpl=false,useOptionals=true -I../protocol ../protocol/livekit_rtc.proto ../protocol/livekit_models.proto",
14+
"proto": "protoc --plugin=node_modules/ts-proto/protoc-gen-ts_proto --ts_proto_opt=esModuleInterop=true --ts_proto_out=./src/proto --ts_proto_opt=outputClientImpl=false,useOptionals=true -I./protocol ./protocol/livekit_rtc.proto ./protocol/livekit_models.proto",
1515
"sample": "cd example && webpack serve",
1616
"build-sample": "cd example && webpack && cp styles.css index.html dist/",
1717
"lint": "yarn exec eslint src",

protocol

Submodule protocol added at cf8fab9

src/api/SignalClient.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {
1111
SignalRequest,
1212
SignalResponse,
1313
SignalTarget,
14+
StreamStateUpdate,
15+
SubscribedQualityUpdate,
1416
TrackPublishedResponse,
1517
UpdateSubscription,
1618
UpdateTrackSettings,
@@ -59,6 +61,10 @@ export class SignalClient {
5961

6062
onConnectionQuality?: (update: ConnectionQualityUpdate) => void;
6163

64+
onStreamStateUpdate?: (update: StreamStateUpdate) => void;
65+
66+
onSubscribedQualityUpdate?: (update: SubscribedQualityUpdate) => void;
67+
6268
onLeave?: () => void;
6369

6470
ws?: WebSocket;
@@ -310,6 +316,14 @@ export class SignalClient {
310316
if (this.onConnectionQuality) {
311317
this.onConnectionQuality(msg.connectionQuality);
312318
}
319+
} else if (msg.streamStateUpdate) {
320+
if (this.onStreamStateUpdate) {
321+
this.onStreamStateUpdate(msg.streamStateUpdate);
322+
}
323+
} else if (msg.subscribedQualityUpdate) {
324+
if (this.onSubscribedQualityUpdate) {
325+
this.onSubscribedQualityUpdate(msg.subscribedQualityUpdate);
326+
}
313327
} else {
314328
log.debug('unsupported message', msg);
315329
}

src/connect.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ export async function connect(
3131
options?: ConnectOptions,
3232
): Promise<Room> {
3333
options ??= {};
34+
if (options.adaptiveStream === undefined) {
35+
options.adaptiveStream = options.autoManageVideo;
36+
}
3437
setLogLevel(options.logLevel ?? LogLevel.warn);
3538

3639
const config: RTCConfiguration = options.rtcConfig ?? {};

src/options.ts

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,22 @@ import {
88
*/
99
export interface RoomOptions {
1010
/**
11-
* automatically manage quality of subscribed video tracks, subscribe to the
12-
* an appropriate resolution based on the size of the video elements that
13-
* tracks are attached to.
11+
* AdaptiveStream lets LiveKit automatically manage quality of subscribed
12+
* video tracks to optimize for bandwidth and CPU.
13+
* When attached video elements are visible, it'll choose an appropriate
14+
* resolution based on the size of largest video element it's attached to.
1415
*
15-
* also observes the visibility of attached tracks and pauses receiving data
16-
* if they are not visible. when an attached element becomes visible again,
17-
* the track resumes receiving data.
16+
* When none of the video elements are visible, it'll temporarily pause
17+
* the data flow until they are visible again.
1818
*/
19-
autoManageVideo?: boolean;
19+
adaptiveStream?: boolean;
20+
21+
/**
22+
* enable Dynacast, off by default. With Dynacast dynamically pauses
23+
* video layers that are not being consumed by any subscribers, significantly
24+
* reducing publishing CPU and bandwidth usage.
25+
*/
26+
dynacast?: boolean;
2027

2128
/**
2229
* default options to use when capturing user's audio
@@ -68,16 +75,21 @@ export interface ConnectOptions extends CreateLocalTracksOptions {
6875
autoSubscribe?: boolean;
6976

7077
/**
71-
* automatically manage quality of subscribed video tracks, subscribe to the
72-
* an appropriate resolution based on the size of the video elements that tracks
73-
* are attached to.
74-
*
75-
* also observes the visibility of attached tracks and pauses receiving data
76-
* if they are not visible.
77-
*
78+
* see [[RoomOptions.adaptiveStream]]
79+
*/
80+
adaptiveStream?: boolean;
81+
82+
/**
83+
* alias for adaptiveStream
84+
* @deprecated
7885
*/
7986
autoManageVideo?: boolean;
8087

88+
/**
89+
* see [[RoomOptions.dynacast]]
90+
*/
91+
dynacast?: boolean;
92+
8193
/** configures LiveKit internal log level */
8294
logLevel?: LogLevel | LogLevelDesc;
8395

0 commit comments

Comments
 (0)