Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 2.3.0 #327

Merged
merged 69 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
12cbbec
Outside of browser environment
sirknightj Oct 1, 2023
752eaf4
Remove Buffer
sirknightj Oct 1, 2023
6331efc
Remove unnecessary import
sirknightj Oct 2, 2023
d37bb0b
Increase max package size
sirknightj Oct 2, 2023
373983a
Remove _
sirknightj Oct 2, 2023
a93d771
Add options allowing for fine-grained control of sending and receivin…
sirknightj Sep 29, 2023
a17d06a
Add description
sirknightj Sep 29, 2023
f043e57
Add presets
sirknightj Sep 29, 2023
20072a7
Fix wrong method name
sirknightj Sep 29, 2023
08c093f
Remove debugging artifacts
sirknightj Sep 29, 2023
60d6c6d
Remove extra newlines
sirknightj Sep 29, 2023
d879653
Extract to common method
sirknightj Oct 2, 2023
b530868
sample: Add manual JoinStorageSession button
sirknightj Sep 1, 2023
0569350
sample: Adjust labels
sirknightj Sep 1, 2023
8f0b763
master role
sirknightj Sep 1, 2023
80db54b
sample: move the connected check to after the SDP answer is sent
sirknightj Sep 1, 2023
2b7e848
Add correlationId to sdp answer for joinStorageSession
sirknightj Oct 11, 2023
5c872be
100% code coverage in the unit tests
sirknightj Oct 11, 2023
445596f
Increase package size
sirknightj Oct 11, 2023
8f105b0
Remove testing artifact
sirknightj Oct 11, 2023
2534f56
Update README for correlationId
sirknightj Oct 12, 2023
cf4f6ac
Fix boolean flag
sirknightj Oct 18, 2023
c9ef64e
Adjust css
sirknightj Oct 18, 2023
cc7dea9
Disable datachannel for WebRTC ingestion and remove remote-view in in…
sirknightj Oct 18, 2023
8725bed
Adjust stop button color
sirknightj Oct 18, 2023
c949b57
reset storage client on next run
sirknightj Oct 18, 2023
57bc54e
reset storage client on next run
sirknightj Oct 18, 2023
5201fcf
Adjust comment for correlationId
sirknightj Oct 19, 2023
4f8e5bd
Bump @babel/traverse from 7.21.4 to 7.23.2
dependabot[bot] Oct 19, 2023
80de306
Bump react-devtools-core from 4.27.6 to 4.28.4
dependabot[bot] Oct 21, 2023
93dc4e2
Bump version
sirknightj Nov 7, 2023
391f4bc
Bump package lock
sirknightj Nov 7, 2023
4a1fa08
data channel benchmarking message
niyatim23 Oct 16, 2023
d90a288
additional logs
niyatim23 Oct 26, 2023
0df8110
granularity in time-to-first-frame
niyatim23 Oct 30, 2023
a87df3c
master and viewer metrics timeline chart
niyatim23 Nov 8, 2023
e6258e7
signaling metrics viewer + master breakdown
niyatim23 Nov 9, 2023
022efe1
color coded, dynamic height adjustment, dynamic dataTable row addition
niyatim23 Nov 10, 2023
cb4a92f
connectAsViewer, enable non-json messages, enable viewing them in mes…
niyatim23 Nov 14, 2023
b8fd215
set timelineChartTestLength to 20
niyatim23 Nov 14, 2023
299ec50
cleanup 1
niyatim23 Nov 14, 2023
69eff77
pr cleanup as per comments
niyatim23 Nov 20, 2023
f8bac09
adding a comment
niyatim23 Nov 20, 2023
97e56a1
readme update
niyatim23 Nov 20, 2023
c65e404
rename timestamp
niyatim23 Dec 8, 2023
9667fe4
update the readme
niyatim23 Dec 18, 2023
eed81a2
rename timestamps
niyatim23 Dec 18, 2023
cf0ce35
decouple from dqp
niyatim23 Dec 20, 2023
2a4b3ba
rename
niyatim23 Dec 20, 2023
81d062c
DQP enhacement and bug fixes
disa6302 Dec 14, 2023
2c184b9
Rebase to include profiling chart
disa6302 Dec 27, 2023
18146f6
Use metrics object data
disa6302 Dec 27, 2023
982e57c
Bump follow-redirects from 1.15.2 to 1.15.5
dependabot[bot] Feb 6, 2024
c89b25f
Bump ip from 1.1.8 to 1.1.9
dependabot[bot] Feb 22, 2024
d7613fa
Merge
sirknightj Mar 26, 2024
32fbf22
Dependabot - Bump multiple dependencies (#303)
sirknightj Mar 28, 2024
a379e60
CI for publishing develop application (#304)
sirknightj Apr 3, 2024
f36fd1b
Separate connecting to signaling vs signing the request metric and pr…
sirknightj Apr 4, 2024
5d12481
Update README.md
sirknightj Apr 5, 2024
420df88
fix typo (#308)
stefankiesz Apr 15, 2024
66365fe
global.WebSocket -> WebSocket (#311)
sirknightj Apr 16, 2024
256b024
Bump tar from 6.1.13 to 6.2.1 (#312)
sirknightj Apr 17, 2024
fa49653
Sample: Master Cleanup (#313)
sirknightj Apr 18, 2024
ff4f691
Move endpoint field to the advanced section (#314)
sirknightj Apr 18, 2024
36e86fd
Bump ws from 8.14.2 to 8.17.1 (#319)
dependabot[bot] Jul 20, 2024
073a452
Bump braces, react-native-codegen and fork-ts-checker-webpack-plugin …
dependabot[bot] Jul 20, 2024
bb09596
Bump fast-xml-parser from 4.2.5 to 4.4.1 (#324)
dependabot[bot] Aug 5, 2024
f651682
Sample change: WebRTC ingestion with multi-viewer support (#326)
sirknightj Aug 5, 2024
6d5588a
Bump the version from 2.2.1 to 2.3.0 (#328)
sirknightj Aug 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/develop-publish-gh-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Deploy Action WebRTC JS SDK

on:
push:
branches:
- develop
jobs:
publish-ubuntu-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@master
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: 16
- name: Install dependencies
run: npm install
- name: Run release
run: npm run release
- name: Deploy to Github pages
uses: JamesIves/[email protected]
with:
folder: dist
branch: gh-pages
target-folder: develop
clean: true
31 changes: 31 additions & 0 deletions .github/workflows/master-publish-gh-pages-and-npm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Deploy and Publish Action WebRTC JS SDK

on:
push:
branches:
- master
jobs:
publish-ubuntu-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@master
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: 16
- name: Install dependencies
run: npm install
- name: Run release
run: npm run release
- name: Deploy to Github pages
uses: JamesIves/[email protected]
with:
folder: dist
branch: gh-pages
clean: true
clean-exclude: develop/
- name: Deploy to npm packages
uses: JS-DevTools/npm-publish@v1
with:
token: '${{ secrets.NPM_TOKEN }}'
31 changes: 0 additions & 31 deletions .github/workflows/publish.yml

This file was deleted.

78 changes: 42 additions & 36 deletions README.md

Large diffs are not rendered by default.

217 changes: 217 additions & 0 deletions examples/answerer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
class Answerer {
/**
* Represents a peer connection in the "answerer" or "callee" role.
* @constructor
* @param {RTCConfiguration} rtcPeerConnectionConfiguration - The configuration for the RTCPeerConnection.
* @param {MediaStream} localMediaStream - The local media stream to send to the remote client.
* @param {RTCSessionDescriptionInit} offer - The offer for the peer connection received from the remote client.
* @param {string} remoteClientId - The signaling ClientID of the remote client.
* @param {SignalingClient} signalingClient - Kinesis Video Streams WebRTC Signaling client.
* @param {boolean} trickleICE - Whether to use trickle ICE.
* @param {boolean} createDataChannel - Whether to create a data channel.
* @param {string} [loggingPrefix=''] - Prefix log messages will have.
* @param {function(RTCIceCandidate): boolean} [outboundIceCandidateFilterFn=candidate => true]
* Callback function invoked when an ICE candidate is generated by this peer.
* Return true if this candidate should be sent to the remote peer.
* If no function is provided, no candidates will be filtered and all generated candidates will be sent.
* @param {function(string): boolean} [inboundIceCandidateFilterFn=candidate => true]
* Callback function invoked when an ICE candidate is received through signaling
* from the remote peer. Return true if this candidate should be added to this peer connection.
* If no function is provided, no candidates will be filtered and all candidates received from remote will
* be added to this peer connection.
* @param {function(MediaStream[]): void} [mediaStreamsUpdated=mediaStreams => {}]
* Invoked when the remote peer adds a track to the peer connection.
* Nothing happens if no function is provided.
* @param {function(string): void} [dataChannelMessageReceived=dataChannelMessage => {}]
* Invoked when the remote peer sends a message over the data channel.
* Only will get invoked if createDataChannel is true.
* Nothing happens if no function is provided.
*/
constructor(
rtcPeerConnectionConfiguration,
localMediaStream,
offer,
remoteClientId,
signalingClient,
trickleICE,
createDataChannel,
loggingPrefix = '',
outboundIceCandidateFilterFn = candidate => true,
inboundIceCandidateFilterFn = candidate => true,
mediaStreamsUpdated = mediaStreams => {},
dataChannelMessageReceived = (dataChannelMessage) => {},
) {
this._configuration = rtcPeerConnectionConfiguration;
this._mediaStream = localMediaStream;
this._remoteClientId = remoteClientId;
this._offer = offer;
this._signalingClient = signalingClient;
this._trickleICE = trickleICE;
this._createDataChannel = createDataChannel;
this._loggingPrefix = loggingPrefix;
this._outboundIceCandidateFilterFn = outboundIceCandidateFilterFn;
this._inboundIceCandidateFilterFn = inboundIceCandidateFilterFn;
this._onMediaStreamsUpdated = mediaStreamsUpdated;
this._dataChannelMessageReceived = dataChannelMessageReceived;

this._dataChannel = null;
this._peerConnection = null;
}

// Must be called first.
// Create the PeerConnection and binds it to the Signaling client.
// It will send back an answer given the provided offer and media to send back.
// Optionally, if configured, the data channel will be opened.
init = async () => {
this._peerConnection = new RTCPeerConnection(this._configuration);

if (this._createDataChannel) {
this._peerConnection.ondatachannel = event => {
this._dataChannel = event.channel;
event.channel.onmessage = this._dataChannelMessageReceived;
};
}

this._addIceCandidate = async (candidate, remoteClientId) => {
if (remoteClientId !== this._remoteClientId) {
// All ICE candidates received over signaling will be received via this callback.
// Ignore ICE candidates not directed for this PeerConnection (when multiple
// viewer participants are connecting to the same signaling channel).
return;
}

console.log(this._loggingPrefix, `Received ICE candidate from ${remoteClientId || 'remote'}`);
console.debug(this._loggingPrefix, 'ICE candidate:', candidate);

if (this._inboundIceCandidateFilterFn(candidate)) {
// Add the ICE candidate received from the client to the peer connection
this._peerConnection.addIceCandidate(candidate);
} else {
console.log(this._loggingPrefix, `Candidate rejected through filter. Not adding candidate from ${remoteClientId || 'remote'}.`);
}
};

this._signalingClient.on('iceCandidate', this._addIceCandidate);

this._peerConnection.addEventListener('icecandidate', ({ candidate }) => {
// `candidate` will be the empty string if the event indicates that there are no further candidates
// to come in this generation, or null if all ICE gathering on all transports is complete.
// https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/icecandidate_event
if (candidate) {
console.log(this._loggingPrefix, 'Generated ICE candidate for', this._remoteClientId || 'remote');
console.debug(this._loggingPrefix, 'ICE candidate:', candidate);

// When trickle ICE is enabled, send the ICE candidates as they are generated.
if (this._trickleICE) {
if (this._outboundIceCandidateFilterFn(candidate)) {
console.log(this._loggingPrefix, 'Sending ICE candidate to', this._remoteClientId || 'remote');
this._signalingClient.sendIceCandidate(candidate, this._remoteClientId);
} else {
console.log(this._loggingPrefix, 'Not sending ICE candidate to', this._remoteClientId || 'remote');
}
}
} else {
console.log(this._loggingPrefix, 'All ICE candidates have been generated for', this._remoteClientId || 'remote');

// When trickle ICE is disabled, send the answer now that all the ICE candidates have been generated.
// NOTE: gathering all the ICE candidates can take a long time. It is recommended to use trickle ICE.
if (!this._trickleICE) {
console.log(this._loggingPrefix, 'Sending SDP answer to', this._remoteClientId || 'remote');
const correlationId = randomString();
console.debug('SDP answer:', this._peerConnection.localDescription, 'correlationId:', correlationId);
this._signalingClient.sendSdpAnswer(this._peerConnection.localDescription, this._remoteClientId, correlationId);
}
}
});

// We receive this event when the remote peer adds a new track to the PeerConnection
// https://webrtc.org/getting-started/remote-streams#adding_remote_tracks
this._peerConnection.addEventListener('track', event => {
console.log(this._loggingPrefix, 'Received track from', this._remoteClientId || 'remote', 'with track id:', event?.streams[0]?.id ?? '[Error retrieving track ID]');
this._onMediaStreamsUpdated(event.streams);
});

// If there's no video/audio, this._mediaStream will be null. So, we should skip adding the tracks from it.
if (this._mediaStream) {
this._mediaStream.getTracks().forEach(track => this._peerConnection.addTrack(track, this._mediaStream));
}

await this._peerConnection.setRemoteDescription(this._offer);

// Create an SDP answer to send back to the client
console.log(this._loggingPrefix, 'Creating SDP answer for', this._remoteClientId || 'remote');
await this._peerConnection.setLocalDescription(
await this._peerConnection.createAnswer({
offerToReceiveAudio: true,
offerToReceiveVideo: true,
}),
);

// When trickle ICE is enabled, send the answer now and then send ICE candidates as they are generated. Otherwise wait on the ICE candidates.
if (this._trickleICE) {
console.log(this._loggingPrefix, 'Sending SDP answer to', this._remoteClientId || 'remote');
const correlationId = randomString();
console.debug(this._loggingPrefix, 'SDP answer:', this._peerConnection.localDescription, 'correlationId:', correlationId);
this._signalingClient.sendSdpAnswer(this._peerConnection.localDescription, this._remoteClientId, correlationId);
}
console.log(this._loggingPrefix, 'Generating ICE candidates for', this._remoteClientId || 'remote');
};

// Returns true if the data channel was created and is currently open.
// Only available after init()
isDataChannelOpen = () => {
if (!this._peerConnection) {
throw 'Init must be called first!';
}
return this._createDataChannel && this._dataChannel.readyState === 'open';
};

// Sends a message over the data channel
// It will throw an error if the data channel is not currently open
// Only available after init()
sendDataChannelMessage = message => {
if (!this._peerConnection) {
throw 'Init must be called first!';
}
if (!this.isDataChannelOpen) {
throw 'The data channel is not open!';
}
this._dataChannel.send(message);
};

// Adds an ice candidate to the PeerConnection
// Only available after init()
addIceCandidate = candidate => {
if (!this._peerConnection) {
throw 'Init must be called first!';
}
this._peerConnection.addIceCandidate(candidate);
};

// Close the resources opened by this answerer.
// This will close the peer connection, unbind from the signaling client,
// and close the data channel (if any). This will not close the signaling
// client.
// Only available after init()
close = () => {
if (!this._peerConnection) {
throw 'Init must be called first!';
}
this._peerConnection.close();

this._signalingClient.removeListener('iceCandidate', this._addIceCandidate);

if (this._dataChannel) {
this._dataChannel.close();
}
};

// Return the peer connection this answerer is using
// Only available after init()
getPeerConnection = () => {
if (!this._peerConnection) {
throw 'Init must be called first!';
}
return this._peerConnection;
};
}
Loading
Loading