Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit a3659b7

Browse files
Publish with RTCRtpTransceivers. (#498)
* Add a property to ConferenceClient to get PeerConnection. * Publish a stream with RTPTransceivers. * Allow publish with transceivers. * Add examples to design doc. * Update docs/design/owt_with_webrtc_apis.md Co-authored-by: Philip Giuliani <[email protected]>
1 parent 4dec44c commit a3659b7

File tree

6 files changed

+203
-69
lines changed

6 files changed

+203
-69
lines changed

docs/design/owt_with_webrtc_apis.md

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,71 @@
11
# OWT SDK with WebRTC APIs
22
## Introduction
33
OWT(Open WebRTC Toolkit) Client SDKs provide convenient APIs to create, publish, and subscribe streams. Most of these APIs are wrappers of WebRTC APIs with signaling support. It helps WebRTC beginners easily involve WebRTC technology into their applications without too much knowledge of WebRTC evolution and browser differences. As WebRTC 1.0 is moving to PR, which means it is quite stable, we are planning to expose more WebRTC APIs to developers to enable advanced and custom usages with OWT.
4-
## WebRTC APIs
5-
### RTCRtpTransceiver, RTCRtpSender, RTCRtpReceiver
6-
#### Potential Usages
4+
## Potential Usages
75
- Replace a track in the middle of a call.
86
- Set custom encoding parameters, perhaps for simulcast.
97
- Set preferred codecs.
108
- Disable or enable RTX / RED / FEC.
11-
#### API Changes
9+
## API Changes
1210
- A new member `rtpTransceivers` will be added to `TransportSettings`. It returns an array `RTCRtpReceiver`s for RTP transport.
1311
- A new member `transport` will be added to `Publication` and `Subscription`. Developers could get `RTPTransceiver`s from its `rtpTransceivers` property.
14-
- A new method `addTransceiver(DOMString trackKind, sequence<RTCRtpEncodingParameters> sendEncodings)` will be added to `ConferenceClient`. It invokes `RTCPeerConnection.addTransceiver(trackKind, {direction:inactive, sendEncodings:sendEncodings})`, returns an `RTCRtpTransceiver`. Please note that direction is `inactive` until a `publish` with return transceiver is called.
15-
- The second parameter of `ConferenceClient.publish` accepts an `RTCRtpTransceiver` created by `RTCPeerConnection.addTransceiver`. When this method is called, certain `RTCRtpTransceiver`'s direction is changed to `sendonly`, and its sender's `setStreams` is called with the first parameter's `mediaStream`.
16-
#### Server Requirements
12+
- A new member `peerConnection` will be added to `ConferenceClient` for developers to get the `PeerConnection`.
13+
- The second parameter of `ConferenceClient.publish` accepts an `RTCRtpTransceiver` created by `RTCPeerConnection.addTransceiver`. `RTCRtpTransceiver`s' direction must be `sendonly`, and its sender's `setStreams` is called with the first parameter's `mediaStream`.
14+
## Server Requirements
1715
- `addTransceiver` and new `publish` needs renegotiation support.
18-
#### Remarks
19-
- Every transceiver could be associated with at most one `Publication` or one `Subscription`.
16+
## Remarks
17+
- Every transceiver could be associated with at most one `Publication` or one `Subscription`.
18+
## Examples
19+
### Replace a video track
20+
```
21+
const transceivers = publication.transport.rtpTransceivers;
22+
for (const transceiver of transceivers) {
23+
if (transceiver.sender.track?.kind === 'video'){
24+
transceiver.sender.replaceTrack(newTrack);
25+
}
26+
}
27+
```
28+
29+
### Publish a stream with codec preferences
30+
```
31+
const codecCapabilities = RTCRtpSender.getCapabilities('video').codecs;
32+
// Reorder codecCapabilities or remove some items.
33+
const transceivers = [];
34+
for (const track of mediaStream.getTracks()) {
35+
const transceiver =
36+
conference.peerConnection.addTransceiver(track, {
37+
direction: 'sendonly',
38+
streams: [stream],
39+
});
40+
if (track.kind==='video'){
41+
transceiver.setCodecPreferences(codecCapabilities);
42+
}
43+
transceivers.push(transceiver);
44+
}
45+
const publication = await conference.publish(localStream, transceivers);
46+
```
47+
48+
49+
### Publish with a codec supports SVC.
50+
This example uses some WebRTC APIs may not be supported by all browsers.
51+
```
52+
const transceiver =
53+
conference.peerConnection.addTransceiver(track, {
54+
direction: 'sendonly',
55+
streams: [stream],
56+
sendEncodings: [
57+
{
58+
rid: 'q',
59+
scaleResolutionDownBy: 4.0,
60+
scalabilityMode: 'L1T3'
61+
},
62+
{
63+
rid: 'h',
64+
scaleResolutionDownBy: 2.0,
65+
scalabilityMode: 'L1T3'
66+
},
67+
{rid: 'f', scalabilityMode: 'L1T3'}
68+
],
69+
});
70+
const publication = await conference.publish(localStream, [transceiver]));
71+
```

docs/mdfiles/changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Change Log
44
* When subscribe a stream in conference mode, the subscribed MediaStream or BidirectionalStream is associated with a `Owt.Conference.Subscription` instead of a `Owt.Base.RemoteStream`. The `stream` property of a RemoteStream in conference mode is always undefined, while a new property `stream` is added to `Subscription`. It allows a RemoteStream to be subscribed multiple times, as well as subscribing audio and video tracks from different streams.
55
* Add a new property `transport` to `Publication` for getting `TransportSettings`.
66
* Add a new property `rtpTransceivers` to `TransportSettings` and `TransportConstraints`.
7+
* Add a new property `peerConnection` to `ConferenceClient`.
8+
* The second argument of `ConferenceClient.publish` could be a list of `RTCRtpTransceiver`s.
79
# 5.0
810
* Add WebTransport support for conference mode, see [this design doc](../../design/webtransport.md) for detailed information.
911
* All publications and subscriptions for the same conference use the same `PeerConnection`.

src/.eslintrc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{
55
"extends": ["eslint:recommended", "google", "webrtc"],
66
"parserOptions": {
7-
"ecmaVersion": 2018,
7+
"ecmaVersion": 2020,
88
"sourceType": "module"
99
},
1010
"rules": {

src/samples/conference/public/scripts/index.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
'use strict';
3030
var conference;
3131
var publicationGlobal;
32+
// Change to your sample server's URL if it's not deployed on the same machine
33+
// as this page.
34+
const serverUrlBase = undefined;
3235
const runSocketIOSample = function() {
3336

3437
let localStream;
@@ -124,7 +127,7 @@ const runSocketIOSample = function() {
124127
console.log('A new stream is added ', event.stream.id);
125128
isSelf = isSelf?isSelf:event.stream.id != publicationGlobal.id;
126129
subscribeForward && isSelf && subscribeAndRenderVideo(event.stream);
127-
mixStream(myRoom, event.stream.id, 'common');
130+
mixStream(myRoom, event.stream.id, 'common', serverUrlBase);
128131
event.stream.addEventListener('ended', () => {
129132
console.log(event.stream.id + ' is ended.');
130133
});
@@ -144,7 +147,7 @@ const runSocketIOSample = function() {
144147
myId = resp.self.id;
145148
myRoom = resp.id;
146149
if(mediaUrl){
147-
startStreamingIn(myRoom, mediaUrl);
150+
startStreamingIn(myRoom, mediaUrl, serverUrlBase);
148151
}
149152
if (isPublish !== 'false') {
150153
// audioConstraintsForMic
@@ -174,9 +177,22 @@ const runSocketIOSample = function() {
174177
mediaStream, new Owt.Base.StreamSourceInfo(
175178
'mic', 'camera'));
176179
$('.local video').get(0).srcObject = stream;
180+
// Publish with RTCRtpTransceivers.
181+
// const transceivers = [];
182+
// for (const track of mediaStream.getTracks()) {
183+
// transceivers.push(
184+
// conference.peerConnection.addTransceiver(track, {
185+
// direction: 'sendonly',
186+
// streams: [stream],
187+
// }));
188+
// }
189+
// publication =
190+
// await conference.publish(localStream, transceivers);
191+
192+
// Publish with options.
177193
conference.publish(localStream, publishOption).then(publication => {
178194
publicationGlobal = publication;
179-
mixStream(myRoom, publication.id, 'common')
195+
mixStream(myRoom, publication.id, 'common', serverUrlBase)
180196
publication.addEventListener('error', (err) => {
181197
console.log('Publication error: ' + err.error.message);
182198
});
@@ -216,7 +232,7 @@ const runSocketIOSample = function() {
216232
$p.appendTo($('body'));
217233
}
218234
});
219-
});
235+
}, serverUrlBase);
220236
};
221237
};
222238
window.onbeforeunload = function(event){

0 commit comments

Comments
 (0)