@reactoo/watchtogether-sdk-js 2.6.79 → 2.6.81

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.
@@ -790,7 +790,7 @@
790
790
  fetch('./affiliation/country/affiliation-data.json').then(response => response.json())
791
791
  .then(countries => {
792
792
  participants.filter(p => p).forEach(participant => {
793
- const continentCountries = continent ? countries.filter(country => country.continent === continent) : countries;
793
+ const continentCountries = continent ? countries.filter(country => country.data.continent === continent) : countries;
794
794
  const randomCountry = continentCountries[Math.floor(Math.random()*continentCountries.length)];
795
795
 
796
796
  participant.sdkInstance.user.getUserSelf()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactoo/watchtogether-sdk-js",
3
- "version": "2.6.79",
3
+ "version": "2.6.81",
4
4
  "description": "Javascript SDK for Reactoo",
5
5
  "main": "src/index.js",
6
6
  "unpkg": "dist/watchtogether-sdk.min.js",
@@ -1584,7 +1584,7 @@ class RoomSession {
1584
1584
  : this.simulcastMode;
1585
1585
  const failedAttempts = p.webrtcStuff.simulcastSwitchFailedAttempts[mid] || 0;
1586
1586
 
1587
- if((simulcastMode === 'auto' && !manualSelectedSubstream) || failedAttempts > 3) {
1587
+ if((simulcastMode === 'auto' && !manualSelectedSubstream) /* || failedAttempts > 3 */) {
1588
1588
  // do nothing
1589
1589
  }
1590
1590
 
@@ -3020,7 +3020,7 @@ class RoomSession {
3020
3020
  this._abortController.signal.removeEventListener('abort', abortResponse);
3021
3021
  this.ws.removeEventListener('message', parseResponse);
3022
3022
  reject('timeout');
3023
- }, 2000);
3023
+ }, 5000);
3024
3024
 
3025
3025
  this.sendMessage(handleId, {
3026
3026
  "body": {
@@ -1,200 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <title>The Example</title>
6
- <script src="./audiocontrols.js"></script>
7
- <script src="../../dist/watchtogether-sdk.js"></script>
8
- </head>
9
- <body style="padding: 0; margin: 0; margin-top: 20px">
10
-
11
- <div style="display: flex">
12
- <div style="flex: 0 0 50%; text-align: center">
13
- <div id="input-container" style="display: none">
14
- <textarea id="input" style="width: 80%; height: 500px; padding: 0"></textarea>
15
- <br>
16
- <button onclick="applyAudioControlsObject()" style="width: 80%">Apply audio controls object</button>
17
- </div>
18
- </div>
19
- <div style="flex: 0 0 50%; text-align: center">
20
- <select id="audio-devices" style="width: 80%" onchange="selectedAudioDeviceId = this.value"></select>
21
- <br>
22
- <select id="video-devices" style="width: 80%" onchange="selectedVideoDeviceId = this.value"></select>
23
- <button style="width: 80%" onclick="getDevicesPermissionAndEnumerateDevices()">Enumerate devices</button>
24
-
25
- <br><br><br><br>
26
-
27
- <div id="stream-container" style="display: none">
28
- <div style="width: 80%; margin-left: auto; margin-right: auto">
29
- <video id="stream" style="width: 100%; height: 300px; background-color: black; object-fit: contain" autoplay></video>
30
- </div>
31
- <button style="width: 80%" onclick="attachStream()">Attach stream to video element</button>
32
- <br>OR<br>
33
- <label for="room-id">Room ID : </label>
34
- <input id="room-id" size="35" onchange="roomId = this.value">
35
- <button style="width: 80%" onclick="sendStreamToRoom()">Send stream to room</button>
36
- <br>
37
- <button id="producer-link" style="width: 80%" onclick="goToProducer()">Producer preview</button>
38
- </div>
39
- </div>
40
- </div>
41
-
42
- <script>
43
- let audioControlsObject = {
44
- enabled: true,
45
- gain: {
46
- value: 1,
47
- decibels: 0
48
- },
49
- equalizer: {
50
- lowshelf: {
51
- frequency: 220,
52
- gain: 0
53
- },
54
- peaking: {
55
- frequency: 2400,
56
- gain: 0,
57
- q: 0.3,
58
- qType: "low"
59
- },
60
- highshelf: {
61
- frequency: 12000,
62
- gain: 0
63
- }
64
- },
65
- compressor: {
66
- threshold: 0,
67
- ratio: 2,
68
- knee: 2,
69
- attack: 0.001,
70
- release: 0.15,
71
- speed: "medium"
72
- },
73
- delay: 0,
74
- };
75
-
76
- let roomId = "03159020-59a8-4d10-a801-8aef895141a3";
77
- let sdkInstance = null;
78
- let roomSession = null;
79
-
80
- let audioControls = null;
81
-
82
- let enumeratedAudioDevices = null;
83
- let enumeratedVideoDevices = null;
84
- let selectedAudioDeviceId = null;
85
- let selectedVideoDeviceId = null;
86
-
87
- const inputContainerElement = document.getElementById('input-container');
88
- const inputElement = document.getElementById('input');
89
- const audioDevicesSelectElement = document.getElementById("audio-devices");
90
- const videoDevicesSelectElement = document.getElementById("video-devices");
91
- const streamContainerElement = document.getElementById('stream-container');
92
- const streamElement = document.getElementById('stream');
93
- const roomIdInputElement = document.getElementById('room-id');
94
-
95
- document.addEventListener("DOMContentLoaded", function() {
96
- audioControls = new AudioControls();
97
- inputElement.value = JSON.stringify(audioControlsObject, null, 2);
98
- });
99
-
100
- function applyAudioControlsObject() {
101
- audioControlsObject = JSON.parse(inputElement.value);
102
- audioControls.setParametersFromAudioControlsObject(audioControlsObject);
103
- }
104
-
105
- function enumerateDevices() {
106
- enumeratedAudioDevices = [];
107
-
108
- return navigator.mediaDevices.enumerateDevices()
109
- .then(devices => {
110
- enumeratedAudioDevices = [];
111
- enumeratedVideoDevices = [];
112
-
113
- devices.forEach(device => {
114
- const deviceDetail = {
115
- id: device.deviceId,
116
- label: device.label
117
- };
118
-
119
- if (device.kind === 'audioinput') {
120
- enumeratedAudioDevices.push(deviceDetail);
121
- }
122
-
123
- if (device.kind === 'videoinput') {
124
- enumeratedVideoDevices.push(deviceDetail);
125
- }
126
- });
127
- });
128
- }
129
-
130
- function getUserMedia(audioDeviceId, videoDeviceId) {
131
- const constraints = {
132
- audio: audioDeviceId ? {deviceId: {exact: audioDeviceId}} : true,
133
- video: {frameRate: {ideal: 10, max: 20}, width: {ideal: 320, max: 480}, height: {ideal: 240, max: 360}}
134
- };
135
-
136
- if (videoDeviceId) {
137
- constraints.video.deviceId = {exact: videoDeviceId};
138
- }
139
-
140
- return navigator.mediaDevices.getUserMedia(constraints);
141
- }
142
-
143
- function getDevicesPermissionAndEnumerateDevices() {
144
- getUserMedia()
145
- .then(stream => stream.getTracks().forEach(key => stream.removeTrack(key)))
146
- .then(() => enumerateDevices())
147
- .then(() => {
148
- while (audioDevicesSelectElement.firstChild) {
149
- audioDevicesSelectElement.removeChild(audioDevicesSelectElement.lastChild);
150
- }
151
- while (videoDevicesSelectElement.firstChild) {
152
- videoDevicesSelectElement.removeChild(videoDevicesSelectElement.lastChild);
153
- }
154
-
155
- enumeratedAudioDevices.forEach(device => {
156
- const optionElement = document.createElement('option');
157
- optionElement.value = device.id;
158
- optionElement.innerHTML = device.label;
159
- audioDevicesSelectElement.appendChild(optionElement);
160
- });
161
- enumeratedVideoDevices.forEach(device => {
162
- const optionElement = document.createElement('option');
163
- optionElement.value = device.id;
164
- optionElement.innerHTML = device.label;
165
- videoDevicesSelectElement.appendChild(optionElement);
166
- });
167
-
168
- inputContainerElement.style.display = "block";
169
- streamContainerElement.style.display = "block";
170
-
171
- roomIdInputElement.value = roomId;
172
- });
173
- }
174
-
175
- function attachStream () {
176
- getUserMedia(selectedAudioDeviceId, selectedVideoDeviceId).then(stream => {
177
- streamElement.srcObject = audioControls.setStream(stream);
178
- });
179
- }
180
-
181
- function sendStreamToRoom () {
182
- getUserMedia(selectedAudioDeviceId, selectedVideoDeviceId).then(stream => {
183
- sdkInstance = WatchTogetherSDK({debug:true, storagePrefix: "user_1"})();
184
- sdkInstance.auth.deviceLogin("user_1")
185
- .then(() => sdkInstance.room.createSession({roomId}))
186
- .then(session => {
187
- roomSession = session;
188
- return Promise.all([session, session.connect()])
189
- })
190
- .then(([session, _]) => session.publishLocal(audioControls.setStream(stream), {getStreamIfEmpty: false}));
191
- });
192
- }
193
-
194
- function goToProducer() {
195
- window.open('https://producer.reactoo.com/#/detail/room-monitor/' + roomId, '_blank').focus();
196
- }
197
- </script>
198
-
199
- </body>
200
- </html>
@@ -1,230 +0,0 @@
1
- // https://createjs.com/docs/soundjs/files/soundjs_webaudio_WebAudioPlugin.js.html
2
- // https://mdn.github.io/webaudio-examples/compressor-example/
3
- // https://codepen.io/webciter/pen/WNbPyrY
4
-
5
- let ac = window.AudioContext || window.webkitAudioContext;
6
-
7
- class AudioControls {
8
-
9
- audioContext;
10
-
11
- eventListeners;
12
-
13
- streamSource;
14
- gainNode;
15
- equalizerNodes; // List of nodes
16
- compressorNode;
17
- delayNode;
18
- streamDestination;
19
-
20
- gainDefaultParameters = {
21
- gain: 1
22
- };
23
- // frequency - The middle of the frequency range getting a boost or an attenuation.
24
- // Q (only applied to peaking, others ignore it) - from 0.0001 to 1000 - The width of the frequency band. The greater the Q value, the smaller the frequency band.
25
- // gain - from -40 to 40 db - The boost, in dB, to be applied; if negative, it will be an attenuation.
26
- // type - must be read only
27
- equalizerDefaultParameters = [
28
- {frequency: 220, gain: 0, type: 'lowshelf'}, // Frequencies lower than the frequency get a boost, or an attenuation; frequencies over it are unchanged.
29
- {frequency: 2400, gain: 0, type: 'peaking', Q: 0.3}, // Frequencies inside the range get a boost or an attenuation; frequencies outside it are unchanged.
30
- {frequency: 12000, gain: 0, type: 'highshelf'} // Frequencies higher than the frequency get a boost or an attenuation; frequencies lower than it are unchanged
31
- ];
32
- compressorDefaultParameters = {
33
- threshold: 0, // from -100 to 0 0 - compression will start at 0db - no compression
34
- knee: 30, // from 0 to 40 0 - hard knee - no smooth transition to compression
35
- ratio: 2, // from 1 to 20 1 - ratio 1:1 will not affect anything
36
- attack: 0.001, // from 0 to 1 0 - no time required to reduce the gain by 10 dB
37
- release: 0.15, // from 0 to 1 0 - no time required to increase the gain by 10 dB
38
- };
39
- delayDefaultParameters = {
40
- delay: 0
41
- };
42
-
43
- constructor() {
44
- this.audioContext = new ac();
45
-
46
- this.streamDestination = this.audioContext.createMediaStreamDestination();
47
-
48
- this.delayNode = this.audioContext.createDelay(179);
49
- this.setDelay(this.delayDefaultParameters.delay);
50
- this.delayNode.connect(this.streamDestination);
51
-
52
- this.compressorNode = this.audioContext.createDynamicsCompressor();
53
- this.setCompressorParameters(this.compressorDefaultParameters);
54
- this.compressorNode.connect(this.delayNode);
55
-
56
- this.equalizerNodes = this.equalizerDefaultParameters.map( parameters => {
57
- const biquadFilter = this.audioContext.createBiquadFilter();
58
- biquadFilter.type = parameters.type;
59
-
60
- return biquadFilter;
61
- });
62
- this.equalizerDefaultParameters.forEach( parameters => {
63
- this.setEqualizerParameters(parameters);
64
- });
65
- this.equalizerNodes.forEach( (node, nodeIndex) => {
66
- if (nodeIndex < this.equalizerNodes.length - 1) {
67
- node.connect(this.equalizerNodes[nodeIndex + 1]);
68
- } else {
69
- node.connect(this.compressorNode);
70
- }
71
- });
72
-
73
- this.gainNode = this.audioContext.createGain();
74
- this.setGain(this.gainDefaultParameters.gain);
75
- this.gainNode.connect(this.equalizerNodes[0]);
76
-
77
- this.streamSource = null;
78
-
79
- this.eventListeners = {};
80
-
81
- document.body.addEventListener('click', () => {
82
- this.resume();
83
- }, { once: true });
84
- }
85
-
86
- emit (label, ...args) {
87
- let callbacks = this.eventListeners[label];
88
- if(callbacks) {
89
- callbacks.forEach(callback => callback.apply(null, args))
90
- }
91
- }
92
-
93
- addEventListener (event, fn) {
94
- if(!this.eventListeners[event]) {
95
- this.eventListeners[event] = []
96
- }
97
- this.eventListeners[event].push(fn);
98
- }
99
-
100
- removeEventListener (event, fn) {
101
- if(!this.eventListeners[event]) {
102
- return
103
- }
104
- let index = this.eventListeners[event].findIndex(listener => listener === fn);
105
- if(index > -1) {
106
- this.eventListeners[event].splice(index, 1);
107
- }
108
- }
109
-
110
- clearEventListeners () {
111
- for(let key in this.eventListeners) {
112
- this.eventListeners[key].length = 0;
113
- }
114
- }
115
-
116
- render() {
117
- this.drawId = setTimeout(() => {
118
- this.emit('compressorReduction', this.compressorNode.reduction);
119
- this.render();
120
- }, 1000 / 10)
121
- }
122
-
123
- startRenderLoop() {
124
- clearTimeout(this.drawId);
125
- this.render();
126
- }
127
-
128
- stopRenderLoop() {
129
- clearTimeout(this.drawId);
130
- }
131
-
132
- setStream(stream) {
133
- if (this.streamSource) {
134
- this.streamSource.disconnect(this.gainNode);
135
- }
136
-
137
- this.streamSource = this.audioContext.createMediaStreamSource(stream);
138
- this.streamSource.connect(this.gainNode);
139
-
140
- this.resume();
141
-
142
- // this.streamDestination.stream.getVideoTracks().forEach(t => this.streamDestination.stream.removeTrack(t));
143
- // stream.getVideoTracks().forEach(t => {
144
- // this.streamDestination.stream.addTrack(t)
145
- // });
146
- // return this.streamDestination.stream;
147
-
148
- const finalStream = new MediaStream();
149
-
150
- const [videotrack] = stream.getVideoTracks();
151
- if(videotrack) {
152
- finalStream.addTrack(videotrack);
153
- }
154
-
155
- const [audiotrack] = this.streamDestination.stream.getAudioTracks();
156
- if(audiotrack) {
157
- finalStream.addTrack(audiotrack);
158
- }
159
-
160
- // https://stackoverflow.com/a/63844077
161
- // new Audio().srcObject = stream;
162
- // new Audio().srcObject = finalStream;
163
-
164
- return finalStream;
165
- }
166
-
167
- resume() {
168
- if (this.audioContext.state === 'suspended') {
169
- this.audioContext.resume();
170
- this.startRenderLoop();
171
- }
172
- }
173
-
174
- setGain(gain) {
175
- this.gainNode.gain.setValueAtTime(gain, Math.floor(this.audioContext.currentTime));
176
- }
177
-
178
- setEqualizerParameters(equalizerParameters, nodeType) {
179
- const nodeIndex = ['lowshelf', 'peaking', 'highshelf'].findIndex(e => e === nodeType || e === equalizerParameters.type);
180
-
181
- if (nodeIndex !== -1) {
182
- ['frequency', 'gain', 'Q'].forEach( parameterName => {
183
- if (equalizerParameters.hasOwnProperty(parameterName) && equalizerParameters[parameterName] !== undefined) {
184
- this.equalizerNodes[nodeIndex][parameterName].value = equalizerParameters[parameterName];
185
- }
186
- });
187
- }
188
- }
189
-
190
- setCompressorParameters(compressorParameters) {
191
- ['threshold', 'knee', 'ratio', 'attack', 'release'].forEach( parameterName => {
192
- if (compressorParameters.hasOwnProperty(parameterName) && compressorParameters[parameterName] !== undefined) {
193
- this.compressorNode[parameterName].value = compressorParameters[parameterName];
194
- }
195
- });
196
- }
197
-
198
- setDelay(delay) {
199
- this.delayNode.delayTime.setValueAtTime(delay, Math.floor(this.audioContext.currentTime));
200
- }
201
-
202
- setParametersFromAudioControlsObject(audioControlsObject) {
203
- if (audioControlsObject.enabled) {
204
- this.setGain(audioControlsObject.gain.value);
205
- Object.keys(audioControlsObject.equalizer)
206
- .forEach(type => this.setEqualizerParameters(audioControlsObject.equalizer[type], type));
207
- this.setCompressorParameters(audioControlsObject.compressor);
208
- this.setDelay(audioControlsObject.delay);
209
- } else {
210
- this.setGain(this.gainDefaultParameters.gain);
211
- this.equalizerDefaultParameters
212
- .forEach( p => this.setEqualizerParameters(p));
213
- this.setCompressorParameters(this.compressorDefaultParameters);
214
- this.setDelay(0);
215
- }
216
- }
217
-
218
- destroy() {
219
- this.stopRenderLoop();
220
- this.streamSource.disconnect(this.gainNode);
221
- this.audioContext.close();
222
- }
223
- }
224
-
225
- // Uncomment this to use in VUE
226
- // export default {
227
- // install: function(Vue) {
228
- // Object.defineProperty(Vue.prototype, '$audiocontrols', { value: AudioControls });
229
- // }
230
- // }