Skip to content

Commit 660e9a8

Browse files
authored
Merge pull request #197449 from chriswhilar/patch-41
Update manage-video-web.md
2 parents 9805432 + ab82efd commit 660e9a8

File tree

1 file changed

+91
-19
lines changed

1 file changed

+91
-19
lines changed

articles/communication-services/how-tos/calling-sdk/includes/manage-video/manage-video-web.md

Lines changed: 91 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -159,38 +159,67 @@ Whenever availability of a remote stream changes you can choose to destroy the w
159159
or keep them, but this will result in displaying blank video frame.
160160

161161
```js
162+
// Reference to the html's div where we would display a grid of all remote video stream from all participants.
163+
let remoteVideosGallery = document.getElementById('remoteVideosGallery');
164+
162165
subscribeToRemoteVideoStream = async (remoteVideoStream) => {
163-
// Create a video stream renderer for the remote video stream.
164-
let videoStreamRenderer = new VideoStreamRenderer(remoteVideoStream);
166+
let renderer = new VideoStreamRenderer(remoteVideoStream);
165167
let view;
166-
const remoteVideoContainer = document.getElementById('remoteVideoContainer');
167-
const renderVideo = async () => {
168+
let remoteVideoContainer = document.createElement('div');
169+
remoteVideoContainer.className = 'remote-video-container';
170+
171+
/**
172+
* isReceiving API is currently an @alpha feature. Do not use in production.
173+
* To use this api please use 'alpha' release of Azure Communication Services Calling Web SDK.
174+
*/
175+
let loadingSpinner = document.createElement('div');
176+
// See the css example below for styling the loading spinner.
177+
loadingSpinner.className = 'loading-spinner';
178+
remoteVideoStream.on('isReceivingChanged', () => {
168179
try {
169-
// Create a renderer view for the remote video stream.
170-
view = await videoStreamRenderer.createView();
171-
// Attach the renderer view to the UI.
172-
remoteVideoContainer.appendChild(view.target);
180+
if (remoteVideoStream.isAvailable) {
181+
const isReceiving = remoteVideoStream.isReceiving;
182+
const isLoadingSpinnerActive = remoteVideoContainer.contains(loadingSpinner);
183+
if (!isReceiving && !isLoadingSpinnerActive) {
184+
remoteVideoContainer.appendChild(loadingSpinner);
185+
} else if (isReceiving && isLoadingSpinnerActive) {
186+
remoteVideoContainer.removeChild(loadingSpinner);
187+
}
188+
}
173189
} catch (e) {
174-
console.warn(`Failed to createView, reason=${e.message}, code=${e.code}`);
190+
console.error(e);
175191
}
192+
});
193+
194+
const createView = async () => {
195+
// Create a renderer view for the remote video stream.
196+
view = await renderer.createView();
197+
// Attach the renderer view to the UI.
198+
remoteVideoContainer.appendChild(view.target);
199+
remoteVideosGallery.appendChild(remoteVideoContainer);
176200
}
177-
remoteVideoStream.on('isAvailableChanged', async () => {
178-
// Participant has switched video on.
179-
if (remoteVideoStream.isAvailable) {
180-
await renderVideo();
181201

182-
// Participant has switched video off.
183-
} else {
184-
if (view) {
202+
// Remote participant has switched video on/off
203+
remoteVideoStream.on('isAvailableChanged', async () => {
204+
try {
205+
if (remoteVideoStream.isAvailable) {
206+
await createView();
207+
} else {
185208
view.dispose();
186-
view = undefined;
209+
remoteVideosGallery.removeChild(remoteVideoContainer);
187210
}
211+
} catch (e) {
212+
console.error(e);
188213
}
189214
});
190215

191-
// Participant has video on initially.
216+
// Remote participant has video on initially.
192217
if (remoteVideoStream.isAvailable) {
193-
await renderVideo();
218+
try {
219+
await createView();
220+
} catch (e) {
221+
console.error(e);
222+
}
194223
}
195224

196225
console.log(`Initial stream size: height: ${remoteVideoStream.size.height}, width: ${remoteVideoStream.size.width}`);
@@ -200,6 +229,38 @@ subscribeToRemoteVideoStream = async (remoteVideoStream) => {
200229
}
201230
```
202231

232+
CSS for styling the loading spinner over the remote video stream.
233+
```css
234+
.remote-video-container {
235+
position: relative;
236+
}
237+
.loading-spinner {
238+
border: 12px solid #f3f3f3;
239+
border-radius: 50%;
240+
border-top: 12px solid #ca5010;
241+
width: 100px;
242+
height: 100px;
243+
-webkit-animation: spin 2s linear infinite; /* Safari */
244+
animation: spin 2s linear infinite;
245+
position: absolute;
246+
margin: auto;
247+
top: 0;
248+
bottom: 0;
249+
left: 0;
250+
right: 0;
251+
transform: translate(-50%, -50%);
252+
}
253+
@keyframes spin {
254+
0% { transform: rotate(0deg); }
255+
100% { transform: rotate(360deg); }
256+
}
257+
/* Safari */
258+
@-webkit-keyframes spin {
259+
0% { -webkit-transform: rotate(0deg); }
260+
100% { -webkit-transform: rotate(360deg); }
261+
}
262+
```
263+
203264
### Remote video stream properties
204265

205266
Remote video streams have the following properties:
@@ -222,6 +283,17 @@ const type: MediaStreamType = remoteVideoStream.mediaStreamType;
222283
const isAvailable: boolean = remoteVideoStream.isAvailable;
223284
```
224285

286+
- `isReceiving`:
287+
- ***This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. To use this api please use 'alpha' release of Azure Communication Services Calling Web SDK.***
288+
- Will inform the application if remote video stream data is being received. Such cases are:
289+
- When the remote mobile participant has their video on and they put the browser app in the background, they will stop sending video stream data until the app is brought back to the foreground.
290+
- When the remote participant has their video on and they have bad network connectivity and video is cutting off / lagging
291+
- This feature improves the user experience for rendering remote video streams.
292+
- You can display a loading spinner over the remote video stream when isReceiving flag changes to false. You don't have to do a loading spinner, you can do anything you desire, but a loading spinner is the most common usage
293+
```js
294+
const isReceiving: boolean = remoteVideoStream.isReceiving;
295+
```
296+
225297
- `size`: The stream size. The higher the stream size, the better the video quality.
226298

227299
```js

0 commit comments

Comments
 (0)