Video beheren tijdens gesprekken
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 geïmplementeerde 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 het beste beheren
Het Call Agent
exemplaar helpt u bij het beheren van gesprekken (om aanroepen deel te nemen of 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 Call Agent
connectionStatue-waarde van Connected
het middel dat de client-SDK is verbonden en meldingen van de Microsoft-infrastructuur kan ontvangen.
Verbinding verbroken - Een Call Agent
connectionStatue-waarde van Disconnected
statussen is er een probleem dat verhindert dat de SDK verbinding maakt. Call Agent
moet opnieuw worden gemaakt.
invalidToken
: Als een token is verlopen of een ongeldig exemplaarCall Agent
wordt verbroken met deze fout.connectionIssue
: Als er een probleem is met de client die verbinding maakt met Microsoft infrascture, wordt deconnectionIssue
fout na veel nieuwe pogingenCall Agent
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
de status 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.
Met de deviceManager
, kunt u inventariseren lokale apparaten 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 aan callClient.getDeviceManager()
te roepen:
const deviceManager = await callClient.getDeviceManager();
Lokale apparaten ophalen
Voor toegang tot lokale apparaten kunt u de deviceManager
opsommingsmethoden getCameras()
en getMicrophones
. 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]);
Camera
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 u aan om verschillende CallAgents
microfoons en luidsprekers te gebruiken. Ze mogen niet dezelfde microfoons of luidsprekers delen. Als het delen plaatsvindt, kan diagnostische gegevens van de microfoon worden geactiveerd en werkt de microfoon niet meer, afhankelijk van de browser/het besturingssysteem.
Lokale videostream
Als u video wilt kunnen verzenden in een gesprek, moet u een LocalVideoStream
object maken.
const localVideoStream = new LocalVideoStream(camera);
De camera die als parameter wordt doorgegeven, is een van het VideoDeviceInfo
object dat door de deviceManager.getCameras()
methode wordt geretourneerd.
A LocalVideoStream
heeft de volgende eigenschappen:
source
: de apparaatgegevens.
const source = localVideoStream.source;
mediaStreamType
: kan zijnVideo
,ScreenSharing
ofRawMedia
.
const type: MediaStreamType = localVideoStream.mediaStreamType;
Voorbeeld van lokale camera
U kunt streams vanaf uw lokale camera gebruiken deviceManager
en VideoStreamRenderer
weergeven.
Zodra een is LocalVideoStream
gemaakt, gebruikt u deze om het in te stellenVideoStreamRenderer
. Zodra de VideoStreamRenderer
methode is gemaakt, wordt de methode aangeroepen createView()
om een weergave te krijgen die u als onderliggend element 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 DeviceManager wordt gemaakt, weet het in eerste instantie niet over apparaten als er nog geen machtigingen zijn verleend, dus in eerste instantie is de apparaatnaam leeg en bevat deze geen gedetailleerde apparaatgegevens. Als we de DeviceManager.askPermission() API aanroepen, wordt de gebruiker gevraagd om apparaattoegang. Wanneer de gebruiker de optie Toestaan selecteert om de apparaatbeheerder toegang te verlenen tot de apparaten op het systeem, werkt u de apparaatlijsten bij en verzendt u de gebeurtenissen 'audioDevicesUpdated' en 'videoDevicesUpdated'. Als een gebruiker de pagina vernieuwt en een apparaatbeheerder maakt, kan de apparaatbeheerder meer informatie krijgen over apparaten omdat de gebruiker eerder toegang heeft verleend. Het apparaat bevat in eerste instantie een lijst met apparaten en verzendt geen 'audioDevicesUpdated' of 'videoDevicesUpdated'-gebeurtenissen.
- 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 deze videoOptions
door als een item in de localVideoStream
matrix 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 video hebt verzonden, wordt een LocalVideoStream
exemplaar van het type Video
toegevoegd aan de localVideoStreams
verzameling van een oproepexemplaren.
De videostream zoeken in het gespreksobject
const localVideoStream = call.localVideoStreams.find( (stream) => { return stream.mediaStreamType === 'Video'} );
Stop de lokale video Om lokale video te stoppen tijdens een gesprek, geeft u het localVideoStream
exemplaar door dat wordt gebruikt voor video door aan de stopVideo-methode van de Call
:
await call.stopVideo(localVideoStream);
U kunt overschakelen naar een ander cameraapparaat terwijl u een actieve LocalVideoStream hebt door deze instantie LocalVideoStream
aan te switchSource
roepen:
const cameras = await callClient.getDeviceManager().getCameras();
const camera = cameras[1];
localVideoStream.switchSource(camera);
Als het opgegeven videoapparaat niet beschikbaar is:
- Als uw video in een gesprek is uitgeschakeld en u video gaat gebruiken
call.startVideo()
, wordt met deze methode eenSourceUnavailableError
diagnostische gegevens voor gebruikerscameraStartFailed
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:
Scherm delen starten
// Start screen sharing
await call.startScreenSharing();
Opmerking: het verzenden van schermshares wordt alleen ondersteund in de bureaubladbrowser.
Het scherm delen zoeken in de verzameling LocalVideoStream
Nadat u het delen van het scherm hebt gestart, wordt er een LocalVideoStream
exemplaar van het type ScreenSharing
toegevoegd aan de localVideoStreams
verzameling op het aanroepexemplaren.
const localVideoStream = call.localVideoStreams.find( (stream) => { return stream.mediaStreamType === 'ScreenSharing'} );
Scherm delen stoppen
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.
Preview-API's en SDK's worden aangeboden zonder een service level agreement. U wordt aangeraden deze niet te gebruiken voor productieworkloads. Sommige functies worden mogelijk niet ondersteund of hebben mogelijk beperkte mogelijkheden.
Raadpleeg aanvullende gebruiksvoorwaarden voor Microsoft Azure Previews voor meer informatie.
Preview van lokale schermshares 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 stoped 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 externe deelnemer video of scherm delen wilt weergeven, is de eerste stap het verkrijgen van een verwijzing op de RemoteVideoStream die u wilt weergeven.
Dit kan worden gedaan 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 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 WebJS SDK van Azure Communication Services biedt een functie met de naam Optimal Video Count (OVC), vanaf versie 1.15.1.
Deze functie kan worden gebruikt 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 (2+ 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 uitvalperiode (ongeveer 10 s) 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, moet de computer een mimimum van 16 GB RAM en een 4-core of hoger CPU hebben die niet ouder is dan 3 jaar.
const optimalVideoCountFeature = call.feature(Features.OptimalVideoCount);
optimalVideoCountFeature.on('optimalVideoCountChanged', () => {
const localOptimalVideoCountVariable = optimalVideoCountFeature.optimalVideoCount;
})
Voorbeeldgebruik: De toepassing moet zich abonneren op wijzigingen van het optimale aantal video's in groepsgesprekken. Een wijziging in het optimale aantal video's kan worden verwerkt door een nieuwe renderer (createView
methode) te maken of weergaven te verwijderen (dispose
) en de indeling van de toepassing dienovereenkomstig bij te werken.
Eigenschappen van externe videostream
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 in de volgende scenario's verplaatst
false
:- Een externe deelnemer die zich in de mobiele browser bevindt, brengt 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 netwerkverbinding.
- Een externe deelnemer op mobiele apparaten beëindigt 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 zich op een desktopcomputer bevindt en in de slaapstand gaat.
De vlag wordt in de volgende scenario's verplaatst
true
:- Een externe deelnemer die zich in de mobiele browser bevindt en de browser achtergrond heeft, brengt deze terug naar de voorgrond.
- Een externe deelnemer die zich in macOS/iOS Safari bevindt, selecteert op 'Hervatten' in de adresbalk nadat de video is onderbroken.
- Een externe deelnemer maakt opnieuw verbinding met het netwerk na een tijdelijke verbroken verbinding.
- Een externe deelnemer op mobiele apparaten ontgrendelt het apparaat en keert terug naar het gesprek in de mobiele browser.
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();
videoStreamRenderer
Verwijder alle bijbehorende exemplaren 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
dit is opgegeven, wordt de gerenderde stroom 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.
Preview-API's en SDK's worden aangeboden zonder een service level agreement. U wordt aangeraden deze niet te gebruiken voor productieworkloads. Sommige functies worden mogelijk niet ondersteund of hebben mogelijk beperkte mogelijkheden.
Raadpleeg aanvullende gebruiksvoorwaarden voor Microsoft Azure Previews voor 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:
- Dit moet worden gedaan met twee verschillende
CallAgent
exemplaren die verschillende identiteiten gebruiken. Het codefragment toont twee aanroepagents die worden gebruikt, elk met een eigen aanroepobject. - In het codevoorbeeld nemen beide CallAgents deel aan dezelfde aanroep (dezelfde oproep-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 op de achtergrond vervagen (van @azure/communication-effects), kunnen alleen worden toegepast op één camera en niet op beide tegelijk.
Installeer de SDK
Zoek het bestand op projectniveau build.gradle
en voeg deze toe aan mavenCentral()
de lijst met opslagplaatsen 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 wordt CommunicationUserCredential
gebruikt als een argument, dat een toegangstoken inkapselt.
Als u toegang DeviceManager
wilt krijgen, moet u eerst een callAgent
exemplaar 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 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 uw audio-/videostreams te verzenden. Hiermee kunt u ook toestemming vragen van een gebruiker om toegang te krijgen tot hun microfoon en camera met behulp van de systeemeigen browser-API.
U kunt toegang krijgen deviceManager
via de aanroepmethode callClient.getDeviceManager()
.
Context appContext = this.getApplicationContext();
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
Lokale apparaten opsommen
Voor toegang tot lokale apparaten kunt u opsommingsmethoden op de Apparaatbeheer gebruiken. 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 streams vanaf uw lokale camera gebruiken DeviceManager
en Renderer
weergeven. Deze stream wordt niet naar andere deelnemers verzonden; het is een lokale preview-feed. Dit 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
Op dit moment wordt slechts één uitgaande lokale videostream ondersteund om een gesprek met video te plaatsen dat u lokale camera's moet inventariseren met behulp van de deviceManager
getCameras
API.
Zodra u een gewenste camera selecteert, 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 de oproep verbinding maakt, wordt automatisch een videostream van de geselecteerde camera naar andere deelnemers verzonden.
Notitie
Vanwege privacyproblemen wordt video niet gedeeld met de oproep als deze niet lokaal wordt bekeken. 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 starten en stoppen
Als u een video wilt starten, moet u camera's inventariseren met behulp van de getCameraList
API op deviceManager
object. Maak vervolgens een nieuw exemplaar van het doorgeven van LocalVideoStream
de gewenste camera 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 u video hebt verzonden, wordt er een LocalVideoStream
exemplaar toegevoegd aan de localVideoStreams
verzameling op het oproepexemplaren.
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 localVideoStreams
de LocalVideoStream
verzameling:
call.stopVideo(appContext, currentLocalVideoStream).get();
U kunt overschakelen naar een ander cameraapparaat terwijl video wordt verzonden door een LocalVideoStream
instantie aan te switchSource
roepen:
currentLocalVideoStream.switchSource(source).get();
Videostreams van externe deelnemers weergeven
Bekijk de verzamelingen om de videostreams en schermdelingsstreams van externe deelnemers videoStreams
weer te geven:
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
de eigenschap aan waar aan dat 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
of behouden, maar dit resulteert in het weergeven 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 externe videostream
Externe videostream heeft een aantal eigenschappen
Id
- Id van een externe videostream
int id = remoteVideoStream.getId();
MediaStreamType
- Kan 'Video' of 'ScreenSharing' zijn
MediaStreamType type = remoteVideoStream.getMediaStreamType();
isAvailable
- Geeft aan of het eindpunt van een externe deelnemer actief stream verzendt
boolean availability = remoteVideoStream.isAvailable();
Renderermethoden en -eigenschappen
Renderer-object na API's
- Maak een
VideoStreamRendererView
exemplaar dat later kan worden gekoppeld in de gebruikersinterface van de toepassing om externe videostream weer te geven.
// Create a view for a video stream
VideoStreamRendererView.createView()
- Renderer en alle
VideoStreamRendererView
die aan deze renderer zijn gekoppeld, verwijderen. Worden aangeroepen wanneer u alle gekoppelde weergaven uit de gebruikersinterface hebt verwijderd.
VideoStreamRenderer.dispose()
StreamSize
- grootte (breedte/hoogte) van een externe videostream
StreamSize renderStreamSize = VideoStreamRenderer.getSize();
int width = renderStreamSize.getWidth();
int height = renderStreamSize.getHeight();
RendererView-methoden en -eigenschappen
Wanneer u een VideoStreamRendererView
exemplaar maakt, kunt u de ScalingMode
eigenschappen mirrored
opgeven die van toepassing zijn op deze weergave: de schaalmodus kan een van de 'CROP' | 'FIT'
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 door API aan te updateScalingMode
roepen op het RendererView-object met een van ScalingMode.CROP | ScalingMode.FIT als argument.
// 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. Schakel het selectievakje Inclusief tests uit.
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>Source Code. 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
Als u een CallAgent
exemplaar CallClient
wilt 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 door waarnaar u hebt gemaakt 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
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 voorbeeld van een lokale camera downloaden
U kunt een Renderer
stream vanaf uw lokale camera weergeven. Deze stream wordt niet naar andere deelnemers verzonden; 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 lokale cameravoorbeeld ophalen
De renderer heeft 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 apparaatbeheerexemplaren op te halen.
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.
Streams voor video delen of scherm delen van externe deelnemers afhandelen
Als u de streams van externe deelnemers wilt weergeven, inspecteert u de videoStreams
verzamelingen.
var remoteParticipantVideoStream = call.remoteParticipants[0].videoStreams[0]
Eigenschappen van externe videostream 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 Universeel Windows-platform-app maakt u in Visual Studio 2022 een nieuw leeg app-project (Universal Windows). 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 aanroepende SDK zoeken, downloaden en installeren:
- Open NuGet Pakketbeheer door Tools>NuGet Pakketbeheer> Manage NuGet Packages for Solution 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.WindowsClient 1.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 moet toegang tot de camera goed worden uitgevoerd. In UWP-apps moet de cameramogelijkheid worden gedeclareerd in het manifestbestand van de app.
In de volgende stappen ziet u hoe u dat kunt bereiken.
- Dubbelklik in het
Solution Explorer
deelvenster op het bestand met.appxmanifest
extensie. - Klik op het
Capabilities
tabblad. - Schakel het
Camera
selectievakje in de lijst met mogelijkheden in.
Ui-knoppen maken om het gesprek te plaatsen en op te hangen
Deze eenvoudige voorbeeld-app bevat twee knoppen. Een voor het plaatsen van de oproep en een andere om een geplaatst gesprek op te hangen. In de volgende stappen ziet u hoe u deze knoppen aan de app toevoegt.
- Dubbelklik in het
Solution Explorer
deelvenster op het bestand met de naamMainPage.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 door 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. De volgende stappen informeren de C#-compiler over deze naamruimten, zodat De IntelliSense van Visual Studio kan helpen bij het ontwikkelen van code.
- Klik in het
Solution Explorer
deelvenster op de pijl aan de linkerkant van het bestand met de naamMainPage.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 stappen wordt er meer code aan toegevoegd.
App-interacties toestaan
De knoppen van de gebruikersinterface die eerder zijn toegevoegd, moeten boven op een geplaatste CommunicationCall
knop werken. Dit betekent dat een CommunicationCall
gegevenslid moet worden toegevoegd aan de MainPage
of MainWindow
klasse.
Daarnaast moet een CallAgent
gegevenslid worden toegevoegd aan dezelfde klasse om de asynchrone bewerking CallAgent
te laten slagen.
Voeg de volgende gegevensleden toe aan de MainPage
of MainWindow
klasse:
CallAgent callAgent;
CommunicationCall call;
Knophandlers maken
Voorheen werden 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. De volgende code moet worden toegevoegd 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.
Name | Beschrijving |
---|---|
CallClient |
Het CallClient is het belangrijkste toegangspunt voor de clientbibliotheek voor aanroepen. |
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 tokenreferentie om de CallAgent . |
CallAgentOptions |
De CallAgentOptions bevat informatie om de beller te identificeren. |
HangupOptions |
De HangupOptions meldingen als een oproep moet worden beëindigd aan alle deelnemers. |
Videoschema-handler registreren
Een UI-onderdeel, zoals MediaElement of MediaPlayerElement van XAML, hebt u de app nodig die 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
exemplaar CallClient
wilt maken, moet u een methode gebruiken CallClient.CreateCallAgentAsync
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
er een ongeldig token wordt doorgegeven.
De volgende code moet worden toegevoegd in de helperfunctie die moet worden aangeroepen in de initialisatie van de app.
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. Raadpleeg de documentatie van het gebruikerstoegangstoken als er een referentietoken moet worden opgehaald.
Een 1:1-gesprek met videocamera plaatsen
De objecten die nodig zijn om een te CallAgent
maken, zijn nu gereed. Het is tijd om asynchroon een videogesprek te maken CallAgent
en te plaatsen.
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 GetStartCallOptionsAsynnc();
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 LocalOutgoingVideoStreamde(this.viceManager.Cameras.FirstOrDefault() as VideoDeviceDetails); // Create a default video stream
private async Task<StartCallOptions> GetStartCallOptionsAsynnc()
{
return new StartCallOptions() {
OutgoingAudioOptions = new OutgoingAudioOptions() { IsMuted = true, Stream = micStream },
OutgoingVideoOptions = new OutgoingVideoOptions() { Streams = new OutgoingVideoStream[] { cameraStream } }
};
}
Voorbeeld van lokale camera
We kunnen eventueel lokale cameravoorbeeld instellen. De video kan worden weergegeven 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 selectedCamerea = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamerea);
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, moet de HangupAsync
methode van het CommunicationCall
object worden gebruikt om de aanroep op te hangen.
Er moet ook een instantie van HangupOptions
worden gebruikt om te informeren of de oproep moet worden beëindigd voor alle deelnemers.
De volgende code moet binnen HangupButton_Click
worden toegevoegd.
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
of ARM64
klik F5
vervolgens om de app uit te voeren. Klik daarna op de CommunicationCall
knop om een oproep naar de opgegeven aanroep te plaatsen.
Houd er rekening mee dat de eerste keer dat de app wordt uitgevoerd, de gebruiker wordt gevraagd om toegang te verlenen tot de microfoon.