Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Meer informatie over het beheren van videogesprekken met de Azure Communication Services SDKS. We leren hoe u het ontvangen en verzenden van video's binnen een gesprek kunt beheren.
Vereisten
- Een Azure-account met een actief abonnement. Gratis een account maken
- Een uitgerolde Communication Services-resource. Een Communication Services-resource maken.
- Een gebruikerstoegangstoken om de aanroepende client in te schakelen. Zie Toegangstokens maken en beheren voor meer informatie.
- Optioneel: Voltooi de quickstart om spraakgesprekken toe te voegen aan uw toepassing
Installeer de SDK
Gebruik de npm install
opdracht om de Common and Calling SDK voor Azure Communication Services voor JavaScript te installeren:
npm install @azure/communication-common --save
npm install @azure/communication-calling --save
Vereiste objecten initialiseren
Een CallClient
exemplaar is vereist voor de meeste aanroepbewerkingen. Wanneer u een nieuw CallClient
exemplaar maakt, kunt u deze configureren met aangepaste opties, zoals een Logger
exemplaar.
Met het CallClient
exemplaar kunt u een CallAgent
exemplaar maken door het createCallAgent
aan te roepen. Deze methode retourneert asynchroon een CallAgent
exemplaarobject.
De createCallAgent
methode gebruikt CommunicationTokenCredential
als argument. Het accepteert een toegangstoken van een gebruiker.
U kunt de getDeviceManager
methode op het CallClient
exemplaar gebruiken om toegang te krijgen tot deviceManager
.
const { CallClient } = require('@azure/communication-calling');
const { AzureCommunicationTokenCredential} = require('@azure/communication-common');
const { AzureLogger, setLogLevel } = require("@azure/logger");
// Set the logger's log level
setLogLevel('verbose');
// Redirect log output to console, file, buffer, REST API, or whatever location you want
AzureLogger.log = (...args) => {
console.log(...args); // Redirect log output to console
};
const userToken = '<USER_TOKEN>';
callClient = new CallClient(options);
const tokenCredential = new AzureCommunicationTokenCredential(userToken);
const callAgent = await callClient.createCallAgent(tokenCredential, {displayName: 'optional Azure Communication Services user name'});
const deviceManager = await callClient.getDeviceManager()
SDK-connectiviteit met Microsoft-infrastructuur beheren
De Call Agent
instantie helpt u bij het beheren van gesprekken (om deel te nemen aan oproepen of ze te starten). Als u wilt werken met uw aanroepende SDK, moet u verbinding maken met de Microsoft-infrastructuur om meldingen van binnenkomende oproepen te ontvangen en andere gespreksgegevens te coördineren. Uw Call Agent
heeft twee mogelijke statussen:
Verbonden - Een connectionStatus-waarde van Call Agent
betekent dat de client-SDK verbonden is en meldingen kan ontvangen van de Microsoft-infrastructuur.
Verbinding verbroken - Een Call Agent
connectionStatus-waarde van Disconnected
geeft aan dat er een probleem is dat voorkomt dat de SDK correct verbinding maakt.
Call Agent
moet opnieuw worden gemaakt.
-
invalidToken
: Als een token is verlopen of ongeldig is, verbreekt deCall Agent
instantie de verbinding met deze fout. -
connectionIssue
: als er een probleem is met de client die verbinding maakt met de Microsoft-infrastructuur, wordt na veel nieuwe pogingenCall Agent
de foutconnectionIssue
weergegeven.
U kunt controleren of uw lokale Call Agent
verbinding heeft met de Microsoft-infrastructuur door de huidige waarde van connectionState
de eigenschap te controleren. Tijdens een actieve oproep kunt u naar de connectionStateChanged
gebeurtenis luisteren om te bepalen of Call Agent
van Verbonden naar Verbroken is gewijzigd.
const connectionState = callAgentInstance.connectionState;
console.log(connectionState); // it may return either of 'Connected' | 'Disconnected'
const connectionStateCallback = (args) => {
console.log(args); // it will return an object with oldState and newState, each of having a value of either of 'Connected' | 'Disconnected'
// it will also return reason, either of 'invalidToken' | 'connectionIssue'
}
callAgentInstance.on('connectionStateChanged', connectionStateCallback);
Apparaatbeheer
Als u video wilt gaan gebruiken met de Calling SDK, moet u apparaten kunnen beheren. Met apparaten kunt u bepalen wat audio en video naar het gesprek verzendt.
Gebruik de deviceManager
opdracht om lokale apparaten op te sommen die uw audio- en videostreams in een gesprek kunnen verzenden. U kunt ook toestemming deviceManager
vragen voor toegang tot de microfoons en camera's van het lokale apparaat.
U kunt toegang krijgen deviceManager
door de methode callClient.getDeviceManager()
aan te roepen.
const deviceManager = await callClient.getDeviceManager();
Lokale apparaten ophalen
Voor toegang tot lokale apparaten kunt u de deviceManager
enumeratiemethoden getCameras()
en getMicrophones
gebruiken. Deze methoden zijn asynchrone acties.
// Get a list of available video devices for use.
const localCameras = await deviceManager.getCameras(); // [VideoDeviceInfo, VideoDeviceInfo...]
// Get a list of available microphone devices for use.
const localMicrophones = await deviceManager.getMicrophones(); // [AudioDeviceInfo, AudioDeviceInfo...]
// Get a list of available speaker devices for use.
const localSpeakers = await deviceManager.getSpeakers(); // [AudioDeviceInfo, AudioDeviceInfo...]
De standaardapparaten instellen
Zodra u weet welke apparaten beschikbaar zijn voor gebruik, kunt u standaardapparaten instellen voor microfoon, luidspreker en camera. Als de standaardinstellingen van de client niet zijn ingesteld, gebruikt de Communication Services SDK standaardinstellingen voor het besturingssysteem.
Microfoon
Toegang tot het gebruikte apparaat
// Get the microphone device that is being used.
const defaultMicrophone = deviceManager.selectedMicrophone;
Het apparaat instellen voor gebruik
// Set the microphone device to use.
await deviceManager.selectMicrophone(localMicrophones[0]);
Spreker
Toegang tot het gebruikte apparaat
// Get the speaker device that is being used.
const defaultSpeaker = deviceManager.selectedSpeaker;
Het apparaat instellen voor gebruik
// Set the speaker device to use.
await deviceManager.selectSpeaker(localSpeakers[0]);
Fototoestel
Toegang tot het gebruikte apparaat
// Get the camera device that is being used.
const defaultSpeaker = deviceManager.selectedSpeaker;
Het apparaat instellen voor gebruik
// Set the speaker device to use.
await deviceManager.selectSpeaker(localCameras[0]);
Elk CallAgent
kan een eigen microfoon en luidsprekers kiezen op de bijbehorende DeviceManager
. We raden aan dat verschillende CallAgents
verschillende microfoons en luidsprekers gebruiken. Ze mogen niet dezelfde microfoons of luidsprekers delen. Als het delen plaatsvindt, kan UFD (Microphone User Facing Diagnostics) worden geactiveerd en werkt de microfoon niet meer, afhankelijk van de browser en het besturingssysteem.
Lokale video-stream
Als gebruikers video in een gesprek willen verzenden, moet u een LocalVideoStream
object maken.
const localVideoStream = new LocalVideoStream(camera);
De camera die als parameter wordt doorgegeven, is een VideoDeviceInfo
object dat door de deviceManager.getCameras()
methode wordt geretourneerd.
A LocalVideoStream
heeft de volgende eigenschappen:
source
is de apparaatgegevens.const source = localVideoStream.source;
mediaStreamType
kan zijnVideo
,ScreenSharing
ofRawMedia
.const type: MediaStreamType = localVideoStream.mediaStreamType;
Voorbeeld van lokale camera
U kunt deviceManager
en VideoStreamRenderer
gebruiken om streams van uw lokale camera weer te geven.
Nadat u LocalVideoStream
hebt gemaakt, kunt u het gebruiken om VideoStreamRenderer
in te stellen. Zodra u de VideoStreamRenderer
hebt gemaakt, roept u de methode createView()
aan om een weergave te krijgen die u als subelement aan uw pagina kunt toevoegen.
Deze stream wordt niet naar andere deelnemers verzonden. Het is een lokale preview-feed.
// To start viewing local camera preview
const cameras = await deviceManager.getCameras();
const camera = cameras[0];
const localVideoStream = new LocalVideoStream(camera);
const videoStreamRenderer = new VideoStreamRenderer(localVideoStream);
const view = await videoStreamRenderer.createView();
htmlElement.appendChild(view.target);
De lokale preview stoppen
Als u de lokale preview-aanroep wilt stoppen, verwijdert u de weergave die is afgeleid van de VideoStreamRenderer
.
Nadat de VideoStreamRenderer is verwijderd, verwijdert u de weergave uit de HTML-structuur door de removeChild()
methode aan te roepen vanuit het DOM-knooppunt dat uw voorbeeld bevat.
// To stop viewing local camera preview
view.dispose();
htmlElement.removeChild(view.target);
Toestemming vragen voor camera en microfoon
Een toepassing kan de camera of microfoon niet zonder machtigingen gebruiken. U kunt deviceManager gebruiken om een gebruiker te vragen om camera- en/of microfoonmachtigingen toe te kennen:
const result = await deviceManager.askDevicePermission({audio: true, video: true});
Zodra de belofte is opgelost, wordt de methode geretourneerd met een DeviceAccess
object dat aangeeft of audio
en video
machtigingen zijn verleend:
console.log(result.audio);
console.log(result.video);
Opmerkingen
-
videoDevicesUpdated
gebeurtenis wordt geactiveerd wanneer videoapparaten zijn aangesloten/losgekoppeld. -
audioDevicesUpdated
gebeurtenis wordt geactiveerd wanneer audioapparaten zijn aangesloten. - Wanneer u
DeviceManager
voor het eerst aanmaakt, weet het niets met betrekking tot apparaten als er nog geen toestemmingen zijn verleend. De apparaatnaam is in eerste instantie leeg en bevat geen gedetailleerde apparaatgegevens. U moetDeviceManager.askPermission()
oproepen, waarbij om apparaattoegang voor de gebruiker wordt gevraagd. Wanneer de gebruiker toegang toestaat, leert de apparaatbeheerder over de apparaten op het systeem, werkt het de lijsten met apparaten bij en verzendt het deaudioDevicesUpdated
envideoDevicesUpdated
gebeurtenissen. Als een gebruiker de pagina vernieuwt en een apparaatbeheerder maakt, krijgt de apparaatbeheerder informatie over apparaten omdat de gebruiker eerder toegang heeft verleend. Het heeft zijn apparaatlijsten aanvankelijk gevuld en het zendt geenaudioDevicesUpdated
- ofvideoDevicesUpdated
-events uit. - Opsomming/selectie van luidsprekers wordt niet ondersteund in Android Chrome, iOS Safari en macOS Safari.
Een gesprek plaatsen met videocamera
Belangrijk
Momenteel wordt slechts één uitgaande lokale videostream ondersteund.
Als u een videogesprek wilt plaatsen, moet u lokale camera's opsommen met behulp van de getCameras()
methode in deviceManager
.
Nadat u een camera hebt geselecteerd, gebruikt u deze om een LocalVideoStream
exemplaar te maken.
Geef het door binnen videoOptions
als een item binnen de localVideoStream
array aan de CallAgent
startCall
methode.
const deviceManager = await callClient.getDeviceManager();
const cameras = await deviceManager.getCameras();
const camera = cameras[0]
const localVideoStream = new LocalVideoStream(camera);
const placeCallOptions = {videoOptions: {localVideoStreams:[localVideoStream]}};
const userCallee = { communicationUserId: '<ACS_USER_ID>' }
const call = callAgent.startCall([userCallee], placeCallOptions);
- U kunt ook deelnemen aan een gesprek met video met
CallAgent.join()
API en video accepteren en aanroepen metCall.Accept()
API. - Wanneer uw oproep verbinding maakt, wordt er automatisch een videostream van de geselecteerde camera naar de andere deelnemer verzonden.
Lokale video starten en stoppen tijdens een gesprek
Video starten
Als u een video wilt starten tijdens een gesprek, moet u camera's opsommen met behulp van de getCameras
methode voor het deviceManager
object.
Maak vervolgens een nieuw exemplaar van LocalVideoStream
met de gewenste camera en geef het LocalVideoStream
object door aan de startVideo
methode van een bestaand aanroepobject:
const deviceManager = await callClient.getDeviceManager();
const cameras = await deviceManager.getCameras();
const camera = cameras[0]
const localVideoStream = new LocalVideoStream(camera);
await call.startVideo(localVideoStream);
Video stoppen
Nadat u succesvol bent begonnen met het verzenden van video, wordt een LocalVideoStream
exemplaar van het type Video
toegevoegd aan de localVideoStreams
verzameling van een oproepexemplaar.
De videostream zoeken in het gespreksobject
const localVideoStream = call.localVideoStreams.find( (stream) => { return stream.mediaStreamType === 'Video'} );
Stop de lokale video Om de lokale video te stoppen tijdens een gesprek, geeft u het localVideoStream
exemplaar dat voor video wordt gebruikt aan de stopVideo-methode van de Call
.
await call.stopVideo(localVideoStream);
U kunt wisselen naar een ander cameratoestel terwijl u een actieve LocalVideoStream hebt door switchSource
op die LocalVideoStream
instantie aan te roepen.
const cameras = await callClient.getDeviceManager().getCameras();
const camera = cameras[1];
localVideoStream.switchSource(camera);
Als het opgegeven videoapparaat niet beschikbaar is:
- Als uw video tijdens een gesprek is uitgeschakeld en u de video start met
call.startVideo()
, veroorzaakt deze methode eenSourceUnavailableError
en wordt een gebruikersgerichte diagnostischecameraStartFailed
ingesteld op waar. - Een aanroep van de
localVideoStream.switchSource()
methode zorgt ervoor datcameraStartFailed
deze wordt ingesteld op true. Onze handleiding voor gespreksdiagnose bevat aanvullende informatie over het diagnosticeren van problemen met betrekking tot oproepen.
Als u wilt controleren of de lokale video is ingeschakeld of uitgeschakeld, kunt u de Call
methode isLocalVideoStarted
gebruiken, die waar of onwaar retourneert:
// Check if local video is on or off
call.isLocalVideoStarted;
Als u wilt luisteren naar wijzigingen in de lokale video, kunt u zich abonneren en afmelden voor de gebeurtenis isLocalVideoStartedChanged:
// Subscribe to local video event
call.on('isLocalVideoStartedChanged', () => {
// Callback();
});
// Unsubscribe from local video event
call.off('isLocalVideoStartedChanged', () => {
// Callback();
});
Scherm delen starten en stoppen tijdens een gesprek
Als u het delen van het scherm tijdens een gesprek wilt starten, kunt u de asynchrone methode startScreenSharing()
voor een Call
object gebruiken:
Schermdeling starten
// Start screen sharing
await call.startScreenSharing();
Notitie
Het verzenden van schermshare wordt alleen ondersteund voor desktopbrowsers.
Zoek de schermdeling in de verzameling LocalVideoStream
Nadat u schermdeling succesvol hebt gestart, wordt een LocalVideoStream
exemplaar van het type ScreenSharing
toegevoegd aan de localVideoStreams
collectie op het aanroep-exemplaar.
const localVideoStream = call.localVideoStreams.find( (stream) => { return stream.mediaStreamType === 'ScreenSharing'} );
Stoppen met scherm delen
Als u het delen van het scherm tijdens een aanroep wilt stoppen, kunt u asynchrone API stoptScreenSharing gebruiken:
// Stop screen sharing
await call.stopScreenSharing();
De status van het delen van het scherm controleren
Als u wilt controleren of het delen van het scherm is ingeschakeld of uitgeschakeld, kunt u isScreenSharingOn-API gebruiken, die waar of onwaar retourneert:
// Check if screen sharing is on or off
call.isScreenSharingOn;
Als u wilt luisteren naar wijzigingen in de schermshare, kunt u zich abonneren en afmelden voor de gebeurtenis isScreenSharingOnChanged:
// Subscribe to screen share event
call.on('isScreenSharingOnChanged', () => {
// Callback();
});
// Unsubscribe from screen share event
call.off('isScreenSharingOnChanged', () => {
// Callback();
});
Belangrijk
Deze functie van Azure Communication Services is momenteel beschikbaar als preview-versie. Functies in preview zijn openbaar beschikbaar en kunnen worden gebruikt door alle nieuwe en bestaande Microsoft-klanten.
Preview-API's en SDK's worden aangeboden zonder een service level agreement. U wordt aangeraden deze niet te gebruiken voor productieworkloads. Bepaalde functies worden mogelijk niet ondersteund of mogelijkheden zijn mogelijk beperkt.
Zie Aanvullende gebruiksvoorwaarden voor Microsoft Azure Previewsvoor meer informatie.
De openbare preview van lokale schermdelen is beschikbaar als onderdeel van versie 1.15.1-beta.1+.
Voorbeeld van lokale schermshare
U kunt een VideoStreamRenderer
bestand gebruiken om streams te genereren vanuit uw lokale schermshare, zodat u kunt zien wat u verzendt als een stream voor het delen van schermen.
// To start viewing local screen share preview
await call.startScreenSharing();
const localScreenSharingStream = call.localVideoStreams.find( (stream) => { return stream.mediaStreamType === 'ScreenSharing' });
const videoStreamRenderer = new VideoStreamRenderer(localScreenSharingStream);
const view = await videoStreamRenderer.createView();
htmlElement.appendChild(view.target);
// To stop viewing local screen share preview.
await call.stopScreenSharing();
view.dispose();
htmlElement.removeChild(view.target);
// Screen sharing can also be stopped by clicking on the native browser's "Stop sharing" button.
// The isScreenSharingOnChanged event will be triggered where you can check the value of call.isScreenSharingOn.
// If the value is false, then that means screen sharing is turned off and so we can go ahead and dispose the screen share preview.
// This event is also triggered for the case when stopping screen sharing via Call.stopScreenSharing() API.
call.on('isScreenSharingOnChanged', () => {
if (!call.isScreenSharingOn) {
view.dispose();
htmlElement.removeChild(view.target);
}
});
Video-/schermen van externe deelnemers weergeven
Als u een video of een scherm van een externe deelnemer wilt weergeven, is de eerste stap om een referentie naar de RemoteVideoStream te verkrijgen die u wilt weergeven.
U kunt alleen een externe deelnemer weergeven door de matrix- of videostream (videoStreams
) van de RemoteParticipant
. De verzameling externe deelnemers wordt geopend via het Call
object.
const remoteVideoStream = call.remoteParticipants[0].videoStreams[0];
const streamType = remoteVideoStream.mediaStreamType;
Als u wilt weergeven RemoteVideoStream
, moet u zich abonneren op de isAvailableChanged
gebeurtenis. Als de isAvailable
eigenschap wordt gewijzigd naar true
, verzendt een externe deelnemer een videostream.
Maak daarna een nieuw exemplaar van VideoStreamRenderer
en maak vervolgens een nieuw VideoStreamRendererView
exemplaar met behulp van de asynchrone createView
methode. Vervolgens kunt u een ui-element koppelen view.target
.
Wanneer de beschikbaarheid van een externe stream verandert, kunt u het geheel VideoStreamRenderer
of een specifiek VideoStreamRendererView
bestand vernietigen. Als u besluit deze te behouden, wordt in de weergave een leeg videoframe weergegeven.
// Reference to the html's div where we would display a grid of all remote video stream from all participants.
let remoteVideosGallery = document.getElementById('remoteVideosGallery');
subscribeToRemoteVideoStream = async (remoteVideoStream) => {
let renderer = new VideoStreamRenderer(remoteVideoStream);
let view;
let remoteVideoContainer = document.createElement('div');
remoteVideoContainer.className = 'remote-video-container';
let loadingSpinner = document.createElement('div');
// See the css example below for styling the loading spinner.
loadingSpinner.className = 'loading-spinner';
remoteVideoStream.on('isReceivingChanged', () => {
try {
if (remoteVideoStream.isAvailable) {
const isReceiving = remoteVideoStream.isReceiving;
const isLoadingSpinnerActive = remoteVideoContainer.contains(loadingSpinner);
if (!isReceiving && !isLoadingSpinnerActive) {
remoteVideoContainer.appendChild(loadingSpinner);
} else if (isReceiving && isLoadingSpinnerActive) {
remoteVideoContainer.removeChild(loadingSpinner);
}
}
} catch (e) {
console.error(e);
}
});
const createView = async () => {
// Create a renderer view for the remote video stream.
view = await renderer.createView();
// Attach the renderer view to the UI.
remoteVideoContainer.appendChild(view.target);
remoteVideosGallery.appendChild(remoteVideoContainer);
}
// Remote participant has switched video on/off
remoteVideoStream.on('isAvailableChanged', async () => {
try {
if (remoteVideoStream.isAvailable) {
await createView();
} else {
view.dispose();
remoteVideosGallery.removeChild(remoteVideoContainer);
}
} catch (e) {
console.error(e);
}
});
// Remote participant has video on initially.
if (remoteVideoStream.isAvailable) {
try {
await createView();
} catch (e) {
console.error(e);
}
}
console.log(`Initial stream size: height: ${remoteVideoStream.size.height}, width: ${remoteVideoStream.size.width}`);
remoteVideoStream.on('sizeChanged', () => {
console.log(`Remote video stream size changed: new height: ${remoteVideoStream.size.height}, new width: ${remoteVideoStream.size.width}`);
});
}
CSS voor het stylen van de laadspinner via de externe videostream.
.remote-video-container {
position: relative;
}
.loading-spinner {
border: 12px solid #f3f3f3;
border-radius: 50%;
border-top: 12px solid #ca5010;
width: 100px;
height: 100px;
-webkit-animation: spin 2s linear infinite; /* Safari */
animation: spin 2s linear infinite;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
transform: translate(-50%, -50%);
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Safari */
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
Externe videokwaliteit
De Azure Communication Services WebJS SDK biedt een functie met de naam Optimal Video Count (OVC), vanaf versie 1.15.1.
Gebruik deze functie om toepassingen tijdens runtime te informeren over hoeveel binnenkomende video's van verschillende deelnemers optimaal kunnen worden weergegeven op een bepaald moment in een groepsgesprek van twee (2) of meer deelnemers.
Met deze functie wordt een eigenschap optimalVideoCount
weergegeven die dynamisch wordt gewijzigd tijdens het aanroepen op basis van de netwerk- en hardwaremogelijkheden van een lokaal eindpunt. De waarde van optimalVideoCount
details hoeveel video's van verschillende deelnemerstoepassing op een bepaald moment moeten worden weergegeven. Toepassingen moeten deze wijzigingen afhandelen en het aantal weergegeven video's dienovereenkomstig bijwerken naar de aanbeveling. Er is een debounceperiode (ongeveer tien (10) seconden) tussen elke update.
Gebruik
De optimalVideoCount
functie is een oproepfunctie. U moet verwijzen naar de functie OptimalVideoCount
via de feature
methode van het Call
object.
Vervolgens kunt u een listener instellen via de on
methode die OptimalVideoCountCallFeature
moet worden gewaarschuwd wanneer de optimalVideoCount wordt gewijzigd. Als u zich wilt afmelden voor de wijzigingen, kunt u de off
methode aanroepen.
Het huidige maximum aantal binnenkomende video's dat kan worden weergegeven, is 16. Om 16 binnenkomende video's goed te ondersteunen, heeft de computer minimaal 16 GB RAM en een vier (4) kern of een hogere CPU nodig die kleiner is dan drie (3) jaar oud.
const optimalVideoCountFeature = call.feature(Features.OptimalVideoCount);
optimalVideoCountFeature.on('optimalVideoCountChanged', () => {
const localOptimalVideoCountVariable = optimalVideoCountFeature.optimalVideoCount;
})
Voorbeeldgebruik: Uw toepassing abonneert zich op wijzigingen van het optimale aantal video's in groepsgesprekken. Een wijziging in het optimale aantal video's wordt verwerkt door een nieuwe renderermethode createView
te maken of weergaven dispose
te verwijderen en de indeling van de toepassing dienovereenkomstig bij te werken.
Eigenschappen van videostream op afstand
Externe videostreams hebben de volgende eigenschappen:
const id: number = remoteVideoStream.id;
-
id
: De ID van een externe videostream.
const type: MediaStreamType = remoteVideoStream.mediaStreamType;
-
mediaStreamType
: Kan zijnVideo
ofScreenSharing
.
const isAvailable: boolean = remoteVideoStream.isAvailable;
-
isAvailable
: Hiermee definieert u of een eindpunt van een externe deelnemer actief een stream verzendt.
const isReceiving: boolean = remoteVideoStream.isReceiving;
isReceiving
:Informeert de toepassing als externe videostreamgegevens worden ontvangen of niet.
De vlag wordt naar
false
verplaatst in de volgende scenario's:- Een externe deelnemer die de mobiele browser gebruikt, zet de browser-app op de achtergrond.
- Een externe deelnemer of de gebruiker die de video ontvangt, heeft een netwerkprobleem dat de videokwaliteit drastisch beïnvloedt.
- Een externe deelnemer die zich in macOS/iOS Safari bevindt, selecteert 'Onderbreken' in de adresbalk.
- Een externe deelnemer heeft een netwerkonderbreking.
- Een deelnemer op afstand op een mobiel apparaat sluit of beëindigt de browser.
- Een externe deelnemer op mobiel of desktop vergrendelt het apparaat. Dit scenario is ook van toepassing als de externe deelnemer een desktopcomputer gebruikt en deze in de slaapstand gaat.
De vlag wordt naar
true
verplaatst in de volgende scenario's:- Een externe deelnemer die zich in de mobiele browser bevindt en de browser op de achtergrond heeft, brengt deze terug naar voorgrond.
- Een externe deelnemer die zich in macOS/iOS Safari bevindt, selecteert Hervatten in de adresbalk nadat de video is onderbroken.
- Een externe deelnemer maakt opnieuw verbinding met het netwerk na een tijdelijke verbroken verbinding.
- Een deelnemer op afstand op een mobiel apparaat ontgrendelt zijn/haar apparaat en keert terug naar het gesprek in de browser van de mobiele telefoon.
Deze functie verbetert de gebruikerservaring voor het weergeven van externe videostreams.
U kunt een laadspinner weergeven via de externe videostream wanneer de vlag isReceiving verandert in false. U hoeft geen laadspinner te implementeren, maar een laadspinner is het meest voorkomende gebruik voor een betere gebruikerservaring.
const size: StreamSize = remoteVideoStream.size;
size
: De streamgrootte met informatie over de breedte en hoogte van de video.
VideoStreamRenderer-methoden en -eigenschappen
await videoStreamRenderer.createView();
Maak een VideoStreamRendererView
exemplaar dat kan worden gekoppeld in de gebruikersinterface van de toepassing om de externe videostream weer te geven, gebruik een asynchrone createView()
methode, deze wordt omgezet wanneer stream gereed is om weer te geven en retourneert een object met target
een eigenschap die het element vertegenwoordigt video
dat overal in de DOM-structuur kan worden ingevoegd.
videoStreamRenderer.dispose();
Verwijder videoStreamRenderer
en alle bijbehorende VideoStreamRendererView
exemplaren.
VideoStreamRendererView-methoden en -eigenschappen
Wanneer u een VideoStreamRendererView
maakt, kunt u de scalingMode
en isMirrored
eigenschappen opgeven.
scalingMode
kan zijn Stretch
, Crop
of Fit
. Als isMirrored
is gespecificeerd, wordt de gerenderde stream verticaal gespiegeld.
const videoStreamRendererView: VideoStreamRendererView = await videoStreamRenderer.createView({ scalingMode, isMirrored });
Elk VideoStreamRendererView
exemplaar heeft een target
eigenschap die het renderingoppervlak vertegenwoordigt. Koppel deze eigenschap in de gebruikersinterface van de toepassing:
htmlElement.appendChild(view.target);
U kunt bijwerken scalingMode
door de updateScalingMode
methode aan te roepen:
view.updateScalingMode('Crop');
Videostreams verzenden vanaf twee verschillende camera's, in dezelfde oproep vanaf hetzelfde desktopapparaat.
Belangrijk
Deze functie van Azure Communication Services is momenteel beschikbaar als preview-versie. Functies in preview zijn openbaar beschikbaar en kunnen worden gebruikt door alle nieuwe en bestaande Microsoft-klanten.
Preview-API's en SDK's worden aangeboden zonder een service level agreement. U wordt aangeraden deze niet te gebruiken voor productieworkloads. Bepaalde functies worden mogelijk niet ondersteund of mogelijkheden zijn mogelijk beperkt.
Zie Aanvullende gebruiksvoorwaarden voor Microsoft Azure Previewsvoor meer informatie.
Het verzenden van videostreams vanaf twee verschillende camera's in dezelfde oproep wordt ondersteund als onderdeel van versie 1.17.1-beta.1+ op desktop ondersteunde browsers.
U kunt videostreams vanaf twee verschillende camera's verzenden vanuit één tabblad/app in de desktopbrowser, in dezelfde aanroep, met het volgende codefragment:
// Create your first CallAgent with identity A
const callClient1 = new CallClient();
const callAgent1 = await callClient1.createCallAgent(tokenCredentialA);
const deviceManager1 = await callClient1.getDeviceManager();
// Create your second CallAgent with identity B
const callClient2 = new CallClient();
const callAgent2 = await callClient2.createCallAgent(tokenCredentialB);
const deviceManager2 = await callClient2.getDeviceManager();
// Join the call with your first CallAgent
const camera1 = await deviceManager1.getCameras()[0];
const callObj1 = callAgent1.join({ groupId: ‘123’}, { videoOptions: { localVideoStreams: [new LocalVideoStream(camera1)] } });
// Join the same call with your second CallAgent and make it use a different camera
const camera2 = (await deviceManager2.getCameras()).filter((camera) => { return camera !== camera1 })[0];
const callObj2 = callAgent2.join({ groupId: '123' }, { videoOptions: { localVideoStreams: [new LocalVideoStream(camera2)] } });
//Mute the microphone and speakers of your second CallAgent’s Call, so that there is no echos/noises.
await callObj2.muteIncomingAudio();
await callObj2.mute();
Beperkingen:
- Het verzenden van videostreams moet worden uitgevoerd met twee verschillende
CallAgent
exemplaren met behulp van verschillende identiteiten. Het codefragment toont twee aanroepagents die worden gebruikt, elk met een eigen aanroepobject. - In het codevoorbeeld nemen beide CallAgents deel aan dezelfde aanroep (dezelfde aanroep-id's). U kunt ook deelnemen aan verschillende gesprekken met elke agent en één video verzenden tijdens één gesprek en een andere video in de andere oproep.
- Het verzenden van dezelfde camera in beide CallAgents wordt niet ondersteund. Ze moeten twee verschillende camera's zijn.
- Het verzenden van twee verschillende camera's met één CallAgent wordt momenteel niet ondersteund.
- Op macOS Safari kunnen video-effecten die een achtergrondvervaging creëren (van @azure/communication-effects)) alleen worden toegepast op één camera en niet op beide tegelijkertijd.
Installeer de SDK
Zoek je projectniveau build.gradle
bestand en voeg mavenCentral()
toe aan de lijst van repositories onder buildscript
en allprojects
.
buildscript {
repositories {
...
mavenCentral()
...
}
}
allprojects {
repositories {
...
mavenCentral()
...
}
}
Voeg vervolgens in het bestand op moduleniveau build.gradle
de volgende regels toe aan de dependencies
sectie:
dependencies {
...
implementation 'com.azure.android:azure-communication-calling:1.0.0'
...
}
De vereiste objecten initialiseren
Als u een CallAgent
exemplaar wilt maken, moet u de createCallAgent
methode voor een CallClient
exemplaar aanroepen. Hiermee wordt asynchroon een CallAgent
exemplaarobject geretourneerd.
De createCallAgent
methode neemt CommunicationUserCredential
als argument, wat een toegangstoken inkapselt.
Om toegang tot DeviceManager
te krijgen, moet u eerst een callAgent
instantie maken. Vervolgens kunt u de CallClient.getDeviceManager
methode gebruiken om op te halen DeviceManager
.
String userToken = '<user token>';
CallClient callClient = new CallClient();
CommunicationTokenCredential tokenCredential = new CommunicationTokenCredential(userToken);
android.content.Context appContext = this.getApplicationContext(); // From within an activity, for instance
CallAgent callAgent = callClient.createCallAgent(appContext, tokenCredential).get();
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
Als u een weergavenaam voor de aanroeper wilt instellen, gebruikt u deze alternatieve methode:
String userToken = '<user token>';
CallClient callClient = new CallClient();
CommunicationTokenCredential tokenCredential = new CommunicationTokenCredential(userToken);
android.content.Context appContext = this.getApplicationContext(); // From within an activity, for instance
CallAgentOptions callAgentOptions = new CallAgentOptions();
callAgentOptions.setDisplayName("Alice Bob");
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
CallAgent callAgent = callClient.createCallAgent(appContext, tokenCredential, callAgentOptions).get();
Apparaatbeheer
Als u video wilt gebruiken met bellen, moet u apparaten beheren. Met apparaten kunt u bepalen wat audio en video naar het gesprek verzendt.
Met DeviceManager
het object kunt u lokale apparaten opsommen die in een gesprek kunnen worden gebruikt om uw audio-/videostreams te verzenden. Hiermee kunt u ook toestemming vragen van een gebruiker om toegang te krijgen tot de microfoon en camera met behulp van de systeemeigen browser-API.
Roep de deviceManager
functie aan om toegang te krijgen tot callClient.getDeviceManager()
.
Context appContext = this.getApplicationContext();
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
Lokale apparaten opsommen
Gebruik opsommingsmethoden voor apparaatbeheer om toegang te krijgen tot lokale apparaten. Opsomming is een synchrone actie.
// Get a list of available video devices for use.
List<VideoDeviceInfo> localCameras = deviceManager.getCameras(); // [VideoDeviceInfo, VideoDeviceInfo...]
Voorbeeld van lokale camera
U kunt DeviceManager
en Renderer
gebruiken om streams van uw lokale camera weer te geven. Deze stream wordt niet naar andere deelnemers verzonden. Het is een lokale preview-feed. Het weergeven van een stream is een asynchrone actie.
VideoDeviceInfo videoDevice = <get-video-device>; // See the `Enumerate local devices` topic above
Context appContext = this.getApplicationContext();
LocalVideoStream currentVideoStream = new LocalVideoStream(videoDevice, appContext);
LocalVideoStream[] localVideoStreams = new LocalVideoStream[1];
localVideoStreams[0] = currentVideoStream;
VideoOptions videoOptions = new VideoOptions(localVideoStreams);
RenderingOptions renderingOptions = new RenderingOptions(ScalingMode.Fit);
VideoStreamRenderer previewRenderer = new VideoStreamRenderer(currentVideoStream, appContext);
VideoStreamRendererView uiView = previewRenderer.createView(renderingOptions);
// Attach the uiView to a viewable location on the app at this point
layout.addView(uiView);
Een 1:1-gesprek met videocamera plaatsen
Waarschuwing
Momenteel wordt slechts één uitgaande lokale videostream ondersteund. Als u een oproep met video wilt plaatsen, moet u lokale camera's inventariseren met behulp van de deviceManager
getCameras
API.
Zodra u een camera hebt geselecteerd, gebruikt u deze om een LocalVideoStream
exemplaar te maken en door te geven videoOptions
als een item in de localVideoStream
matrix aan een call
methode. Zodra het gesprek is verbonden, wordt automatisch een videostream van de geselecteerde camera naar andere deelnemers verzonden.
Notitie
Vanwege privacyproblemen wordt video niet gedeeld met het gesprek als deze niet lokaal wordt gepreviewd. Zie voorbeeld van lokale camera voor meer informatie.
VideoDeviceInfo desiredCamera = <get-video-device>; // See the `Enumerate local devices` topic above
Context appContext = this.getApplicationContext();
LocalVideoStream currentVideoStream = new LocalVideoStream(desiredCamera, appContext);
LocalVideoStream[] localVideoStreams = new LocalVideoStream[1];
localVideoStreams[0] = currentVideoStream;
VideoOptions videoOptions = new VideoOptions(localVideoStreams);
// Render a local preview of video so the user knows that their video is being shared
Renderer previewRenderer = new VideoStreamRenderer(currentVideoStream, appContext);
View uiView = previewRenderer.createView(new CreateViewOptions(ScalingMode.FIT));
// Attach the uiView to a viewable location on the app at this point
layout.addView(uiView);
CommunicationUserIdentifier[] participants = new CommunicationUserIdentifier[]{ new CommunicationUserIdentifier("<acs user id>") };
StartCallOptions startCallOptions = new StartCallOptions();
startCallOptions.setVideoOptions(videoOptions);
Call call = callAgent.startCall(context, participants, startCallOptions);
Lokale video verzenden starten en stoppen
Als u een video wilt starten, moet u camera's inventariseren met behulp van de getCameraList
bewerking op deviceManager
object. Maak vervolgens een nieuw exemplaar van LocalVideoStream
door de gewenste camera door te geven, en geef deze als argument door in de startVideo
API:
VideoDeviceInfo desiredCamera = <get-video-device>; // See the `Enumerate local devices` topic above
Context appContext = this.getApplicationContext();
LocalVideoStream currentLocalVideoStream = new LocalVideoStream(desiredCamera, appContext);
VideoOptions videoOptions = new VideoOptions(currentLocalVideoStream);
Future startVideoFuture = call.startVideo(appContext, currentLocalVideoStream);
startVideoFuture.get();
Zodra het u is gelukt video te verzenden, wordt er een LocalVideoStream
exemplaar toegevoegd aan de localVideoStreams
verzameling op het oproepexemplaar.
List<LocalVideoStream> videoStreams = call.getLocalVideoStreams();
LocalVideoStream currentLocalVideoStream = videoStreams.get(0); // Please make sure there are VideoStreams in the list before calling get(0).
Als u lokale video wilt stoppen, geeft u het exemplaar door dat beschikbaar is in LocalVideoStream
de localVideoStreams
verzameling:
call.stopVideo(appContext, currentLocalVideoStream).get();
U kunt overschakelen naar een ander cameraapparaat terwijl video wordt verzonden door switchSource
aan te roepen op een LocalVideoStream
instantie.
currentLocalVideoStream.switchSource(source).get();
Videostreams van externe deelnemers weergeven
Inspecteer de videoStreams
-verzamelingen om de videostreams en schermdelingsstreams van externe deelnemers te bekijken.
List<RemoteParticipant> remoteParticipants = call.getRemoteParticipants();
RemoteParticipant remoteParticipant = remoteParticipants.get(0); // Please make sure there are remote participants in the list before calling get(0).
List<RemoteVideoStream> remoteStreams = remoteParticipant.getVideoStreams();
RemoteVideoStream remoteParticipantStream = remoteStreams.get(0); // Please make sure there are video streams in the list before calling get(0).
MediaStreamType streamType = remoteParticipantStream.getType(); // of type MediaStreamType.Video or MediaStreamType.ScreenSharing
Als u een RemoteVideoStream
van een externe deelnemer wilt weergeven, moet u zich abonneren op een OnVideoStreamsUpdated
gebeurtenis.
Binnen de gebeurtenis geeft de wijziging van isAvailable
eigenschap naar waarheidswaarde aan dat de externe deelnemer momenteel een stream verzendt. Als dat gebeurt, maakt u een nieuw exemplaar van een Renderer
, maakt u vervolgens een nieuwe RendererView
met behulp van asynchrone createView
API en voegt u overal in de gebruikersinterface van uw toepassing toe view.target
.
Wanneer de beschikbaarheid van een externe stream verandert, kunt u ervoor kiezen om de hele Renderer
te vernietigen, een specifieke RendererView
te verwijderen, of ze te behouden, wat echter resulteert in het tonen van een leeg videoframe.
VideoStreamRenderer remoteVideoRenderer = new VideoStreamRenderer(remoteParticipantStream, appContext);
VideoStreamRendererView uiView = remoteVideoRenderer.createView(new RenderingOptions(ScalingMode.FIT));
layout.addView(uiView);
remoteParticipant.addOnVideoStreamsUpdatedListener(e -> onRemoteParticipantVideoStreamsUpdated(p, e));
void onRemoteParticipantVideoStreamsUpdated(RemoteParticipant participant, RemoteVideoStreamsEvent args) {
for(RemoteVideoStream stream : args.getAddedRemoteVideoStreams()) {
if(stream.getIsAvailable()) {
startRenderingVideo();
} else {
renderer.dispose();
}
}
}
Eigenschappen van videostream op afstand
Externe videostream heeft de volgende eigenschappen:
Id
- Id van een externe videostream.int id = remoteVideoStream.getId();
MediaStreamType
- Kan zijnVideo
ofScreenSharing
.MediaStreamType type = remoteVideoStream.getMediaStreamType();
isAvailable
- Geeft aan of het eindpunt van externe deelnemers actief stream verzendt.boolean availability = remoteVideoStream.isAvailable();
Renderermethoden en -eigenschappen
Het Renderer
object gebruikt de volgende methoden.
Als u een externe videostream wilt weergeven, maakt u een
VideoStreamRendererView
exemplaar dat later kan worden gekoppeld aan de gebruikersinterface van de toepassing.// Create a view for a video stream VideoStreamRendererView.createView()
Renderer en alle
VideoStreamRendererView
die aan deze renderer zijn gekoppeld, verwijderen. Roep deze aan nadat u alle bijbehorende weergaven uit de gebruikersinterface hebt verwijderd.VideoStreamRenderer.dispose()
Als u de grootte (breedte/hoogte) van een externe videostream wilt instellen, gebruikt u
StreamSize
.StreamSize renderStreamSize = VideoStreamRenderer.getSize(); int width = renderStreamSize.getWidth(); int height = renderStreamSize.getHeight();
RendererView-methoden en -eigenschappen
Wanneer u een VideoStreamRendererView
maakt, kunt u de ScalingMode
en mirrored
eigenschappen opgeven die van toepassing zijn op deze weergave.
De schaalmodus kan ofwel CROP
of FIT
zijn.
VideoStreamRenderer remoteVideoRenderer = new VideoStreamRenderer(remoteVideoStream, appContext);
VideoStreamRendererView rendererView = remoteVideoRenderer.createView(new CreateViewOptions(ScalingMode.Fit));
De gemaakte RendererView kan vervolgens worden gekoppeld aan de gebruikersinterface van de toepassing met behulp van het volgende codefragment:
layout.addView(rendererView);
U kunt de schaalmodus later bijwerken met behulp van de updateScalingMode
bewerking op het RendererView
object met een argument van of ScalingMode.CROP
ScalingMode.FIT
.
// Update the scale mode for this view.
rendererView.updateScalingMode(ScalingMode.CROP)
Uw systeem instellen
Volg deze stappen om uw systeem in te stellen.
Het Xcode-project maken
Maak in Xcode een nieuw iOS-project en selecteer de sjabloon Single View-app (Toepassing met één weergave). In dit artikel wordt het SwiftUI-framework gebruikt, dus u moet taal instellen op Swift en interface instellen op SwiftUI.
U gaat geen tests maken in dit artikel. Voel je vrij om het selectievakje Inclusief tests uit te schakelen.
Het pakket en afhankelijkheden installeren met CocoaPods
Maak een Podfile voor uw toepassing, zoals in dit voorbeeld:
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 1.0.0' end
Voer
pod install
uit.Open
.xcworkspace
met behulp van Xcode.
Toegang tot de microfoon aanvragen
Voor toegang tot de microfoon van het apparaat moet u de lijst met gegevenseigenschappen van uw app bijwerken met behulp van NSMicrophoneUsageDescription
. Stel de gekoppelde waarde in op een tekenreeks die is opgenomen in het dialoogvenster dat het systeem gebruikt om toegang van de gebruiker aan te vragen.
Klik met de rechtermuisknop op de vermelding Info.plist van de projectstructuur en selecteer Open As.> Voeg de volgende regels toe in de sectie op het hoogste niveau <dict>
en sla het bestand op.
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>
Stel het app-framework in
Open het projectbestand ContentView.swift
. Voeg een import
declaratie toe aan het begin van het bestand om de AzureCommunicationCalling
bibliotheek te importeren. Daarnaast importeert u AVFoundation
. U hebt deze nodig voor audiomachtigingsaanvragen in de code.
import AzureCommunicationCalling
import AVFoundation
CallAgent initialiseren
Om een CallAgent
instantie van CallClient
te maken, moet u een callClient.createCallAgent
-methode gebruiken die asynchroon een CallAgent
-object retourneert nadat het is geïnitialiseerd.
Als u een aanroepclient wilt maken, geeft u een CommunicationTokenCredential
object door:
import AzureCommunication
let tokenString = "token_string"
var userCredential: CommunicationTokenCredential?
do {
let options = CommunicationTokenRefreshOptions(initialToken: token, refreshProactively: true, tokenRefresher: self.fetchTokenSync)
userCredential = try CommunicationTokenCredential(withOptions: options)
} catch {
updates("Couldn't created Credential object", false)
initializationDispatchGroup!.leave()
return
}
// tokenProvider needs to be implemented by Contoso, which fetches a new token
public func fetchTokenSync(then onCompletion: TokenRefreshOnCompletion) {
let newToken = self.tokenProvider!.fetchNewToken()
onCompletion(newToken, nil)
}
Geef het CommunicationTokenCredential
-object dat u hebt gemaakt door aan CallClient
, en stel de weergavenaam in:
self.callClient = CallClient()
let callAgentOptions = CallAgentOptions()
options.displayName = " iOS Azure Communication Services User"
self.callClient!.createCallAgent(userCredential: userCredential!,
options: callAgentOptions) { (callAgent, error) in
if error == nil {
print("Create agent succeeded")
self.callAgent = callAgent
} else {
print("Create agent failed")
}
})
Apparaten beheren
Als u video wilt gaan gebruiken met bellen, moet u weten hoe u apparaten beheert. Met apparaten kunt u bepalen wat audio en video naar het gesprek verzendt.
DeviceManager
hiermee kunt u lokale apparaten opsommen die kunnen worden gebruikt in een gesprek om audio- of videostreams te verzenden. Hiermee kunt u ook toestemming vragen van een gebruiker om toegang te krijgen tot een microfoon of camera. U kunt toegang krijgen tot deviceManager
op het callClient
object.
self.callClient!.getDeviceManager { (deviceManager, error) in
if (error == nil) {
print("Got device manager instance")
self.deviceManager = deviceManager
} else {
print("Failed to get device manager instance")
}
}
Lokale apparaten opsommen
Voor toegang tot lokale apparaten kunt u opsommingsmethoden gebruiken in apparaatbeheer. Opsomming is een synchrone actie.
// enumerate local cameras
var localCameras = deviceManager.cameras // [VideoDeviceInfo, VideoDeviceInfo...]
Een voorvertoning van een lokale camera bekijken
U kunt Renderer
gebruiken om te beginnen met het weergeven van een stream vanaf uw lokale camera. Deze stream is niet voor andere deelnemers; het is een lokale preview-feed. Dit is een asynchrone actie.
let camera: VideoDeviceInfo = self.deviceManager!.cameras.first!
let localVideoStream = LocalVideoStream(camera: camera)
let localRenderer = try! VideoStreamRenderer(localVideoStream: localVideoStream)
self.view = try! localRenderer.createView()
Eigenschappen van de lokale camerapreview ophalen
De renderer bevat een set eigenschappen en methoden waarmee u de rendering kunt beheren.
// Constructor can take in LocalVideoStream or RemoteVideoStream
let localRenderer = VideoStreamRenderer(localVideoStream:localVideoStream)
let remoteRenderer = VideoStreamRenderer(remoteVideoStream:remoteVideoStream)
// [StreamSize] size of the rendering view
localRenderer.size
// [VideoStreamRendererDelegate] an object you provide to receive events from this Renderer instance
localRenderer.delegate
// [Synchronous] create view
try! localRenderer.createView()
// [Synchronous] create view with rendering options
try! localRenderer!.createView(withOptions: CreateViewOptions(scalingMode: ScalingMode.fit))
// [Synchronous] dispose rendering view
localRenderer.dispose()
Een 1:1-gesprek met video plaatsen
Zie de sectie over het beheren van apparaten om een apparaatbeheerexemplaar te vinden.
let firstCamera = self.deviceManager!.cameras.first
self.localVideoStreams = [LocalVideoStream]()
self.localVideoStreams!.append(LocalVideoStream(camera: firstCamera!))
let videoOptions = VideoOptions(localVideoStreams: self.localVideoStreams!)
let startCallOptions = StartCallOptions()
startCallOptions.videoOptions = videoOptions
let callee = CommunicationUserIdentifier('UserId')
self.callAgent?.startCall(participants: [callee], options: startCallOptions) { (call, error) in
if error == nil {
print("Successfully started outgoing video call")
self.call = call
} else {
print("Failed to start outgoing video call")
}
}
Videostreams van externe deelnemers weergeven
Externe deelnemers kunnen tijdens een gesprek video of scherm delen initiëren.
Afhandelen van video- en schermdelingsstreams van externe deelnemers
Als u de streams van externe deelnemers wilt weergeven, inspecteert u de videoStreams
verzamelingen.
var remoteParticipantVideoStream = call.remoteParticipants[0].videoStreams[0]
Eigenschappen van videostream op afstand ophalen
var type: MediaStreamType = remoteParticipantVideoStream.type // 'MediaStreamTypeVideo'
var isAvailable: Bool = remoteParticipantVideoStream.isAvailable // indicates if remote stream is available
var id: Int = remoteParticipantVideoStream.id // id of remoteParticipantStream
Externe deelnemersstreams weergeven
Als u externe deelnemersstreams wilt weergeven, gebruikt u de volgende code.
let renderer = VideoStreamRenderer(remoteVideoStream: remoteParticipantVideoStream)
let targetRemoteParticipantView = renderer?.createView(withOptions: CreateViewOptions(scalingMode: ScalingMode.crop))
// To update the scaling mode later
targetRemoteParticipantView.update(scalingMode: ScalingMode.fit)
Externe videoweergavemethoden en -eigenschappen ophalen
// [Synchronous] dispose() - dispose renderer and all `RendererView` associated with this renderer. To be called when you have removed all associated views from the UI.
remoteVideoRenderer.dispose()
Uw systeem instellen
Volg deze stappen om uw systeem in te stellen.
Het Visual Studio-project maken
Voor een Universele Windows Platform-app maakt u in Visual Studio 2022 een nieuw lege app (Universele Windows)-project. Nadat u de projectnaam hebt ingevoerd, kunt u een Windows SDK kiezen die hoger is dan 10.0.17763.0.
Maak voor een WinUI 3-app een nieuw project met de sjabloon Blank App, Packaged (WinUI 3 in Desktop) om een WinUI 3-app met één pagina in te stellen. Windows-app SDK versie 1.3 of hoger is vereist.
Installeer het pakket en afhankelijkheden met behulp van NuGet Pakketbeheer
De Aanroepende SDK-API's en -bibliotheken zijn openbaar beschikbaar via een NuGet-pakket.
Het NuGet-pakket voor de Calling SDK zoeken, downloaden en installeren:
- Open NuGet Pakketbeheer door Hulpmiddelen>NuGet Pakketbeheer>NuGet-pakketten voor Oplossing beheren te selecteren.
- Selecteer Bladeren en voer vervolgens Azure.Communication.Calling.WindowsClient in het zoekvak in.
- Zorg ervoor dat het selectievakje Voorlopige versie opnemen is ingeschakeld.
- Selecteer het pakket Azure.Communication.Calling.WindowsClient en selecteer vervolgens Azure.Communication.Calling.WindowsClient1.4.0-beta.1 of een nieuwere versie.
- Schakel het selectievakje in dat overeenkomt met het Azure Communication Services-project in het rechterdeelvenster.
- Selecteer Installeren.
Toegang tot de microfoon aanvragen
Voor de app is toegang tot de camera vereist. In UWP-apps (Universal Windows Platform) moet u de cameramogelijkheid declareren in het manifestbestand van de app.
- Open het project in Visual Studio.
- Dubbelklik in het deelvenster Solution Explorer op het bestand met
.appxmanifest
de extensie. - Klik op het tabblad Mogelijkheden .
- Schakel het
Camera
selectievakje in de lijst met mogelijkheden in.
UI-knoppen maken om het gesprek te starten en op te hangen
Deze voorbeeld-app bevat twee knoppen. Een voor het plaatsen van de oproep en een andere om een geplaatst gesprek op te hangen.
- Dubbelklik in het deelvenster Solution Explorer op het bestand met de naam
MainPage.xaml
UWP ofMainWindows.xaml
voor WinUI 3. - Zoek in het centrale deelvenster naar de XAML-code onder de preview-versie van de gebruikersinterface.
- Wijzig de XAML-code met behulp van het volgende fragment:
<TextBox x:Name="CalleeTextBox" PlaceholderText="Who would you like to call?" />
<StackPanel>
<Button x:Name="CallButton" Content="Start/Join call" Click="CallButton_Click" />
<Button x:Name="HangupButton" Content="Hang up" Click="HangupButton_Click" />
</StackPanel>
De app instellen met SDK-API's voor aanroepen
De CALLING SDK-API's bevinden zich in twee verschillende naamruimten.
Voer de volgende stappen uit om de C#-compiler te informeren over deze naamruimten, zodat Visual Studio's IntelliSense kan helpen bij het ontwikkelen van code.
- Klik in het deelvenster Solution Explorer op de pijl aan de linkerkant van het bestand met de naam
MainPage.xaml
UWP ofMainWindows.xaml
voor WinUI 3. - Dubbelklik op bestand met de naam
MainPage.xaml.cs
ofMainWindows.xaml.cs
. - Voeg de volgende opdrachten onder aan de huidige
using
instructies toe.
using Azure.Communication.Calling.WindowsClient;
Houd MainPage.xaml.cs
of MainWindows.xaml.cs
open. In de volgende stap wordt meer code toegevoegd.
App-interacties inschakelen
De ui-knoppen die we hebben toegevoegd, moeten boven op een geplaatste CommunicationCall
knop werken. Dit betekent dat u een CommunicationCall
gegevenslid moet toevoegen aan de MainPage
of MainWindow
klasse.
U moet ook de asynchrone bewerking waarmee CallAgent
wordt gemaakt activeren om te slagen. Voeg een CallAgent
gegevenslid toe aan dezelfde klasse.
Voeg de volgende gegevensleden toe aan de MainPage
of MainWindow
klasse:
CallAgent callAgent;
CommunicationCall call;
Knophandlers maken
Eerder hebben we twee UI-knoppen toegevoegd aan de XAML-code. Met de volgende code worden de handlers toegevoegd die moeten worden uitgevoerd wanneer een gebruiker de knop selecteert.
Voeg de volgende code toe na de gegevensleden uit de vorige sectie.
private async void CallButton_Click(object sender, RoutedEventArgs e)
{
// Start call
}
private async void HangupButton_Click(object sender, RoutedEventArgs e)
{
// End the current call
}
Objectmodel
De volgende klassen en interfaces verwerken enkele van de belangrijkste functies van de Clientbibliotheek voor aanroepen van Azure Communication Services voor UWP.
Naam | Beschrijving |
---|---|
CallClient |
Het CallClient is het belangrijkste toegangspunt tot de oproepclientbibliotheek. |
CallAgent |
Het CallAgent wordt gebruikt om oproepen te starten en eraan deel te nemen. |
CommunicationCall |
Het CommunicationCall wordt gebruikt voor het beheren van geplaatste of gekoppelde oproepen. |
CommunicationTokenCredential |
De CommunicationTokenCredential wordt gebruikt als de token-inloggegevens om de CallAgent te initialiseren. |
CallAgentOptions |
De CallAgentOptions bevat informatie om de beller te identificeren. |
HangupOptions |
De HangupOptions geeft aan of een oproep aan alle deelnemers moet worden beëindigd. |
Videoschema-handler registreren
Een UI-onderdeel, zoals XAML's MediaElement
of MediaPlayerElement
, vereist dat de app een configuratie registreert voor het weergeven van lokale en externe videofeeds.
Voeg de volgende inhoud toe tussen de Package
tags van:Package.appxmanifest
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
De CallAgent initialiseren
Als u een CallAgent
instantie van CallClient
wilt maken, moet u de CallClient.CreateCallAgentAsync
methode gebruiken die asynchroon een CallAgent
object retourneert zodra het is geïnitialiseerd.
Als u wilt maken CallAgent
, moet u een CallTokenCredential
object en een CallAgentOptions
object doorgeven. Houd er rekening mee dat CallTokenCredential
een uitzondering veroorzaakt als er een ongeldig token wordt doorgegeven.
Voeg de volgende code binnen en helperfunctie toe, zodat deze wordt uitgevoerd tijdens de initialisatie.
var callClient = new CallClient();
this.deviceManager = await callClient.GetDeviceManagerAsync();
var tokenCredential = new CallTokenCredential("<AUTHENTICATION_TOKEN>");
var callAgentOptions = new CallAgentOptions()
{
DisplayName = "<DISPLAY_NAME>"
};
this.callAgent = await callClient.CreateCallAgentAsync(tokenCredential, callAgentOptions);
this.callAgent.CallsUpdated += Agent_OnCallsUpdatedAsync;
this.callAgent.IncomingCallReceived += Agent_OnIncomingCallAsync;
Wijzig het <AUTHENTICATION_TOKEN>
met een geldig referentietoken voor uw resource. Zie het token voor gebruikerstoegang voor meer informatie over het ophalen van een referentietoken.
Een 1:1-gesprek met videocamera plaatsen
De objecten die nodig zijn om een CallAgent
te maken, zijn nu gereed. Maak vervolgens asynchroon CallAgent
en plaats een videogesprek.
private async void CallButton_Click(object sender, RoutedEventArgs e)
{
var callString = CalleeTextBox.Text.Trim();
if (!string.IsNullOrEmpty(callString))
{
if (callString.StartsWith("8:")) // 1:1 Azure Communication Services call
{
this.call = await StartAcsCallAsync(callString);
}
}
if (this.call != null)
{
this.call.RemoteParticipantsUpdated += OnRemoteParticipantsUpdatedAsync;
this.call.StateChanged += OnStateChangedAsync;
}
}
private async Task<CommunicationCall> StartAcsCallAsync(string acsCallee)
{
var options = await GetStartCallOptionsAsync();
var call = await this.callAgent.StartCallAsync( new [] { new UserCallIdentifier(acsCallee) }, options);
return call;
}
var micStream = new LocalOutgoingAudioStream(); // Create a default local audio stream
var cameraStream = new LocalOutgoingVideoStream(this.viceManager.Cameras.FirstOrDefault() as VideoDeviceDetails); // Create a default video stream
private async Task<StartCallOptions> GetStartCallOptionsAsync()
{
return new StartCallOptions() {
OutgoingAudioOptions = new OutgoingAudioOptions() { IsMuted = true, Stream = micStream },
OutgoingVideoOptions = new OutgoingVideoOptions() { Streams = new OutgoingVideoStream[] { cameraStream } }
};
}
Voorbeeld van lokale camera
We kunnen eventueel een lokale cameravoorvertoning instellen. U kunt de video weergeven via MediaPlayerElement
:
<Grid>
<MediaPlayerElement x:Name="LocalVideo" AutoPlay="True" />
<MediaPlayerElement x:Name="RemoteVideo" AutoPlay="True" />
</Grid>
De lokale preview MediaPlayerElement
initialiseren:
private async void CameraList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (cameraStream != null)
{
await cameraStream?.StopPreviewAsync();
if (this.call != null)
{
await this.call?.StopVideoAsync(cameraStream);
}
}
var selectedCamera = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamera);
var localUri = await cameraStream.StartPreviewAsync();
LocalVideo.Source = MediaSource.CreateFromUri(localUri);
if (this.call != null) {
await this.call?.StartVideoAsync(cameraStream);
}
}
Externe camerastream weergeven
Stel zelfs handler in als reactie op OnCallsUpdated
gebeurtenis:
private async void OnCallsUpdatedAsync(object sender, CallsUpdatedEventArgs args)
{
var removedParticipants = new List<RemoteParticipant>();
var addedParticipants = new List<RemoteParticipant>();
foreach(var call in args.RemovedCalls)
{
removedParticipants.AddRange(call.RemoteParticipants.ToList<RemoteParticipant>());
}
foreach (var call in args.AddedCalls)
{
addedParticipants.AddRange(call.RemoteParticipants.ToList<RemoteParticipant>());
}
await OnParticipantChangedAsync(removedParticipants, addedParticipants);
}
private async void OnRemoteParticipantsUpdatedAsync(object sender, ParticipantsUpdatedEventArgs args)
{
await OnParticipantChangedAsync(
args.RemovedParticipants.ToList<RemoteParticipant>(),
args.AddedParticipants.ToList<RemoteParticipant>());
}
private async Task OnParticipantChangedAsync(IEnumerable<RemoteParticipant> removedParticipants, IEnumerable<RemoteParticipant> addedParticipants)
{
foreach (var participant in removedParticipants)
{
foreach(var incomingVideoStream in participant.IncomingVideoStreams)
{
var remoteVideoStream = incomingVideoStream as RemoteIncomingVideoStream;
if (remoteVideoStream != null)
{
await remoteVideoStream.StopPreviewAsync();
}
}
participant.VideoStreamStateChanged -= OnVideoStreamStateChanged;
}
foreach (var participant in addedParticipants)
{
participant.VideoStreamStateChanged += OnVideoStreamStateChanged;
}
}
private void OnVideoStreamStateChanged(object sender, VideoStreamStateChangedEventArgs e)
{
CallVideoStream callVideoStream = e.CallVideoStream;
switch (callVideoStream.StreamDirection)
{
case StreamDirection.Outgoing:
OnOutgoingVideoStreamStateChanged(callVideoStream as OutgoingVideoStream);
break;
case StreamDirection.Incoming:
OnIncomingVideoStreamStateChanged(callVideoStream as IncomingVideoStream);
break;
}
}
Start het weergeven van externe videostream op MediaPlayerElement
:
private async void OnIncomingVideoStreamStateChanged(IncomingVideoStream incomingVideoStream)
{
switch (incomingVideoStream.State)
{
case VideoStreamState.Available:
{
switch (incomingVideoStream.Kind)
{
case VideoStreamKind.RemoteIncoming:
var remoteVideoStream = incomingVideoStream as RemoteIncomingVideoStream;
var uri = await remoteVideoStream.StartPreviewAsync();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
RemoteVideo.Source = MediaSource.CreateFromUri(uri);
});
/* Or WinUI 3
this.DispatcherQueue.TryEnqueue(() => {
RemoteVideo.Source = MediaSource.CreateFromUri(uri);
RemoteVideo.MediaPlayer.Play();
});
*/
break;
case VideoStreamKind.RawIncoming:
break;
}
break;
}
case VideoStreamState.Started:
break;
case VideoStreamState.Stopping:
break;
case VideoStreamState.Stopped:
if (incomingVideoStream.Kind == VideoStreamKind.RemoteIncoming)
{
var remoteVideoStream = incomingVideoStream as RemoteIncomingVideoStream;
await remoteVideoStream.StopPreviewAsync();
}
break;
case VideoStreamState.NotAvailable:
break;
}
}
Een gesprek beëindigen
Zodra een aanroep is geplaatst, gebruikt u de HangupAsync
methode van het CommunicationCall
object om de aanroep op te hangen.
Gebruik een instantie van HangupOptions
om deelnemers te informeren als de oproep moet worden beëindigd.
Voeg de volgende code toe in HangupButton_Click
.
var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
foreach (var localVideoStream in call.OutgoingVideoStreams)
{
await call.StopVideoAsync(localVideoStream);
}
try
{
if (cameraStream != null)
{
await cameraStream.StopPreviewAsync();
}
await call.HangUpAsync(new HangUpOptions() { ForEveryone = false });
}
catch(Exception ex)
{
var errorCode = unchecked((int)(0x0000FFFFU & ex.HResult));
if (errorCode != 98) // Sample error code, sam_status_failed_to_hangup_for_everyone (98)
{
throw;
}
}
}
}
De code uitvoeren
- Zorg ervoor dat Visual Studio de app bouwt voor
x64
,x86
ofARM64
. - Druk op F5 om de app uit te voeren.
- Klik op de knop CommunicationCall om een oproep naar de gedefinieerde ontvanger te plaatsen.
De eerste keer dat de app wordt uitgevoerd, vraagt het systeem de gebruiker toegang te verlenen tot de microfoon.