Skip to content

Commit

Permalink
feat: update room streaming flow (#71)
Browse files Browse the repository at this point in the history
* feat: handle auto reconnect and get client name from track

* feat: getStreamByTrackId and mapping client id and name

* fix: remove _onAllowedRenegotiation listener

* feat: add client id and name from draftstream

* feat: get browser name util

* feat: bandwidth controller module

* refactor: use private class field

* feat: video observer module

* feat: update peer to support simulcast, and video observer

* fix: wrong variable returned

* fix: bind this  for observer instances

* feat: add validation must be an instance of MediaStreamTrack

* feat: add replace track to peer instance type

* doc: update the room readme

- add more methods on peer object
- add more properties on stream object

* doc: update stream properties description

* feat: add more response data from api

* doc: update information related to client

* doc: update addStream name example

* refactor: remove unused methodss

- remove getVideoOutboundTracksLength()
- remove getAudioOutboundTracksLength()
- remove getAvailable()
- remove getOutbountStats()

* doc: remove observer video methods from doc

* fix: update scalabilityMode to L3T2
  • Loading branch information
faiq-naufal authored Nov 1, 2023
1 parent dcd81d9 commit ceb43a2
Show file tree
Hide file tree
Showing 14 changed files with 794 additions and 57 deletions.
24 changes: 24 additions & 0 deletions packages/internal/utils/get-browser-name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export const CHROME = 'Chrome',
FIREFOX = 'Firefox',
SAFARI = 'Safari',
OPERA = 'Opera',
IE = 'IE',
EDGE = 'Edge'

export const getBrowserName = () => {
if (
navigator.userAgent.includes(CHROME) &&
navigator.userAgent.includes(EDGE)
)
return EDGE
if (
navigator.userAgent.includes(CHROME) &&
navigator.userAgent.includes(OPERA)
)
return OPERA
if (navigator.userAgent.includes(CHROME)) return CHROME
if (navigator.userAgent.includes(FIREFOX)) return FIREFOX
if (navigator.userAgent.includes(SAFARI)) return SAFARI
if (navigator.userAgent.includes(IE)) return IE
return null
}
35 changes: 29 additions & 6 deletions packages/room/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ const client = await room.createClient(roomData.data.roomId);
// create a new peer and automatically open connection to the remote peer
const peer = await room.createPeer(roomData.data.roomId, client.data.clientId);

// create a new data channel server for broadcasting data to all connected clients
await room.createDataChannel(roomData.data.roomId, 'my-channel')

// listen for a specific room event
room.on(room.event.STREAM_AVAILABLE, function () {
// handle event
Expand Down Expand Up @@ -65,9 +68,9 @@ await room.endRoom(roomData.data.roomId);

A method to get the room data. It expects a `roomId` as a parameter. This method will return a promise.

- `room.createClient(roomId: string, clientId?: string | undefined)`
- `room.createClient(roomId: string, config?: object)`

A method to create and register a new client to the room. It expects two parameters. The `roomId` is required. If the client prefers to set their own client ID, the second client ID parameter can be set. This method will return a promise.
A method to create and register a new client to the room. It expects two parameters. The `roomId` is required. The second parameter is an optional config to set a custom client data. This method will return a promise.

- `room.setClientName(roomId: string, clientId: string, clientName: string)`

Expand Down Expand Up @@ -110,6 +113,8 @@ const mediaStream = await navigator.mediaDevices.getUserMedia({ video: true, aud

// Add the user media input stream to the peer
peer.addStream(mediaStream.id, {
clientId: client.data.clientId,
name: 'Client A stream',
origin: 'local', // local | remote
source: 'media', // media | screen
mediaStream: mediaStream,
Expand All @@ -119,6 +124,8 @@ const displayScreen = await navigator.mediaDevices.getDisplayMedia({ video: true

// Add the display screen media input stream to the peer
peer.addStream(displayScreen.id, {
clientId: client.data.clientId,
name: 'Screen by Client A',
origin: 'local', // local | remote
source: 'screen', // media | screen
mediaStream: displayScreen,
Expand Down Expand Up @@ -148,6 +155,14 @@ peer.disconnect();

#### Methods

- `peer.getClientId()`

A method to get the client ID currently used by the peer

- `peer.getRoomId()`

A method to get the room ID currently used by the peer

- `peer.getPeerConnection()`

A method to get a [RTCPeerConnection](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection) object. This object is useful to get current client connection state and listen for events related to the WebRTC connection.
Expand All @@ -163,6 +178,8 @@ peer.disconnect();
- `peer.addStream(key, data)`

- Required data:
- **clientId**: string,
- **name**: string,
- **origin**: 'local' | 'remote'
- **source**: 'media' | 'screen'
- **mediaStream**: MediaStream
Expand All @@ -179,7 +196,11 @@ peer.disconnect();

- `peer.getStream(key)`

A method to get and retrieve a specific stream object. It requires a key to find the data.
A method to get and retrieve a specific stream object based on key provided.

- `peer.getStreamByTrackId(trackId: string)`

A method to get and retrieve a specific stream object based on track ID provided.

- `peer.getTotalStreams()`

Expand Down Expand Up @@ -207,16 +228,18 @@ peer.disconnect();

- `peer.replaceTrack(track: MediaStreamTrack)`

A method to replace the track currently being sent by sender with a new MediaStreamTrack
A method to replace the track currently being sent by sender with a new MediaStreamTrack.

### Stream object

The stream object is an object created and stored after the method `peer.addStream()` is called. This object is mainly used to store the data for a specific MediaStream added by `peer.addStream()` method. We can say that a single stream is the representative of a single participant. Because of that, it's important to call the addStream method in order to create a local participant and establish a peer connection with remote peer.
The stream object is an object created and stored after the method `peer.addStream()` is called. This object is mainly used to store the data for a specific MediaStream added by `peer.addStream()` method. We can say a single stream object is the representative of a single participant or we can call it a **client**.

#### Properties

The stream object holds read-only properties based on the data client provided when creating a new stream.
- **id**: The ID of the stream
- **id**: The ID or key identifier of the stream
- **clientId**: The ID of the client which transceive this specific stream.
- **name**: The name or label for identification purpose.
- **origin**: The origin of the stream. The value is between a `local` or `remote`
- **source**: The source of the stream. MediaStream from `getUserMedia()` should set a **media** source and the one from `getDisplayMedia()` should set a **screen** source.
- **mediaStream**: The MediaStream object
Expand Down
4 changes: 4 additions & 0 deletions packages/room/api/api-types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@ export declare namespace RoomAPIType {
audio_red: number
video: number
video_high: number
video_high_pixels: number
video_mid: number
video_mid_pixels: number
video_low: number
video_low_pixels: number
initial_bandwidth: number
}

Expand All @@ -56,6 +59,7 @@ export declare namespace RoomAPIType {
data: {
room_id: string
name: string
bitrates_config: Bitrates
}
}

Expand Down
22 changes: 22 additions & 0 deletions packages/room/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ export const createApi = ({ fetcher }) => {
audioRed: bitrates.audio_red || 0,
video: bitrates.video || 0,
videoHigh: bitrates.video_high || 0,
videoHighPixels: bitrates.video_high_pixels || 0,
videoMid: bitrates.video_mid || 0,
videoMidPixels: bitrates.video_mid_pixels || 0,
videoLow: bitrates.video_low || 0,
videoLowPixels: bitrates.video_low_pixels || 0,
initialBandwidth: bitrates.initial_bandwidth || 0,
},
},
Expand All @@ -54,6 +57,7 @@ export const createApi = ({ fetcher }) => {
const response = await this._fetcher.get(`/rooms/${roomId}`)

const data = response.data || {}
const bitrates = data.bitrates_config || {}

const room = {
code: response.code || 500,
Expand All @@ -62,6 +66,18 @@ export const createApi = ({ fetcher }) => {
data: {
roomId: data.room_id || '',
roomName: data.name || '',
bitrates: {
audio: bitrates.audio || 0,
audioRed: bitrates.audio_red || 0,
video: bitrates.video || 0,
videoHigh: bitrates.video_high || 0,
videoHighPixels: bitrates.video_high_pixels || 0,
videoMid: bitrates.video_mid || 0,
videoMidPixels: bitrates.video_mid_pixels || 0,
videoLow: bitrates.video_low || 0,
videoLowPixels: bitrates.video_low_pixels || 0,
initialBandwidth: bitrates.initial_bandwidth || 0,
},
},
}

Expand Down Expand Up @@ -112,8 +128,11 @@ export const createApi = ({ fetcher }) => {
audioRed: bitrates.audio_red || 0,
video: bitrates.video || 0,
videoHigh: bitrates.video_high || 0,
videoHighPixels: bitrates.video_high_pixels || 0,
videoMid: bitrates.video_mid || 0,
videoMidPixels: bitrates.video_mid_pixels || 0,
videoLow: bitrates.video_low || 0,
videoLowPixels: bitrates.video_low_pixels || 0,
initialBandwidth: bitrates.initial_bandwidth || 0,
},
},
Expand Down Expand Up @@ -166,8 +185,11 @@ export const createApi = ({ fetcher }) => {
audioRed: bitrates.audio_red || 0,
video: bitrates.video || 0,
videoHigh: bitrates.video_high || 0,
videoHighPixels: bitrates.video_high_pixels || 0,
videoMid: bitrates.video_mid || 0,
videoMidPixels: bitrates.video_mid_pixels || 0,
videoLow: bitrates.video_low || 0,
videoLowPixels: bitrates.video_low_pixels || 0,
initialBandwidth: bitrates.initial_bandwidth || 0,
},
},
Expand Down
51 changes: 51 additions & 0 deletions packages/room/bandwidth-controller/bandwidth-controller-types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { RoomPeerType } from '../peer/peer-types.js'
import type { RoomEventType } from '../event/event-types.js'

export declare namespace RoomBwControllerType {
type BwControllerDependencies = {
event: RoomEventType.InstanceEvent
peer: RoomPeerType.InstancePeer
}

type TrackInboundStats = {
kind: string
source: string
bytesReceived: number
bitrate: number
lastUpdated: number
}

type TrackOutboundStats = {
rid: string
kind: string
bytesSent: number
bitrates: number
lastUpdated: number
}

type PublisherStatsData = {
available_outgoing_bitrate: number
quality_limitation_reason: string
}

type PublisherStatsReport = {
type: string
data: PublisherStatsData
}

type InboundTracks = {
[key: string]: TrackInboundStats
}

type OutboundTracks = {
[key: string]: TrackOutboundStats
}

type RTCInboundRtpStreamStatsExtra = RTCInboundRtpStreamStats & {
trackIdentifier: string
}

type RTCOutboundRtpStreamStatsExtra = RTCOutboundRtpStreamStats & {
qualityLimitationReason?: string
}
}
Loading

0 comments on commit ceb43a2

Please sign in to comment.