Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Lär dig hur du hanterar videosamtal med Azure Communication Services SDK:er. Vi kommer att lära oss hur man hanterar mottagning och sändning av video under ett samtal.
Förutsättningar
- Ett Azure-konto med en aktiv prenumeration. Skapa ett konto kostnadsfritt.
- En distribuerad kommunikationstjänsteresurs. Skapa en kommunikationstjänstresurs
- En användartillgångstoken för att aktivera den uppringande klienten. För mer information, se Skapa och hantera åtkomsttokens.
- Valfritt: Slutför snabbstarten för att lägga till röstsamtal i din applikation.
Installera SDK:en
Använd kommandot npm install för att installera Azure Communication Services Common och Calling SDK för JavaScript.
npm install @azure/communication-common --save
npm install @azure/communication-calling --save
Initiera nödvändiga objekt
En CallClient-instans krävs för de flesta samtalsoperationer. När du skapar en ny CallClient instans kan du konfigurera den med anpassade alternativ som en Logger instans.
Med CallClient-instansen kan du skapa en CallAgent-instans genom att anropa createCallAgent. Denna metod returnerar asynkront ett CallAgent instansobjekt.
Metoden createCallAgent använder CommunicationTokenCredential som argument. Den accepterar ett användaråtkomsttoken.
Du kan använda getDeviceManager metoden på CallClient instansen för att få tillgång till 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()
Hantera SDK-anslutning till Microsoft-infrastruktur
Instansen Call Agent hjälper dig att hantera anrop (för att ansluta eller starta samtal). För att fungera måste din samtals-SDK ansluta till Microsofts infrastruktur för att få aviseringar om inkommande samtal och samordna andra samtalsdetaljer. Din Call Agent har två möjliga tillstånd:
Connected - Ett värde på Call Agent anslutningsstatus av Connected innebär att klient-SDK:t är anslutet och kan ta emot meddelanden från Microsoft-infrastruktur.
Frånkopplad – Ett Call Agent anslutningsstatus-värde för Disconnected anger att det finns ett problem som hindrar SDK:n från korrekt anslutning.
Call Agent bör återskapas.
-
invalidToken: Om en token har gått ut eller är ogiltig kopplasCall Agentinstansen från med detta fel. -
connectionIssue: Om det finns ett problem med att klienten ansluter till Microsoft-infrastrukturen, efter många återförsök exponerarCall AgentconnectionIssue-felet.
Du kan kontrollera om din lokala Call Agent är ansluten till Microsofts infrastruktur genom att inspektera det aktuella värdet på egenskapen connectionState. Under ett aktivt anrop kan du lyssna på connectionStateChanged händelsen för att avgöra om Call Agent det ändras från Anslutet till frånkopplat tillstånd.
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);
Enhetshantering
För att börja använda video med Calling SDK, måste du kunna hantera enheter. Med enheter kan du styra vad som överför ljud och video till samtalet.
deviceManager Använd för att räkna upp lokala enheter som kan överföra dina ljud- och videoströmmar i ett samtal. Du kan också använda deviceManager för att begära tillstånd att få åtkomst till den lokala enhetens mikrofoner och kameror.
Du kan komma åt deviceManager genom att anropa metoden callClient.getDeviceManager():
const deviceManager = await callClient.getDeviceManager();
Hämta lokala enheter
För att få tillgång till lokala enheter kan du använda deviceManager uppräkningsmetoderna getCameras() och getMicrophones. Dessa metoder är asynkrona åtgärder.
// 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...]
Ange standardenheter
När du vet vilka enheter som finns tillgängliga att använda kan du ställa in standardenheter för mikrofon, högtalare och kamera. Om klientens standardvärden inte har angetts använder Communication Services SDK standardinställningarna för operativsystemet.
Mikrofon
Åtkomst till den använda enheten
// Get the microphone device that is being used.
const defaultMicrophone = deviceManager.selectedMicrophone;
Ställa in enheten för användning
// Set the microphone device to use.
await deviceManager.selectMicrophone(localMicrophones[0]);
Talare
Åtkomst till den använda enheten
// Get the speaker device that is being used.
const defaultSpeaker = deviceManager.selectedSpeaker;
Ställa in enheten för användning
// Set the speaker device to use.
await deviceManager.selectSpeaker(localSpeakers[0]);
Kamera
Åtkomst till den använda enheten
// Get the camera device that is being used.
const defaultSpeaker = deviceManager.selectedSpeaker;
Ställa in enheten för användning
// Set the speaker device to use.
await deviceManager.selectSpeaker(localCameras[0]);
Varje CallAgent kan välja sin egen mikrofon och högtalare på sin tillhörande DeviceManager. Vi rekommenderar att olika CallAgents använder olika mikrofoner och högtalare. De bör inte dela samma mikrofoner eller högtalare. Om delning sker kan mikrofonanvändarinriktad diagnostik (UFD) utlösas och mikrofonen slutar fungera beroende på webbläsare och operativsystem.
Lokal videoström
För att användare ska kunna skicka video i ett anrop måste du skapa ett LocalVideoStream objekt.
const localVideoStream = new LocalVideoStream(camera);
Kameran som skickas som parameter är ett VideoDeviceInfo objekt som returneras av deviceManager.getCameras() metoden.
Ett LocalVideoStream har följande egenskaper:
sourceär enhetsinformationen.const source = localVideoStream.source;mediaStreamTypekan varaVideo,ScreenSharing, ellerRawMedia.const type: MediaStreamType = localVideoStream.mediaStreamType;
Förhandsgranskning av lokal kamera
Du kan använda deviceManager och VideoStreamRenderer för att börja rendera strömmar från din lokala kamera.
När du har skapat LocalVideoStreamanvänder du den för att konfigureraVideoStreamRenderer. När du har skapat VideoStreamRenderer, anropar du dess createView()-metod för att hämta en vy som du kan lägga till som ett barn på din sida.
Den här strömmen skickas inte till andra deltagare. Det är ett lokalt förhandsgranskningsflöde.
// 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);
Stoppa den lokala förhandsgranskningen
För att stoppa den lokala förhandsgranskningen, avsluta visningen som härrör från VideoStreamRenderer.
När VideoStreamRenderer tas bort, ta bort vyn från HTML-trädet genom att anropa removeChild()-metoden från DOM-noden som innehåller din förhandsgranskning.
// To stop viewing local camera preview
view.dispose();
htmlElement.removeChild(view.target);
Begär tillstånd för kamera och mikrofon
Ett program kan inte använda kameran eller mikrofonen utan behörighet. Du kan använda enhetshanteraren för att be en användare att ge tillstånd för kamera och/eller mikrofon:
const result = await deviceManager.askDevicePermission({audio: true, video: true});
När löftet har lösts, returnerar metoden ett DeviceAccess objekt som anger om audio och video behörigheter har beviljats.
console.log(result.audio);
console.log(result.video);
Anteckningar
-
videoDevicesUpdatedhändelsen aktiveras när videoutrustning ansluts eller kopplas från. -
audioDevicesUpdatedhändelsen utlöses när ljudenheter ansluts. - När du först skapar
DeviceManagerkänner den inte till några enheter om behörigheter inte har beviljats ännu. Ursprungligen är enhetsnamnet tomt och innehåller inte detaljerad enhetsinformation. Du måste anropaDeviceManager.askPermission(), vilket uppmanar användaren att få åtkomst till enheten. När användaren tillåter åtkomst får enhetshanteraren information om enheterna i systemet, uppdaterar enhetslistor och skickar händelsernaaudioDevicesUpdatedochvideoDevicesUpdated. Om en användare uppdaterar sidan och skapar en enhetshanterare lär sig enhetshanteraren om enheter eftersom användaren tidigare beviljat åtkomst. Den har sina enhetslistor fyllda från början och genererar varkenaudioDevicesUpdatedellervideoDevicesUpdatedhändelser. - Enumerering/val av högtalare stöds inte på Android Chrome, iOS Safari eller macOS Safari.
Ring ett samtal med videokamera
Viktigt
För närvarande stöds endast en utgående lokal videoström.
För att starta ett videosamtal måste du först lista de lokala kamerorna med hjälp av getCameras()-metoden i deviceManager.
Efter att du valt en kamera, använd den för att konstruera en LocalVideoStream instans.
Skicka den inom videoOptions som ett objekt i localVideoStream arrayen till CallAgentstartCall metoden.
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);
- Du kan också delta i ett videosamtal med
CallAgent.join()API, och acceptera och ringa videosamtal medCall.Accept()API. - När ditt samtal ansluter, börjar det automatiskt skicka en videoström från den valda kameran till den andra deltagaren.
Starta och stoppa sändning av lokal video under ett samtal
Starta video
För att starta en video under ett samtal måste du enumerera kamerorna med hjälp av metoden getCameras på objektet deviceManager.
Skapa sedan en ny instans av LocalVideoStream med den önskade kameran och skicka sedan LocalVideoStream-objektet till startVideo-metoden för ett befintligt samtalsobjekt.
const deviceManager = await callClient.getDeviceManager();
const cameras = await deviceManager.getCameras();
const camera = cameras[0]
const localVideoStream = new LocalVideoStream(camera);
await call.startVideo(localVideoStream);
Stoppa video
När du lyckas med att börja skicka video, läggs en LocalVideoStream instans av typ Video till i localVideoStreams samlingen på en samtalsinstans.
Hitta videoströmmen i samtalsobjektet
const localVideoStream = call.localVideoStreams.find( (stream) => { return stream.mediaStreamType === 'Video'} );
Stoppa den lokala videon För att stoppa lokal video under ett samtal, skicka den localVideoStream instans som används för video till stopVideo-metoden av Call:
await call.stopVideo(localVideoStream);
Du kan byta till en annan kameranordning medan du har en aktiv lokal videoström genom att anropa switchSource på den LocalVideoStream-instansen.
const cameras = await callClient.getDeviceManager().getCameras();
const camera = cameras[1];
localVideoStream.switchSource(camera);
Om den angivna videoenheten inte är tillgänglig:
- När du är i ett samtal, om din video är avstängd och du startar video med hjälp av
call.startVideo(), kastar den här metoden ettSourceUnavailableErrorochcameraStartFailedanvändarvänlig diagnostik sätts till sann. - Ett anrop till
localVideoStream.switchSource()-metoden gör attcameraStartFailedsätts till sant. Vår guide för samtalsdiagnostik ger ytterligare information om hur man diagnostiserar samtalsrelaterade problem.
Om du vill kontrollera om den lokala videon är på eller av kan du använda Call metoden isLocalVideoStarted, som returnerar sant eller falskt:
// Check if local video is on or off
call.isLocalVideoStarted;
För att lyssna efter ändringar i den lokala videon kan du prenumerera och avsluta prenumerationen på händelsen isLocalVideoStartedChanged.
// Subscribe to local video event
call.on('isLocalVideoStartedChanged', () => {
// Callback();
});
// Unsubscribe from local video event
call.off('isLocalVideoStartedChanged', () => {
// Callback();
});
Starta och stoppa skärmdelning under ett samtal
För att börja skärmdelning under ett samtal kan du använda den asynkrona metoden startScreenSharing() på ett Call-objekt.
Starta skärmdelning
// Start screen sharing
await call.startScreenSharing();
Anteckning
Att skicka skärmdelning stöds endast för skrivbordswebbläsare.
Hitta skärmdelningen i samlingen av LocalVideoStream
När du har börjat skicka skärmdelning läggs en LocalVideoStream instans av typen ScreenSharing till i localVideoStreams samlingen på samtalsinstansen.
const localVideoStream = call.localVideoStreams.find( (stream) => { return stream.mediaStreamType === 'ScreenSharing'} );
Stoppa skärmdelning
För att stoppa skärmdelningen under ett samtal kan du använda den asynkrona API:n stoptScreenSharing.
// Stop screen sharing
await call.stopScreenSharing();
Kontrollera statusen för skärmdelning
För att kontrollera om skärmdelning är på eller av kan du använda isScreenSharingOn API, som returnerar sant eller falskt.
// Check if screen sharing is on or off
call.isScreenSharingOn;
För att lyssna efter ändringar i skärmdelningen kan du prenumerera och avprenumerera på händelsen isScreenSharingOnChanged.
// Subscribe to screen share event
call.on('isScreenSharingOnChanged', () => {
// Callback();
});
// Unsubscribe from screen share event
call.off('isScreenSharingOnChanged', () => {
// Callback();
});
Viktigt
Denna funktion i Azure Communication Services är för närvarande i förhandsgranskning. Funktioner i förhandsversionen är offentligt tillgängliga och kan användas av alla nya och befintliga Microsoft-kunder.
Förhands-APIs och SDK:er tillhandahålls utan ett servicenivåavtal. Vi rekommenderar att du inte använder dem för produktionsbelastningar. Vissa funktioner kanske inte stöds eller så kan funktionerna vara begränsade.
Mer information finns i Kompletterande villkor för användning av Microsoft Azure-förhandsversioner.
Förhandsgranskning av lokal skärmdelning finns i offentlig förhandsgranskning och är tillgänglig som en del av version 1.15.1-beta.1+.
Lokal skärmdelning förhandsvisning
Du kan använda en VideoStreamRenderer för att börja rendera strömmar från din lokala skärmdelning så att du kan se vad du skickar som en skärmdelningsström.
// 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);
}
});
Visa strömmar för avlägsen deltagares video/skärmdelning
För att rendera en fjärrdeltagares video eller skärmdelning, är det första steget att få en referens till den RemoteVideoStream du vill rendera.
Du kan bara återge en fjärrdeltagare genom att gå igenom matrisen eller videoströmmen (videoStreams) för RemoteParticipant. Samlingen fjärrdeltagare nås via objektet Call .
const remoteVideoStream = call.remoteParticipants[0].videoStreams[0];
const streamType = remoteVideoStream.mediaStreamType;
För att återge RemoteVideoStream måste du prenumerera på dess isAvailableChanged-händelse. Om isAvailable-egenskapen ändras till true, så skickar en fjärrdeltagare en videoström.
När det har hänt, skapa en ny instans av VideoStreamRenderer och skapa sedan en ny VideoStreamRendererView-instans med hjälp av den asynkrona createView-metoden. Du kan sedan fästa view.target på vilket UI-element som helst.
När tillgängligheten för en fjärrström ändras kan du förstöra hela VideoStreamRenderer eller en specifik VideoStreamRendererView. Om du bestämmer dig för att behålla dem, visar vyn en tom videoruta.
// 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 för att styla laddningsindikatorn över den fjärranslutna videoströmmen.
.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); }
}
Fjärrvideokvalitet
Azure Communication Services WebJS SDK innehåller en funktion som heter Optimal Video Count (OVC), med början i version 1.15.1.
Använd den här funktionen för att informera program under körning om hur många inkommande videor från olika deltagare som kan återges optimalt vid ett givet ögonblick i ett gruppsamtal med två (2) eller fler deltagare.
Den här funktionen avslöjar en egenskap optimalVideoCount som ändras dynamiskt under samtalet baserat på nätverkets och hårdvarans kapacitet hos en lokal slutpunkt. Värdet för optimalVideoCount förklarar hur många videor från olika deltagarapplikationer som ska återges vid en given tidpunkt. Applikationerna bör hantera dessa förändringar och uppdatera antalet renderade videor i enlighet med rekommendationen. Det finns en fördröjningsperiod (cirka tio (10) sekunder) mellan varje uppdatering.
Användning
Funktionen optimalVideoCount är en samtalsfunktion. Du behöver göra en referens till funktionen OptimalVideoCount via metoden feature i objektet Call.
Du kan sedan ställa in en lyssnare via on-metoden på OptimalVideoCountCallFeature för att bli informerad när optimalVideoCount ändras. För att avregistrera dig från ändringarna kan du anropa metoden off.
Det maximala antalet inkommande videor som kan renderas för närvarande är 16. För att kunna stödja 16 inkommande videor på rätt sätt behöver datorn minst 16 GB RAM-minne och en fyra (4) kärnor eller större PROCESSOR som är mindre än tre (3) år gamla.
const optimalVideoCountFeature = call.feature(Features.OptimalVideoCount);
optimalVideoCountFeature.on('optimalVideoCountChanged', () => {
const localOptimalVideoCountVariable = optimalVideoCountFeature.optimalVideoCount;
})
Exempel på användning: Ditt program prenumererar på ändringar av Optimalt videoantal i gruppanrop. En ändring av det optimala videoantalet hanteras genom att antingen skapa en ny återgivningsmetod createView eller ta bort vyer dispose och uppdatera programlayouten i enlighet med detta.
Egenskaper för fjärrvideoström
Fjärrvideoströmmar har följande egenskaper:
const id: number = remoteVideoStream.id;
-
id: ID för en fjärrvideoström.
const type: MediaStreamType = remoteVideoStream.mediaStreamType;
-
mediaStreamType: Kan varaVideoellerScreenSharing.
const isAvailable: boolean = remoteVideoStream.isAvailable;
-
isAvailable: Definierar om en fjärrdeltagande slutpunkt aktivt skickar en ström.
const isReceiving: boolean = remoteVideoStream.isReceiving;
isReceiving:Informerar applikationen om fjärrvideo-strömdata tas emot eller inte.
Flaggan flyttas till
falsei följande scenarier:- En deltagare på distans som använder en mobil webbläsare flyttar webbläsarappen till bakgrunden.
- En deltagare på distans eller användaren som tar emot videon har nätverksproblem som påverkar videokvaliteten avsevärt.
- En fjärrdeltagare som använder macOS/iOS Safari väljer "Pausa" från adressfältet.
- En fjärrdeltagare har en nätverksfrånkoppling.
- En fjärrdeltagare på mobil dödar eller avslutar webbläsaren.
- En fjärrdeltagare på mobil eller stationär dator låser sin enhet. Denna situation gäller även om den fjärranslutna deltagaren är på en stationär dator och den går i viloläge.
Flaggan flyttas till
truei följande scenarier:- En deltagare på distans som använder en mobil webbläsare och vars webbläsare har befunnit sig i bakgrunden återställer den till förgrunden.
- En fjärrdeltagare som är På macOS/iOS Safari väljer Återuppta från adressfältet efter att ha pausat videon.
- En fjärrdeltagare återansluter till nätverket efter ett tillfälligt avbrott.
- En fjärra deltagare på mobil låser upp sin enhet och återvänder till samtalet på sin mobila webbläsare.
Denna funktion förbättrar användarupplevelsen vid rendering av fjärrvideoströmmar.
Du kan visa en laddningsindikator över den fjärrstyrda videoströmmen när isReceiving-flaggan ändras till falsk. Du behöver inte implementera en laddningssnurra, men en laddningssnurra är det vanligaste sättet att förbättra användarupplevelsen.
const size: StreamSize = remoteVideoStream.size;size: Strömstorleken med information om videons bredd och höjd.
VideoStreamRenderer-metoder och egenskaper
await videoStreamRenderer.createView();
Skapa en VideoStreamRendererView-instans som kan fästas i applikationens användargränssnitt för att återge den fjärrstyrda videoströmmen. Använd den asynkrona createView()-metoden, som löser sig när strömmen är redo att återges och returnerar ett objekt med egenskapen target, som representerar ett video-element som kan infogas var som helst i DOM-trädet.
videoStreamRenderer.dispose();
Avyttra videoStreamRenderer och alla associerade VideoStreamRendererView instanser.
VideoStreamRendererView metoder och egenskaper
När du skapar en VideoStreamRendererView kan du specificera egenskaperna scalingMode och isMirrored.
scalingMode kan vara Stretch, Crop, eller Fit. Om isMirrored anges, vänds den renderade strömmen vertikalt.
const videoStreamRendererView: VideoStreamRendererView = await videoStreamRenderer.createView({ scalingMode, isMirrored });
Varje VideoStreamRendererView instans har en target egenskap som representerar renderingsytan. Fäst den här egenskapen i applikationens UI:
htmlElement.appendChild(view.target);
Du kan uppdatera scalingMode genom att anropa metoden updateScalingMode:
view.updateScalingMode('Crop');
Skicka videoströmmar från två olika kameror, i samma samtal från samma skrivbordsenhet.
Viktigt
Denna funktion i Azure Communication Services är för närvarande i förhandsgranskning. Funktioner i förhandsversionen är offentligt tillgängliga och kan användas av alla nya och befintliga Microsoft-kunder.
Förhands-APIs och SDK:er tillhandahålls utan ett servicenivåavtal. Vi rekommenderar att du inte använder dem för produktionsbelastningar. Vissa funktioner kanske inte stöds eller så kan funktionerna vara begränsade.
Mer information finns i Kompletterande villkor för användning av Microsoft Azure-förhandsversioner.
Skicka videoströmmar från två olika kameror i samma samtal stöds som en del av version 1.17.1-beta.1+ på skrivbordsstödda webbläsare.
Du kan skicka videoströmmar från två olika kameror från en enda skrivbordswebbläsares flik/app, i samma anrop, med följande kodfragment:
// 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();
Begränsningar:
- Sändning av videoströmmar måste göras med två olika
CallAgentinstanser med olika identiteter. Kodsnutten visar två call-agenter som används, var och en med sitt eget Call-objekt. - I kodexemplet ansluter båda CallAgents till samma anrop (samma anrops-ID). Du kan också delta i olika samtal med varje agent och skicka en video på ett samtal och en annan video på ett annat samtal.
- Det går inte att skicka samma kamera i båda CallAgents. De måste vara två olika kameror.
- Att skicka två olika kameror med en CallAgent stöds för närvarande inte.
- På macOS Safari kan bakgrundsoskärpa videoeffekter (från @azure/communication-effects)) endast tillämpas på en kamera och inte på båda samtidigt.
Installera SDK:en
Lokalisera din projektfil på nivå build.gradle och lägg till mavenCentral() till listan över förvar under buildscript och allprojects.
buildscript {
repositories {
...
mavenCentral()
...
}
}
allprojects {
repositories {
...
mavenCentral()
...
}
}
Sedan, i din fil på modulnivå build.gradle, lägg till följande rader i dependencies-avsnittet.
dependencies {
...
implementation 'com.azure.android:azure-communication-calling:1.0.0'
...
}
Initiera de nödvändiga objekten
För att skapa en CallAgent-instans måste du anropa metoden createCallAgent på en CallClient-instans. Det här anropet returnerar asynkront ett CallAgent instansobjekt.
createCallAgent-metoden tar CommunicationUserCredential som ett argument, vilket kapslar in en åtkomsttoken.
För att få tillgång till DeviceManager måste du först skapa en callAgent instans. Då kan du använda CallClient.getDeviceManager-metoden för att få 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();
För att ställa in ett visningsnamn för den uppringande, använd denna alternativa metod:
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();
Enhetshantering
Om du vill använda video med Samtal måste du hantera enheter. Med hjälp av enheter kan du styra vad som överför ljud och video till samtalet.
Med DeviceManager objektet kan du räkna upp lokala enheter som ska användas i ett anrop för att överföra dina ljud-/videoströmmar. Du kan också begära behörighet från en användare för att få åtkomst till deras mikrofon och kamera med hjälp av det interna webbläsar-API:et.
För att komma åt deviceManager, anropa metoden för callClient.getDeviceManager().
Context appContext = this.getApplicationContext();
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
Uppräkna lokala enheter
Om du vill komma åt lokala enheter använder du uppräkningsmetoder i Enhetshanteraren. Uppräkning är en synkron åtgärd.
// Get a list of available video devices for use.
List<VideoDeviceInfo> localCameras = deviceManager.getCameras(); // [VideoDeviceInfo, VideoDeviceInfo...]
Förhandsgranskning av lokal kamera
Du kan använda DeviceManager och Renderer för att börja rendera strömmar från din lokala kamera. Den här strömmen skickas inte till andra deltagare. Det är ett lokalt förhandsgranskningsflöde. Att rendera en ström är en asynkron åtgärd.
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);
Anslut ett 1:1-videosamtal med kamera
Varning
För närvarande stöds endast en utgående lokal videoström. Om du vill ringa ett samtal med video måste du räkna upp lokala kameror med hjälp av API:et deviceManagergetCameras .
När du har valt en kamera använder du den för att konstruera en LocalVideoStream instans och skicka den till videoOptions som ett objekt i matrisen localVideoStream till en call metod. När samtalet ansluter börjar det automatiskt skicka en videoström från den valda kameran till andra deltagare.
Anteckning
På grund av sekretessproblem delas inte video till samtalet om det inte förhandsgranskas lokalt. Mer information finns i Lokal kameraförhandsgranskning.
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);
Starta och stoppa sändning av lokal video
Om du vill starta en video måste du räkna upp kameror med hjälp av getCameraList åtgärden på deviceManager objektet. Skapa sedan en ny instans av LocalVideoStream genom att skicka in den önskade kameran, och använd den som ett argument i startVideo API:t.
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();
När du har börjat skicka video läggs en LocalVideoStream instans till i localVideoStreams samlingen på samtalsinstansen.
List<LocalVideoStream> videoStreams = call.getLocalVideoStreams();
LocalVideoStream currentLocalVideoStream = videoStreams.get(0); // Please make sure there are VideoStreams in the list before calling get(0).
För att stoppa den lokala videon, skicka instansen LocalVideoStream tillgänglig i localVideoStreams-kollektionen.
call.stopVideo(appContext, currentLocalVideoStream).get();
Du kan växla till en annan kameraenhet medan video skickas genom att switchSource anropa på en LocalVideoStream instans:
currentLocalVideoStream.switchSource(source).get();
Rendera videoströmmar för fjärrdeltagare
För att lista videoströmmarna och skärmdelningsströmmarna för fjärrdeltagare, inspektera videoStreams-samlingarna.
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
För att rendera en RemoteVideoStream från en fjärrdeltagare måste du prenumerera på en OnVideoStreamsUpdated-händelse.
Inom händelsen indikerar ändringen av isAvailable-egenskapen till sant att den avlägsna deltagaren för närvarande skickar en ström. När det sker, skapa en ny instans av en Renderer, skapa sedan en ny RendererView med hjälp av den asynkrona createView API:n och fäst view.target var som helst i användargränssnittet på din applikation.
När tillgängligheten för en fjärrström ändras kan du välja att förstöra hela Renderer, en specifik RendererView eller behålla dem, men resulterar i att visa en tom videoram.
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();
}
}
}
Egenskaper för fjärrvideoström
Fjärrvideoström har följande egenskaper:
Id– ID för en fjärrvideoström.int id = remoteVideoStream.getId();MediaStreamType- Kan varaVideoellerScreenSharing.MediaStreamType type = remoteVideoStream.getMediaStreamType();isAvailable– Anger om fjärrdeltagarens slutpunkt aktivt skickar ström.boolean availability = remoteVideoStream.isAvailable();
Renderingsmetoder och -egenskaper
Objektet Renderer använder följande metoder.
Om du vill återge fjärrvideoström skapar du en
VideoStreamRendererViewinstans som kan kopplas senare i programgränssnittet.// Create a view for a video stream VideoStreamRendererView.createView()Kassera renderaren och alla
VideoStreamRendererViewsom är associerade med denna renderare. Anropa den när du har tagit bort alla associerade vyer från användargränssnittet.VideoStreamRenderer.dispose()Om du vill ange storleken (bredd/höjd) för en fjärransluten videoström använder du
StreamSize.StreamSize renderStreamSize = VideoStreamRenderer.getSize(); int width = renderStreamSize.getWidth(); int height = renderStreamSize.getHeight();
RendererView-metoder och egenskaper
När du skapar en VideoStreamRendererViewkan du ange egenskaperna ScalingMode och mirrored som gäller för den här vyn.
Skalningsläget kan vara antingen en av CROP eller FIT.
VideoStreamRenderer remoteVideoRenderer = new VideoStreamRenderer(remoteVideoStream, appContext);
VideoStreamRendererView rendererView = remoteVideoRenderer.createView(new CreateViewOptions(ScalingMode.Fit));
Den skapade RendererView kan sedan fästas till applikationens användargränssnitt med hjälp av följande kodsnutt:
layout.addView(rendererView);
Du kan senare uppdatera skalningsläget med hjälp av updateScalingMode åtgärden på RendererView objektet med argumentet antingen ScalingMode.CROP eller ScalingMode.FIT.
// Update the scale mode for this view.
rendererView.updateScalingMode(ScalingMode.CROP)
Ställ in ditt system
Följ dessa steg för att ställa in ditt system.
Skapa Xcode-projektet
I Xcode skapar du ett nytt iOS-projekt och väljer mallen för en Enkelvyapp. Denna artikel använder SwiftUI-ramverket, så du bör ställa in Språk till Swift och ställa in Gränssnitt till SwiftUI.
Du kommer inte att skapa tester i den här artikeln. Du kan gärna avmarkera kryssrutan för "Inkludera tester".
Installera paketet och dess beroenden med hjälp av CocoaPods
Skapa en Podfile för din applikation, som i detta exempel:
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 1.0.0' endKör
pod install.Öppna
.xcworkspacemed hjälp av Xcode.
Begär tillgång till mikrofonen
För att komma åt enhetens mikrofon behöver du uppdatera informationslistan för din app genom att använda NSMicrophoneUsageDescription. Ställ in det associerade värdet till en sträng som inkluderas i dialogrutan som systemet använder för att begära åtkomst från användaren.
Högerklicka på Info.plist-posten i projektträdet och välj sedan Öppna som>Källkod. Lägg till följande rader i avsnittet på toppnivå <dict> och spara sedan filen.
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>
Ställ in appens ramverk
Öppna din projekts ContentView.swift-fil. Lägg till en import-deklaration längst upp i filen för att importera AzureCommunicationCalling-biblioteket. Dessutom, importera AVFoundation. Du behöver det för ljudtillståndsförfrågningar i koden.
import AzureCommunicationCalling
import AVFoundation
Initiera samtalsagent
För att skapa en CallAgent instans från CallClient måste du använda en callClient.createCallAgent metod som asynkront returnerar ett CallAgent objekt efter att det har initierats.
För att skapa en samtalsklient, överför ett CommunicationTokenCredential objekt:
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)
}
Skicka objektet CommunicationTokenCredential som du skapade till CallClient, och ställ in visningsnamnet.
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")
}
})
Hantera enheter
Om du vill börja använda video med Samtal behöver du veta hur du hanterar enheter. Med enheter kan du styra vad som överför ljud och video till samtalet.
DeviceManager låter dig enumerera lokala enheter som kan användas i ett samtal för att överföra ljud- eller videoströmmar. Du kan också begära behörighet från en användare för att få åtkomst till en mikrofon eller kamera. Du kan komma åt deviceManager på callClient-objektet.
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")
}
}
Uppräkna lokala enheter
För att få tillgång till lokala enheter kan du använda uppräkningsmetoder i enhetshanteraren. Uppräkning är en synkron åtgärd.
// enumerate local cameras
var localCameras = deviceManager.cameras // [VideoDeviceInfo, VideoDeviceInfo...]
Få en lokal kameraförhandsvisning
Du kan använda Renderer för att börja rendera en ström från din lokala kamera. Den här strömmen sänds inte till andra deltagare; det är en lokal förhandsgranskningssändning. Detta är en asynkron handling.
let camera: VideoDeviceInfo = self.deviceManager!.cameras.first!
let localVideoStream = LocalVideoStream(camera: camera)
let localRenderer = try! VideoStreamRenderer(localVideoStream: localVideoStream)
self.view = try! localRenderer.createView()
Hämta egenskaper för lokal kameraförhandsvisning
Renderaren innehåller en uppsättning egenskaper och metoder som gör att du kan styra återgivningen.
// 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()
Ringa ett 1:1-samtal med video
Information om hur du hämtar en instans av enhetshanteraren finns i avsnittet om att hantera enheter.
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")
}
}
Rendera videoströmmar för fjärrdeltagare
Fjärrdeltagare kan initiera video- eller skärmdelning under ett samtal.
Hantera videodelnings- eller skärmdelningsströmmar för fjärranslutna deltagare
För att lista strömmarna av fjärranslutna deltagare, inspektera videoStreams-samlingarna.
var remoteParticipantVideoStream = call.remoteParticipants[0].videoStreams[0]
Hämta egenskaper för fjärrvideoström
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
Rendera strömmar från fjärrdeltagare
Om du vill börja återge fjärrdeltagareströmmar använder du följande kod.
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)
Skaffa fjärrvideorenderarens metoder och egenskaper
// [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()
Ställ in ditt system
Följ dessa steg för att ställa in ditt system.
Skapa Visual Studio-projektet
För en Universal Windows Platform-app skapar du i Visual Studio 2022 ett nytt Blank App (Universal Windows)-projekt. När du har angett projektnamnet, kan du välja vilken Windows SDK som helst senare än 10.0.17763.0.
För en WinUI 3-app, skapa ett nytt projekt med mallen Blank App, Packaged (WinUI 3 in Desktop) för att ställa in en en-sidig WinUI 3-app. Windows App SDK version 1.3 eller senare krävs.
Installera paketet och dess beroenden genom att använda NuGet-pakethanteraren
API:erna och biblioteken för Calling SDK är allmänt tillgängliga via ett NuGet-paket.
För att hitta, ladda ner och installera Calling SDK NuGet-paketet:
- Öppna NuGet Package Manager genom att välja Verktyg>NuGet Package Manager>Hantera NuGet-paket för lösning.
- Välj Bläddra, och skriv sedan in Azure.Communication.Calling.WindowsClient i sökrutan.
- Se till att kryssrutan Inkludera förhandsversion är markerad.
- Välj paketet Azure.Communication.Calling.WindowsClient, och välj sedan Azure.Communication.Calling.WindowsClient1.4.0-beta.1 eller en nyare version.
- Markera kryssrutan som motsvarar Azure Communication Services-projektet på den högra panelen.
- Välj Installera.
Begär tillgång till mikrofonen
Appen kräver åtkomst till kameran. I UWP-appar (Universal Windows Platform) måste du deklarera kamerafunktionen i appmanifestfilen.
- Öppna projektet i Visual Studio.
- Dubbelklicka på filen med tillägget i
.appxmanifest. - Klicka på fliken Funktioner .
- Välj kryssrutan
Camerafrån listan över funktioner.
Skapa UI-knappar för att placera och avsluta samtalet
Den här exempelappen innehåller två knappar. En för att ringa samtalet och en annan för att lägga på ett anslutet samtal.
- Dubbelklicka på filen med namnet UWP i
MainPage.xamlellerMainWindows.xamlför WinUI 3. - I det centrala panelområdet, leta efter XAML-koden under UI-förhandsgranskningen.
- Ändra XAML-koden med hjälp av följande utdrag:
<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>
Installera appen med Calling SDK API:er
The Calling SDK-API:erna finns i två olika namnutrymmen.
Slutför följande steg för att informera C#-kompilatorn om dessa namnområden, så att Visual Studio Intellisense kan hjälpa till med kodutveckling.
- I panelen Solution Explorer klickar du på pilen till vänster i filen med namnet
MainPage.xamlför UWP ellerMainWindows.xamlför WinUI 3. - Dubbelklicka på filen som heter
MainPage.xaml.csellerMainWindows.xaml.cs. - Lägg till följande kommandon längst ner i de befintliga
using-uttalandena.
using Azure.Communication.Calling.WindowsClient;
Håll MainPage.xaml.cs eller MainWindows.xaml.cs öppen. Nästa steg lägger till mer kod.
Aktivera appinteraktioner
De användargränssnittsknappar som vi lade till måste fungera ovanpå en placerad CommunicationCall. Det innebär att du måste lägga till en CommunicationCall datamedlem i MainPage klassen eller MainWindow .
Du måste också möjliggöra att den asynkrona operationen som skapar CallAgent ska lyckas. Lägg till en CallAgent datamedlem i samma klass.
Lägg till följande datamedlemmar i MainPage- eller MainWindow-klassen:
CallAgent callAgent;
CommunicationCall call;
Skapa knapphanterare
Tidigare lade vi till två användargränssnittsknappar i XAML-koden. Följande kod lägger till de hanterare som ska köras när en användare väljer knappen.
Lägg till följande kod efter datamedlemmarna från föregående avsnitt.
private async void CallButton_Click(object sender, RoutedEventArgs e)
{
// Start call
}
private async void HangupButton_Click(object sender, RoutedEventArgs e)
{
// End the current call
}
Objektmodell
Följande klasser och gränssnitt hanterar några av de viktigaste funktionerna i Azure Communication Services Calling-klientbiblioteket för UWP.
| Namn | Beskrivning |
|---|---|
CallClient |
CallClient är huvudingången till klientbiblioteket för samtal. |
CallAgent |
CallAgent Används för att starta och ansluta anrop. |
CommunicationCall |
CommunicationCall används för att hantera placerade eller anslutna samtal. |
CommunicationTokenCredential |
CommunicationTokenCredential används som tokenreferens för att instansiera CallAgent. |
CallAgentOptions |
CallAgentOptions innehåller information för att identifiera uppringaren. |
HangupOptions |
HangupOptions informerar om en samtal ska avslutas för alla deltagare. |
Registrera videoschemahanterare
En UI-komponent, till exempel XAML:s MediaElement eller MediaPlayerElement, kräver att appen registrerar en konfiguration för återgivning av lokala och fjärranslutna videoflöden.
Lägg till följande innehåll mellan Package-taggarna i Package.appxmanifest:
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
Initiera CallAgent
För att skapa en CallAgent instans från CallClient måste du använda CallClient.CreateCallAgentAsync metoden som asynkront returnerar ett CallAgent objekt när det är initierat.
För att skapa CallAgent måste du skicka ett CallTokenCredential-objekt och ett CallAgentOptions-objekt. Kom ihåg att CallTokenCredential kastar ett undantag om ett felaktigt token skickas.
Lägg till följande kod i hjälpfunktionen och så att den körs under initieringen.
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;
Byt ut <AUTHENTICATION_TOKEN> mot en giltig autentiseringstoken för din resurs. Mer information om hur du hämtar en token för autentiseringsuppgifter finns i användaråtkomsttoken.
Anslut ett 1:1-videosamtal med kamera
De objekt som behövs för att skapa en CallAgent är nu redo. Skapa CallAgent asynkront och starta ett videosamtal.
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 } }
};
}
Förhandsgranskning av lokal kamera
Vi kan valfritt ställa in lokal kameraförhandsvisning. Du kan återge videon via MediaPlayerElement:
<Grid>
<MediaPlayerElement x:Name="LocalVideo" AutoPlay="True" />
<MediaPlayerElement x:Name="RemoteVideo" AutoPlay="True" />
</Grid>
För att initiera den lokala förhandsvisningen MediaPlayerElement:
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);
}
}
Återge fjärrkameraström
Ställ in händelsehanterare för att svara på OnCallsUpdated-händelsen:
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;
}
}
Börja rendera fjärrvideoström på 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;
}
}
Avsluta ett samtal
När ett anrop har ringts använder du HangupAsync -metoden för CommunicationCall objektet för att lägga på anropet.
Använd en instans av HangupOptions för att informera deltagarna om samtalet måste avslutas.
Lägg till följande kod i 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;
}
}
}
}
Kör koden
- Se till att Visual Studio skapar appen för
x64,x86ellerARM64. - Tryck på F5 för att börja köra appen.
- Klicka på knappen CommunicationCall för att ringa ett anrop till den definierade mottagaren.
Första gången appen körs uppmanar systemet användaren att bevilja åtkomst till mikrofonen.