Kom igång med exemplet med anropande hero

Azure Communication Services Group Calling Hero-exemplet visar hur Web SDK för kommunikationstjänster som anropar webb kan användas för att skapa en gruppsamtalsupplevelse.

I den här exempelsnabbstarten lär vi oss hur exemplet fungerar innan vi kör exemplet på den lokala datorn och distribuerar sedan exemplet till Azure med dina egna Azure Communication Services-resurser.

Ladda ned kod

Hitta projektet för det här exemplet på GitHub. En version av exemplet som innehåller funktioner som för närvarande finns i offentlig förhandsversion, till exempel Teams Interop och Samtalsinspelning , finns på en separat gren.

Distribuera till Azure

Översikt

Exemplet har både ett program på klientsidan och ett program på serversidan. Programmet på klientsidan är ett React/Redux-webbprogram som använder Microsofts Fluent UI-ramverk. Det här programmet skickar begäranden till ett ASP.NET Core-program på serversidan som hjälper programmet på klientsidan att ansluta till Azure.

Så här ser exemplet ut:

Skärmbild som visar exempelprogrammets landningssida.

När du trycker på knappen Starta ett anrop hämtar webbprogrammet en användaråtkomsttoken från programmet på serversidan. Den här token används sedan för att ansluta klientappen till Azure Communication Services. När token har hämtats uppmanas du att ange den kamera och mikrofon som du vill använda. Du kan inaktivera/aktivera dina enheter med växlingskontroller:

Skärmbild som visar föranropsskärmen för exempelprogrammet.

När du har konfigurerat visningsnamnet och enheterna kan du ansluta till samtalssessionen. Du kommer att se huvudsamtalsarbetsytan där kärnsamtalsupplevelsen finns.

Skärmbild som visar huvudskärmen i exempelprogrammet.

Komponenter i huvudsamtalsskärmen:

  • Mediegalleri: Huvudscenen där deltagarna visas. Om en deltagare har sin kamera aktiverad visas deras videoflöde här. Varje deltagare har en enskild panel som visar deras visningsnamn och videoström (när det finns en)
  • Rubrik: Det är här de primära anropskontrollerna finns för att växla inställningar och deltagarpanelen, aktivera/inaktivera video och blanda, dela skärmen och lämna samtalet.
  • Sidofält: Här visas information om deltagare och inställningar när de växlas med hjälp av kontrollerna i rubriken. Komponenten kan stängas med hjälp av X i det övre högra hörnet. Deltagarnas sidofält visar en lista över deltagare och en länk för att bjuda in fler användare att chatta. Inställningar sidofältet kan du konfigurera mikrofon- och kamerainställningar.

Nedan hittar du mer information om förutsättningar och steg för att konfigurera exemplet.

Förutsättningar

Innan du kör exemplet för första gången

  1. Öppna en instans av PowerShell, Windows-terminal, kommandotolken eller motsvarande och navigera till katalogen som du vill klona exemplet till.

    git clone https://github.com/Azure-Samples/communication-services-web-calling-hero.git
    
  2. Connection String Hämta från Azure-portalen eller med hjälp av Azure CLI.

    az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
    

    Mer information om anslutningssträng finns i Skapa en Azure-kommunikationsresurser

  3. När du har hämtat Connection Stringlägger du till anslutningssträng i filen samples/Server/appsetting.json. Ange din anslutningssträng i variabeln: ResourceConnectionString.

  4. Endpoint string Hämta från Azure-portalen eller med hjälp av Azure CLI.

    az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
    

    Mer information om slutpunktssträngar finns i Skapa en Azure-kommunikationsresurser

  5. När du har hämtat Endpoint Stringlägger du till slutpunktssträngen i filen samples/Server/appsetting.json . Ange din slutpunktssträng i variabeln EndpointUrl

Lokal körning

  1. Installera beroenden

    npm run setup
    
  2. Starta den anropande appen

    npm run start
    

    Då öppnas en klientserver på port 3000 som hanterar webbplatsfilerna och en API-server på port 8080 som utför funktioner som minting-token för samtalsdeltagare.

Felsökning

  • Appen visar en "webbläsare som inte stöds" men jag finns i en webbläsare som stöds.

    Om din app hanteras över ett annat värdnamn än localhost måste du hantera trafik via https och inte http.

Publicera till Azure

  1. npm run setup
  2. npm run build
  3. npm run package
  4. Använd Azure-tillägget och distribuera katalogen Calling/dist till din apptjänst

Rensa resurser

Om du vill rensa och ta bort en Communication Services-prenumeration kan du ta bort resursen eller resursgruppen. Om du tar bort resursgruppen tas även alla andra resurser som är associerade med den bort. Läs mer om att rensa resurser.

Nästa steg

Mer information finns i följande artiklar:

Mer att läsa

  • Exempel – Hitta fler exempel och exempel på översiktssidan för våra exempel.
  • Redux – Tillståndshantering på klientsidan
  • FluentUI – Microsofts drivna användargränssnittsbibliotek
  • React – Bibliotek för att skapa användargränssnitt
  • ASP.NET Core – Ramverk för att skapa webbprogram

Azure Communication Services Group Calling Hero Sample för iOS visar hur Communication Services Calling iOS SDK kan användas för att skapa en gruppsamtalsupplevelse som innehåller röst och video. I den här exempelsnabbstarten får du lära dig hur du konfigurerar och kör exemplet. En översikt över exemplet tillhandahålls för kontexten.

Ladda ned kod

Hitta projektet för det här exemplet på GitHub.

Översikt

Exemplet är ett internt iOS-program som använder Azure Communication Services iOS SDK:er för att skapa en samtalsupplevelse som innehåller både röst- och videosamtal. Programmet använder en komponent på serversidan för att etablera åtkomsttoken som sedan används för att initiera Azure Communication Services SDK. Om du vill konfigurera den här komponenten på serversidan kan du följa självstudien Betrodd tjänst med Azure Functions .

Så här ser exemplet ut:

Skärmbild som visar exempelprogrammets landningssida.

När du trycker på knappen "Starta nytt anrop" uppmanar iOS-programmet dig att ange ditt visningsnamn som ska användas för samtalet.

Skärmbild som visar föranropsskärmen för exempelprogrammet.

När du har tryckt på Nästa på skärmen "Starta samtal" har du möjlighet att dela grupp-ID:t för samtalet via iOS-resursbladet.

Skärmbild som visar skärmen dela grupp-ID för exempelprogrammet.

Med programmet kan du också ansluta till ett befintligt Azure Communication Services-anrop genom att ange det befintliga anropets ID- eller teams-ID-länk.

Skärmbild som visar skärmen för kopplingsanrop i exempelprogrammet.

När du har anslutit till ett samtal uppmanas du att ge programmet behörighet att komma åt kameran och mikrofonen, om den inte redan är auktoriserad. Tänk på att precis som alla AVFoundation-baserade appar är sann ljud- och videofunktion endast tillgänglig på verklig maskinvara.

När du har konfigurerat visningsnamnet och ansluter till samtalet ser du huvudsamtalsarbetsytan där kärnsamtalsupplevelsen finns.

Skärmbild som visar huvudskärmen i exempelprogrammet.

Komponenter i huvudsamtalsskärmen:

  • Mediegalleri: Huvudscenen där deltagarna visas. Om en deltagare har sin kamera aktiverad visas deras videoflöde här. Varje deltagare har en enskild panel som visar deras visningsnamn och videoström (när det finns en). Galleriet stöder flera deltagare och uppdateras när deltagarna läggs till eller tas bort i anropet.
  • Åtgärdsfält: Här finns de primära anropskontrollerna. Med de här kontrollerna kan du aktivera/inaktivera video och mikrofon, dela skärmen och lämna samtalet.

Nedan hittar du mer information om förutsättningar och steg för att konfigurera exemplet.

Förutsättningar

  • Ett Azure-konto med en aktiv prenumeration. Mer information finns i Skapa ett konto kostnadsfritt.
  • En Mac som kör Xcode, tillsammans med ett giltigt utvecklarcertifikat installerat i nyckelringen.
  • En Azure Communication Services-resurs. Mer information finns i Skapa en Azure Communication Services-resurs.
  • En Azure-funktion som kör autentiseringsslutpunkten för att hämta åtkomsttoken.

Köra exempel lokalt

Gruppsamtalsexemplet kan köras lokalt med XCode. Utvecklare kan antingen använda sin fysiska enhet eller en emulator för att testa programmet.

Innan du kör exemplet för första gången

  1. Installera beroenden genom att köra pod install.
  2. Öppna AzureCalling.xcworkspace i XCode.
  3. Skapa en textfil i roten med namnet AppSettings.xcconfig och ange värdet:
    communicationTokenFetchUrl = <your authentication endpoint, without the https:// component>
    

Kör exempel

Skapa och kör exemplet i XCode med hjälp av AzureCalling-målet på valfri simulator eller enhet.

(Valfritt) Skydda en autentiseringsslutpunkt

I demonstrationssyfte använder det här exemplet en offentligt tillgänglig slutpunkt som standard för att hämta en Azure Communication Services-åtkomsttoken. För produktionsscenarier rekommenderar vi att du använder din egen skyddade slutpunkt för att etablera egna token.

Med ytterligare konfiguration stöder det här exemplet anslutning till en Microsoft Entra-ID (Microsoft Entra ID) skyddad slutpunkt så att användarinloggning krävs för att appen ska kunna hämta en Åtkomsttoken för Azure Communication Services. Se stegen nedan:

  1. Aktivera Microsoft Entra-autentisering i din app.
  2. Gå till översiktssidan för din registrerade app under Microsoft Entra-appregistreringar. Anteckna Application (client) ID, , Directory (tenant) IDApplication ID URI

Microsoft Entra-konfiguration på Azure-portalen.

  1. Skapa en AppSettings.xcconfig fil i roten om den inte redan finns och lägg till värdena:
    communicationTokenFetchUrl = <Application ID URI, without the https:// component>
    aadClientId = <Application (client) ID>
    aadTenantId = <Directory (tenant) ID>
    

Rensa resurser

Om du vill rensa och ta bort en Communication Services-prenumeration kan du ta bort resursen eller resursgruppen. Om du tar bort resursgruppen tas även alla andra resurser som är associerade med den bort. Läs mer om att rensa resurser.

Nästa steg

Mer information finns i följande artiklar:

Mer att läsa

Azure Communication Services Group Calling Hero-exemplet för Android visar hur Communication Services Calling Android SDK kan användas för att skapa en gruppsamtalsupplevelse som innehåller röst och video. I den här exempelsnabbstarten får du lära dig hur du konfigurerar och kör exemplet. En översikt över exemplet tillhandahålls för kontexten.

Ladda ned kod

Hitta projektet för det här exemplet på GitHub.

Översikt

Exemplet är ett internt Android-program som använder Azure Communication Services Android UI-klientbiblioteket för att skapa en samtalsupplevelse som innehåller både röst- och videosamtal. Programmet använder en komponent på serversidan för att etablera åtkomsttoken som sedan används för att initiera Azure Communication Services SDK. Om du vill konfigurera den här komponenten på serversidan kan du följa självstudien Betrodd tjänst med Azure Functions .

Så här ser exemplet ut:

Skärmbild som visar exempelprogrammets landningssida.

När du trycker på knappen "Starta nytt anrop" uppmanar Android-programmet dig att ange ditt visningsnamn som ska användas för samtalet.

Skärmbild som visar föranropsskärmen för exempelprogrammet.

När du har tryckt på Nästa på sidan "Starta ett samtal" har du möjlighet att dela "Gruppsamtals-ID".

Skärmbild som visar skärmen dela gruppsamtals-ID för exempelprogrammet.

Med programmet kan du ansluta till ett befintligt Azure Communication Services-anrop genom att ange det befintliga samtalets ID eller teams mötes-ID-länk och visningsnamn.

Skärmbild som visar skärmen för kopplingsanrop i exempelprogrammet.

När du har anslutit till ett samtal uppmanas du att ge programmet behörighet att komma åt kameran och mikrofonen, om den inte redan är auktoriserad. Du ser huvudsamtalsarbetsytan där kärnsamtalsupplevelsen finns.

Skärmbild som visar huvudskärmen i exempelprogrammet.

Komponenter i huvudsamtalsskärmen:

  • Mediegalleri: Huvudscenen där deltagarna visas. Om en deltagare har sin kamera aktiverad visas deras videoflöde här. Varje deltagare har en enskild panel som visar deras visningsnamn och videoström (när det finns en). Galleriet stöder flera deltagare och uppdateras när deltagarna läggs till eller tas bort i anropet.
  • Åtgärdsfält: Här finns de primära anropskontrollerna. Med de här kontrollerna kan du aktivera/inaktivera video och mikrofon, dela skärmen och lämna samtalet.

Nedan hittar du mer information om förutsättningar och steg för att konfigurera exemplet.

Förutsättningar

Köra exempel lokalt

Gruppsamtalsexemplet kan köras lokalt med Android Studio. Utvecklare kan antingen använda sin fysiska enhet eller en emulator för att testa programmet.

Innan du kör exemplet för första gången

  1. Öppna Android Studio och välj Open an Existing Project
  2. Öppna mappen i den AzureCalling nedladdade versionen för exemplet.
  3. Expandera app/tillgångar för att uppdatera appSettings.properties. Ange värdet för nyckeln communicationTokenFetchUrl som URL för din autentiseringsslutpunkt som konfigurerats som en förutsättning.

Kör exempel

Skapa och kör exemplet i Android Studio.

(Valfritt) Skydda en autentiseringsslutpunkt

I demonstrationssyfte använder det här exemplet en offentligt tillgänglig slutpunkt som standard för att hämta en Azure Communication Services-token. För produktionsscenarier rekommenderar vi att du använder din egen skyddade slutpunkt för att etablera egna token.

Med ytterligare konfiguration stöder det här exemplet anslutning till en Microsoft Entra-ID (Microsoft Entra ID) skyddad slutpunkt så att användarinloggning krävs för att appen ska kunna hämta en Azure Communication Services-token. Se stegen nedan:

  1. Aktivera Microsoft Entra-autentisering i din app.

  2. Gå till översiktssidan för din registrerade app under Microsoft Entra-appregistreringar. Anteckna Package name, Signature hash, MSAL Configutaion.

Microsoft Entra-konfiguration på Azure-portalen.

  1. Redigera AzureCalling/app/src/main/res/raw/auth_config_single_account.json och ange isAADAuthEnabled för att aktivera Microsoft Entra-ID.

  2. Redigera AndroidManifest.xml och ange android:path till nyckellagringssignaturshash. (Valfritt. Det aktuella värdet använder hash från bundled debug.keystore. Om ett annat nyckelarkiv används måste detta uppdateras.)

    <activity android:name="com.microsoft.identity.client.BrowserTabActivity">
             <intent-filter>
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.BROWSABLE" />
                 <data
                     android:host="com.azure.samples.communication.calling"
                     android:path="/Signature hash" <!-- do not remove /. The current hash in AndroidManifest.xml is for debug.keystore. -->
                     android:scheme="msauth" />
             </intent-filter>
         </activity>
    
  3. Kopiera MSAL Android-konfiguration från Azure-portalen och klistra in på AzureCalling/app/src/main/res/raw/auth_config_single_account.json. Inkludera "account_mode": "SINGLE"

       {
          "client_id": "",
          "authorization_user_agent": "DEFAULT",
          "redirect_uri": "",
          "account_mode" : "SINGLE",
          "authorities": [
             {
                "type": "AAD",
                "audience": {
                "type": "AzureADMyOrg",
                "tenant_id": ""
                }
             }
          ]
       }
    
  4. Redigera AzureCalling/app/src/main/res/raw/auth_config_single_account.json och ange värdet för nyckeln communicationTokenFetchUrl som URL för din säkra autentiseringsslutpunkt.

  5. Redigera AzureCalling/app/src/main/res/raw/auth_config_single_account.json och ange värdet för nyckeln aadScopes från Azure Active DirectoryExpose an API omfång

  6. Ange värdet för graphURL i AzureCalling/app/assets/appSettings.properties som Graph API-slutpunkt för att hämta användarinformation.

  7. Redigera AzureCalling/app/src/main/assets/appSettings.properties och ange värdet för nyckeln tenant för att aktivera tyst inloggning så att användaren inte behöver autentiseras om och om igen när programmet startas om.

Rensa resurser

Om du vill rensa och ta bort en Communication Services-prenumeration kan du ta bort resursen eller resursgruppen. Om du tar bort resursgruppen tas även alla andra resurser som är associerade med den bort. Läs mer om att rensa resurser.

Nästa steg

Mer information finns i följande artiklar:

Mer att läsa

Azure Communication Services Group Calling Hero Sample för Windows visar hur Communication Services Calling Windows SDK kan användas för att skapa en gruppsamtalsupplevelse som innehåller röst och video. I det här exemplet får du lära dig hur du konfigurerar och kör exemplet. En översikt över exemplet tillhandahålls för kontexten.

I den här snabbstarten får du lära dig hur du startar ett 1:1-videosamtal med hjälp av Azure Communication Services Calling SDK för Windows.

UWP-exempelkod

Förutsättningar

För att slutföra den här självstudien, finns följande förhandskrav:

Konfigurera

Skapa projektet

I Visual Studio skapar du ett nytt projekt med mallen Tom app (Universell Windows) för att konfigurera en enkelsidig Universell Windows-plattform-app (UWP).

Skärmbild som visar fönstret Nytt UWP-projekt i Visual Studio.

Installera -paketet

Högerklicka på projektet och gå till för att Manage Nuget Packages installera Azure.Communication.Calling.WindowsClient1.2.0-beta.1 eller överlägsen version. Kontrollera att Inkludera förhyrd är markerat.

Begär åtkomst

Gå till Package.appxmanifest och klicka på Capabilities. Kontrollera Internet (Client & Server) om du vill få inkommande och utgående åtkomst till Internet. Kontrollera Microphone om du vill komma åt mikrofonens ljudflöde. Kontrollera WebCam om du vill komma åt enhetens kamera.

Lägg till följande kod i din Package.appxmanifest genom att högerklicka och välja Visa kod.

<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>

Konfigurera appramverket

Vi måste konfigurera en grundläggande layout för att koppla vår logik. För att kunna ringa ett utgående samtal behöver vi ett TextBox för att ange användar-ID:t för den anropade. Vi behöver också en Start Call knapp och en Hang Up knapp. Vi måste också förhandsgranska den lokala videon och återge fjärrvideon för den andra deltagaren. Därför behöver vi två element för att visa videoströmmarna.

MainPage.xaml Öppna projektet och ersätt innehållet med följande implementering.

<Page
    x:Class="CallingQuickstart.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CallingQuickstart"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid x:Name="MainGrid" HorizontalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="200*"/>
            <RowDefinition Height="60*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Grid Grid.Row="0" x:Name="AppTitleBar" Background="LightSeaGreen">
            <!-- Width of the padding columns is set in LayoutMetricsChanged handler. -->
            <!-- Using padding columns instead of Margin ensures that the background paints the area under the caption control buttons (for transparent buttons). -->
            <TextBlock x:Name="QuickstartTitle" Text="Calling Quickstart sample title bar" Style="{StaticResource CaptionTextBlockStyle}" Padding="4,4,0,0"/>
        </Grid>

        <TextBox Grid.Row="1" x:Name="CalleeTextBox" PlaceholderText="Who would you like to call?" TextWrapping="Wrap" VerticalAlignment="Center" />

        <Grid Grid.Row="2" Background="LightGray">
            <Grid.RowDefinitions>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <MediaPlayerElement x:Name="LocalVideo" HorizontalAlignment="Center" Stretch="UniformToFill" Grid.Column="0" VerticalAlignment="Center" AutoPlay="True" />
            <MediaPlayerElement x:Name="RemoteVideo" HorizontalAlignment="Center" Stretch="UniformToFill" Grid.Column="1" VerticalAlignment="Center" AutoPlay="True" />
        </Grid>
        <StackPanel Grid.Row="3" Orientation="Vertical" Grid.RowSpan="2">
            <StackPanel Orientation="Horizontal" Margin="10">
                <TextBlock VerticalAlignment="Center">Cameras:</TextBlock>
                <ComboBox x:Name="CameraList" HorizontalAlignment="Left" Grid.Column="0" DisplayMemberPath="Name" SelectionChanged="CameraList_SelectionChanged" Margin="10"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <Button x:Name="CallButton" Content="Start/Join call" Click="CallButton_Click" VerticalAlignment="Center" Margin="10,0,0,0" Height="40" Width="123"/>
                <Button x:Name="HangupButton" Content="Hang up" Click="HangupButton_Click" VerticalAlignment="Center" Margin="10,0,0,0" Height="40" Width="123"/>
                <CheckBox x:Name="MuteLocal" Content="Mute" Margin="10,0,0,0" Click="MuteLocal_Click" Width="74"/>
                <CheckBox x:Name="BackgroundBlur" Content="Background blur" Width="142" Margin="10,0,0,0" Click="BackgroundBlur_Click"/>
            </StackPanel>
        </StackPanel>
        <TextBox Grid.Row="4" x:Name="Stats" Text="" TextWrapping="Wrap" VerticalAlignment="Center" Height="30" Margin="0,2,0,0" BorderThickness="2" IsReadOnly="True" Foreground="LightSlateGray" />
    </Grid>
</Page>

Öppna ( App.xaml.cs högerklicka och välj Visa kod) och lägg till den här raden längst upp:

using CallingQuickstart;

MainPage.xaml.cs Öppna (högerklicka och välj Visa kod) och ersätt innehållet med följande implementering:

using Azure.Communication.Calling.WindowsClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Core;
using Windows.Media.Core;
using Windows.Networking.PushNotifications;
using Windows.UI;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace CallingQuickstart
{
    public sealed partial class MainPage : Page
    {
        private const string authToken = "<Azure Communication Services auth token>";
    
        private CallClient callClient;
        private CallTokenRefreshOptions callTokenRefreshOptions;
        private CallAgent callAgent;
        private CommunicationCall call = null;

        private LocalOutgoingAudioStream micStream;
        private LocalOutgoingVideoStream cameraStream;

        #region Page initialization
        public MainPage()
        {
            this.InitializeComponent();
            
            // Hide default title bar.
            var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
            coreTitleBar.ExtendViewIntoTitleBar = true;

            QuickstartTitle.Text = $"{Package.Current.DisplayName} - Ready";
            Window.Current.SetTitleBar(AppTitleBar);

            CallButton.IsEnabled = true;
            HangupButton.IsEnabled = !CallButton.IsEnabled;
            MuteLocal.IsChecked = MuteLocal.IsEnabled = !CallButton.IsEnabled;

            ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(800, 600);
            ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
        }

        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            await InitCallAgentAndDeviceManagerAsync();

            base.OnNavigatedTo(e);
        }
#endregion

        private async Task InitCallAgentAndDeviceManagerAsync()
        {
            // Initialize call agent and Device Manager
        }

        private async void Agent_OnIncomingCallAsync(object sender, IncomingCall incomingCall)
        {
            // Accept an incoming call
        }

        private async void CallButton_Click(object sender, RoutedEventArgs e)
        {
            // Start a call with video
        }

        private async void HangupButton_Click(object sender, RoutedEventArgs e)
        {
            // End the current call
        }

        private async void Call_OnStateChangedAsync(object sender, PropertyChangedEventArgs args)
        {
            var call = sender as CommunicationCall;

            if (call != null)
            {
                var state = call.State;

                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                {
                    QuickstartTitle.Text = $"{Package.Current.DisplayName} - {state.ToString()}";
                    Window.Current.SetTitleBar(AppTitleBar);

                    HangupButton.IsEnabled = state == CallState.Connected || state == CallState.Ringing;
                    CallButton.IsEnabled = !HangupButton.IsEnabled;
                    MuteLocal.IsEnabled = !CallButton.IsEnabled;
                });

                switch (state)
                {
                    case CallState.Connected:
                        {
                            break;
                        }
                    case CallState.Disconnected:
                        {
                            break;
                        }
                    default: break;
                }
            }
        }
        
        private async void CameraList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // Handle camera selection
        }
    }
}

Objektmodell

Följande klasser och gränssnitt hanterar några av de viktigaste funktionerna i Azure Communication Services Calling SDK:

Name beskrivning
CallClient CallClient är huvudinmatningspunkten 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 anrop.
CallTokenCredential CallTokenCredential Används som tokenautentiseringsuppgifter för att instansiera CallAgent.
CommunicationUserIdentifier CommunicationUserIdentifier Används för att representera användarens identitet, vilket kan vara något av följande alternativ: CommunicationUserIdentifier, PhoneNumberIdentifier eller CallingApplication.

Autentisera klienten

För att initiera en CallAgentbehöver du en användaråtkomsttoken. Vanligtvis genereras denna token från en tjänst med autentisering som är specifik för programmet. Mer information om token för användaråtkomst finns i guiden Användaråtkomsttoken .

För snabbstarten ersätter du <AUTHENTICATION_TOKEN> med en användaråtkomsttoken som genererats för din Azure Communication Service-resurs.

När du har en token initierar du en CallAgent instans med den, vilket gör att vi kan ringa och ta emot samtal. För att komma åt kamerorna på enheten måste vi också få Enhetshanteraren instans.

Lägg till följande kod i InitCallAgentAndDeviceManagerAsync funktionen.

this.callClient = new CallClient(new CallClientOptions() {
    Diagnostics = new CallDiagnosticsOptions() { 
        AppName = "CallingQuickstart",
        AppVersion="1.0",
        Tags = new[] { "Calling", "ACS", "Windows" }
        }
    });

// Set up local video stream using the first camera enumerated
var deviceManager = await this.callClient.GetDeviceManagerAsync();
var camera = deviceManager?.Cameras?.FirstOrDefault();
var mic = deviceManager?.Microphones?.FirstOrDefault();
micStream = new LocalOutgoingAudioStream();

CameraList.ItemsSource = deviceManager.Cameras.ToList();

if (camera != null)
{
    CameraList.SelectedIndex = 0;
}

callTokenRefreshOptions = new CallTokenRefreshOptions(false);
callTokenRefreshOptions.TokenRefreshRequested += OnTokenRefreshRequestedAsync;

var tokenCredential = new CallTokenCredential(authToken, callTokenRefreshOptions);

var callAgentOptions = new CallAgentOptions()
{
    DisplayName = "Contoso",
    //https://github.com/lukes/ISO-3166-Countries-with-Regional-Codes/blob/master/all/all.csv
    EmergencyCallOptions = new EmergencyCallOptions() { CountryCode = "840" }
};


try
{
    this.callAgent = await this.callClient.CreateCallAgentAsync(tokenCredential, callAgentOptions);
    //await this.callAgent.RegisterForPushNotificationAsync(await this.RegisterWNS());
    this.callAgent.CallsUpdated += OnCallsUpdatedAsync;
    this.callAgent.IncomingCallReceived += OnIncomingCallAsync;

}
catch(Exception ex)
{
    if (ex.HResult == -2147024809)
    {
        // E_INVALIDARG
        // Handle possible invalid token
    }
}

Starta ett samtal med video

Lägg till implementeringen i CallButton_Click för att starta ett anrop med video. Vi måste räkna upp kamerorna med enhetshanterarens instans och skapa LocalOutgoingVideoStream. Vi måste ange VideoOptions med LocalVideoStream och skicka det med startCallOptions för att ange inledande alternativ för anropet. Genom att ansluta LocalOutgoingVideoStream till en MediaElementkan vi se förhandsversionen av den lokala videon.

var callString = CalleeTextBox.Text.Trim();

if (!string.IsNullOrEmpty(callString))
{
    if (callString.StartsWith("8:")) // 1:1 Azure Communication Services call
    {
        call = await StartAcsCallAsync(callString);
    }
    else if (callString.StartsWith("+")) // 1:1 phone call
    {
        call = await StartPhoneCallAsync(callString, "+12133947338");
    }
    else if (Guid.TryParse(callString, out Guid groupId))// Join group call by group guid
    {
        call = await JoinGroupCallByIdAsync(groupId);
    }
    else if (Uri.TryCreate(callString, UriKind.Absolute, out Uri teamsMeetinglink)) //Teams meeting link
    {
        call = await JoinTeamsMeetingByLinkAsync(teamsMeetinglink);
    }
}

if (call != null)
{
    call.RemoteParticipantsUpdated += OnRemoteParticipantsUpdatedAsync;
    call.StateChanged += OnStateChangedAsync;
}

Lägg till metoderna för att starta eller ansluta till de olika typerna av samtal (1:1 Azure Communication Services-samtal, 1:1-telefonsamtal, Gruppsamtal för Azure Communication Services, Teams-mötesanslutning osv.).

private async Task<CommunicationCall> StartAcsCallAsync(string acsCallee)
{
    var options = await GetStartCallOptionsAsynnc();
    var call = await this.callAgent.StartCallAsync( new [] { new UserCallIdentifier(acsCallee) }, options);
    return call;
}

private async Task<CommunicationCall> StartPhoneCallAsync(string acsCallee, string alternateCallerId)
{
    var options = await GetStartCallOptionsAsynnc();
    options.AlternateCallerId = new PhoneNumberCallIdentifier(alternateCallerId);

    var call = await this.callAgent.StartCallAsync( new [] { new PhoneNumberCallIdentifier(acsCallee) }, options);
    return call;
}

private async Task<CommunicationCall> JoinGroupCallByIdAsync(Guid groupId)
{
    var joinCallOptions = await GetJoinCallOptionsAsync();

    var groupCallLocator = new GroupCallLocator(groupId);
    var call = await this.callAgent.JoinAsync(groupCallLocator, joinCallOptions);
    return call;
}

private async Task<CommunicationCall> JoinTeamsMeetingByLinkAsync(Uri teamsCallLink)
{
    var joinCallOptions = await GetJoinCallOptionsAsync();

    var teamsMeetingLinkLocator = new TeamsMeetingLinkLocator(teamsCallLink.AbsoluteUri);
    var call = await callAgent.JoinAsync(teamsMeetingLinkLocator, joinCallOptions);
    return call;
}

private async Task<StartCallOptions> GetStartCallOptionsAsynnc()
{
    return new StartCallOptions() {
        OutgoingAudioOptions = new OutgoingAudioOptions() { IsOutgoingAudioMuted = true, OutgoingAudioStream = micStream  },
        OutgoingVideoOptions = new OutgoingVideoOptions() { OutgoingVideoStreams = new OutgoingVideoStream[] { cameraStream } }
    };
}

private async Task<JoinCallOptions> GetJoinCallOptionsAsync()
{
    return new JoinCallOptions() {
        OutgoingAudioOptions = new OutgoingAudioOptions() { IsOutgoingAudioMuted = true },
        OutgoingVideoOptions = new OutgoingVideoOptions() { OutgoingVideoStreams = new OutgoingVideoStream[] { cameraStream } }
    };
}

Lägg till koden för att skapa LocalVideoStream beroende på den valda kameran på CameraList_SelectionChanged metoden.

var selectedCamerea = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamerea);

 var localUri = await cameraStream.StartPreviewAsync();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
    LocalVideo.Source = MediaSource.CreateFromUri(localUri);
});

if (call != null)
{
    await call?.StartVideoAsync(cameraStream);
}

Acceptera ett inkommande samtal

Lägg till implementeringen i OnIncomingCallAsync för att besvara ett inkommande samtal med video, skicka LocalVideoStream till acceptCallOptions.

var incomingCall = args.IncomingCall;

var acceptCallOptions = new AcceptCallOptions() { 
    IncomingVideoOptions = new IncomingVideoOptions()
    {
        IncomingVideoStreamKind = VideoStreamKind.RemoteIncoming
    } 
};

_ = await incomingCall.AcceptAsync(acceptCallOptions);

Fjärrdeltagare och fjärrvideoströmmar

Alla fjärrdeltagare är tillgängliga via RemoteParticipants samlingen på en samtalsinstans. När samtalet är anslutet kan vi komma åt fjärrdeltagarna i samtalet och hantera fjärrvideoströmmarna.


private async void Call_OnVideoStreamsUpdatedAsync(object sender, RemoteVideoStreamsEventArgs args)
{
    foreach (var remoteVideoStream in args.AddedRemoteVideoStreams)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
        {
            RemoteVideo.Source = await remoteVideoStream.Start();
        });
    }

    foreach (var remoteVideoStream in args.RemovedRemoteVideoStreams)
    {
        remoteVideoStream.Stop();
    }
}

private async void Agent_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 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;
    }
}

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);
                    });
                    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;
    }

}

Rendera fjärrvideor

För varje fjärrvideoström kopplar du den till MediaElement.

private async Task AddVideoStreamsAsync(IReadOnlyList<RemoteVideoStream> remoteVideoStreams)
{
    foreach (var remoteVideoStream in remoteVideoStreams)
    {
        var remoteUri = await remoteVideoStream.Start();

        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            RemoteVideo.Source = remoteUri;
            RemoteVideo.Play();
        });
    }
}

Uppdatering av samtalstillstånd

Vi måste rensa videoåtergivningarna när anropet är frånkopplat och hantera ärendet när fjärrdeltagarna först ansluter samtalet.

private async void Call_OnStateChanged(object sender, PropertyChangedEventArgs args)
{
    switch (((Call)sender).State)
    {
        case CallState.Disconnected:
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                LocalVideo.Source = null;
                RemoteVideo.Source = null;
            });
            break;

        case CallState.Connected:
            foreach (var remoteParticipant in call.RemoteParticipants)
            {
                String remoteParticipantMRI = remoteParticipant.Identifier.ToString();
                remoteParticipantDictionary.TryAdd(remoteParticipantMRI, remoteParticipant);
                await AddVideoStreams(remoteParticipant.VideoStreams);
                remoteParticipant.OnVideoStreamsUpdated += Call_OnVideoStreamsUpdated;
            }
            break;

        default:
            break;
    }
}

Avsluta samtal

Avsluta det aktuella samtalet när Hang Up knappen klickas. Lägg till implementeringen i HangupButton_Click för att avsluta ett anrop med den callAgent som vi skapade och ta ned händelsehanterare för deltagaruppdatering och samtalstillstånd.

var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
    try
    {
        await call.HangUpAsync(new HangUpOptions() { ForEveryone = true });
    }
    catch(Exception ex) 
    {
    }
}

Kör koden

Du kan skapa och köra koden i Visual Studio. För lösningsplattformar stöder ARM64vi , x64 och x86.

Du kan göra ett utgående videosamtal genom att ange ett användar-ID i textfältet och klicka på Start Call knappen.

Obs! Samtal 8:echo123 stoppar videoströmmen eftersom ekoroboten inte stöder videoströmning.

Mer information om användar-ID:t (identitet) finns i guiden Användaråtkomsttoken .

WinUI 3-exempelkod

Förutsättningar

För att slutföra den här självstudien, finns följande förhandskrav:

Konfigurera

Skapa projektet

I Visual Studio skapar du ett nytt projekt med mallen Tom app, Paketerad (WinUI 3 i Desktop) för att konfigurera en winui 3-app med en enda sida.

Skärmbild som visar fönstret Nytt WinUI-projekt i Visual Studio.

Installera -paketet

Högerklicka på projektet och gå till för att Manage Nuget Packages installera Azure.Communication.Calling.WindowsClient1.0.0 eller överlägsen version. Kontrollera att Inkludera förhyrd är markerat.

Begär åtkomst

Skärmbild som visar begäran om åtkomst till Internet och mikrofon i Visual Studio.

Lägg till följande kod i :app.manifest

<file name="RtmMvrMf.dll">
    <activatableClass name="VideoN.VideoSchemeHandler" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>

Konfigurera appramverket

Vi måste konfigurera en grundläggande layout för att koppla vår logik. För att kunna ringa ett utgående samtal behöver vi ett TextBox för att ange användar-ID:t för den anropade. Vi behöver också en Start Call knapp och en Hang Up knapp. Vi måste också förhandsgranska den lokala videon och återge fjärrvideon för den andra deltagaren. Därför behöver vi två element för att visa videoströmmarna.

MainWindow.xaml Öppna projektet och ersätt innehållet med följande implementering.

<Page
    x:Class="CallingQuickstart.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CallingQuickstart"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid x:Name="MainGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="32"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="200*"/>
            <RowDefinition Height="60*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Grid Grid.Row="0" x:Name="AppTitleBar" Background="LightSeaGreen">
            <!-- Width of the padding columns is set in LayoutMetricsChanged handler. -->
            <!-- Using padding columns instead of Margin ensures that the background paints the area under the caption control buttons (for transparent buttons). -->
            <TextBlock x:Name="QuickstartTitle" Text="Calling Quickstart sample title bar" Style="{StaticResource CaptionTextBlockStyle}" Padding="4,4,0,0"/>
        </Grid>

        <TextBox Grid.Row="1" x:Name="CalleeTextBox" PlaceholderText="Who would you like to call?" TextWrapping="Wrap" VerticalAlignment="Center" />

        <Grid Grid.Row="2" Background="LightGray">
            <Grid.RowDefinitions>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <MediaPlayerElement x:Name="LocalVideo" HorizontalAlignment="Center" Stretch="UniformToFill" Grid.Column="0" VerticalAlignment="Center" AutoPlay="True" />
            <MediaPlayerElement x:Name="RemoteVideo" HorizontalAlignment="Center" Stretch="UniformToFill" Grid.Column="1" VerticalAlignment="Center" AutoPlay="True" />
        </Grid>
        <StackPanel Grid.Row="3" Orientation="Vertical" Grid.RowSpan="2">
            <StackPanel Orientation="Horizontal" Margin="10">
                <TextBlock VerticalAlignment="Center">Cameras:</TextBlock>
                <ComboBox x:Name="CameraList" HorizontalAlignment="Left" Grid.Column="0" DisplayMemberPath="Name" SelectionChanged="CameraList_SelectionChanged" Margin="10"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <Button x:Name="CallButton" Content="Start/Join call" Click="CallButton_Click" VerticalAlignment="Center" Margin="10,0,0,0" Height="40" Width="123"/>
                <Button x:Name="HangupButton" Content="Hang up" Click="HangupButton_Click" VerticalAlignment="Center" Margin="10,0,0,0" Height="40" Width="123"/>
                <CheckBox x:Name="MuteLocal" Content="Mute" Margin="10,0,0,0" Click="MuteLocal_Click" Width="74"/>
                <CheckBox x:Name="BackgroundBlur" Content="Background blur" Width="142" Margin="10,0,0,0" Click="BackgroundBlur_Click"/>
            </StackPanel>
        </StackPanel>
        <TextBox Grid.Row="4" x:Name="Stats" Text="" TextWrapping="Wrap" VerticalAlignment="Center" Height="30" Margin="0,2,0,0" BorderThickness="2" IsReadOnly="True" Foreground="LightSlateGray" />
    </Grid>    
</Page>

Öppna ( App.xaml.cs högerklicka och välj Visa kod) och lägg till den här raden längst upp:

using CallingQuickstart;

MainWindow.xaml.cs Öppna (högerklicka och välj Visa kod) och ersätt innehållet med följande implementering:

using Azure.Communication.Calling.WindowsClient;
using Azure.WinRT.Communication;
using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.Media.Core;

namespace CallingQuickstart
{
    public sealed partial class MainWindow : Window
    {
        CallAgent callAgent;
        Call call;
        DeviceManager deviceManager;
        Dictionary<string, RemoteParticipant> remoteParticipantDictionary = new Dictionary<string, RemoteParticipant>();

        public MainWindow()
        {
            this.InitializeComponent();
            Task.Run(() => this.InitCallAgentAndDeviceManagerAsync()).Wait();
        }

        private async Task InitCallAgentAndDeviceManagerAsync()
        {
            // Initialize call agent and Device Manager
        }

        private async void Agent_OnIncomingCallAsync(object sender, IncomingCall incomingCall)
        {
            // Accept an incoming call
        }

        private async void CallButton_Click(object sender, RoutedEventArgs e)
        {
            // Start a call with video
        }

        private async void HangupButton_Click(object sender, RoutedEventArgs e)
        {
            // End the current call
        }

        private async void Call_OnStateChangedAsync(object sender, PropertyChangedEventArgs args)
        {
            var state = (sender as Call)?.State;
            this.DispatcherQueue.TryEnqueue(() => {
                State.Text = state.ToString();
            });
        }
    }
}

Objektmodell

Följande klasser och gränssnitt hanterar några av de viktigaste funktionerna i Azure Communication Services Calling SDK:

Name beskrivning
CallClient CallClient är huvudinmatningspunkten 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 anrop.
CallTokenCredential CallTokenCredential Används som tokenautentiseringsuppgifter för att instansiera CallAgent.
CommunicationUserIdentifier CommunicationUserIdentifier Används för att representera användarens identitet, vilket kan vara något av följande alternativ: CommunicationUserIdentifier, PhoneNumberIdentifier eller CallingApplication.

Autentisera klienten

För att initiera en CallAgentbehöver du en användaråtkomsttoken. Vanligtvis genereras denna token från en tjänst med autentisering som är specifik för programmet. Mer information om token för användaråtkomst finns i guiden Användaråtkomsttoken .

För snabbstarten ersätter du <AUTHENTICATION_TOKEN> med en användaråtkomsttoken som genererats för din Azure Communication Service-resurs.

När du har en token initierar du en CallAgent instans med den, vilket gör att vi kan göra och ta emot anrop. För att komma åt kamerorna på enheten måste vi också få Enhetshanteraren instans.

Lägg till följande kod i InitCallAgentAndDeviceManagerAsync funktionen.

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.OnCallsUpdated += Agent_OnCallsUpdatedAsync;
this.callAgent.OnIncomingCall += Agent_OnIncomingCallAsync;

Starta ett samtal med video

Lägg till implementeringen i CallButton_Click för att starta ett anrop med video. Vi måste räkna upp kamerorna med enhetshanterarens instans och skapa LocalVideoStream. Vi måste ange VideoOptions med LocalVideoStream och skicka det med startCallOptions för att ange inledande alternativ för anropet. Genom att ansluta LocalVideoStream till en MediaPlayerElementkan vi se förhandsversionen av den lokala videon.

var startCallOptions = new StartCallOptions();

if (this.deviceManager.Cameras?.Count > 0)
{
    var videoDeviceInfo = this.deviceManager.Cameras?.FirstOrDefault();
    if (videoDeviceInfo != null)
    {
        var selectedCamerea = CameraList.SelectedItem as VideoDeviceDetails;
        cameraStream = new LocalOutgoingVideoStream(selectedCamerea);

        var localUri = await cameraStream.StartPreviewAsync();
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            LocalVideo.Source = MediaSource.CreateFromUri(localUri);
        });

        startCallOptions.VideoOptions = new OutgoingVideoOptions(new[] { cameraStream });
    }
}

var callees = new ICommunicationIdentifier[1]
{
    new CommunicationUserIdentifier(CalleeTextBox.Text.Trim())
};

this.call = await this.callAgent.StartCallAsync(callees, startCallOptions);
this.call.OnRemoteParticipantsUpdated += Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged += Call_OnStateChangedAsync;

Acceptera ett inkommande samtal

Lägg till implementeringen i Agent_OnIncomingCallAsync för att besvara ett inkommande samtal med video, skicka LocalVideoStream till acceptCallOptions.

var acceptCallOptions = new AcceptCallOptions();

if (this.deviceManager.Cameras?.Count > 0)
{
    var videoDeviceInfo = this.deviceManager.Cameras?.FirstOrDefault();
    if (videoDeviceInfo != null)
    {
        var selectedCamerea = CameraList.SelectedItem as VideoDeviceDetails;
        cameraStream = new LocalOutgoingVideoStream(selectedCamerea);

        var localUri = await cameraStream.StartPreviewAsync();
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            LocalVideo.Source = MediaSource.CreateFromUri(localUri);
        });

        acceptCallOptions.VideoOptions = new OutgoingVideoOptions(new[] { localVideoStream });
    }
}

call = await incomingCall.AcceptAsync(acceptCallOptions);

Fjärrdeltagare och fjärrvideoströmmar

Alla fjärrdeltagare är tillgängliga via RemoteParticipants samlingen på en samtalsinstans. När samtalet är anslutet kan vi komma åt fjärrdeltagarna i samtalet och hantera fjärrvideoströmmarna.

private async void Call_OnVideoStreamsUpdatedAsync(object sender, RemoteVideoStreamsEventArgs args)
{
    foreach (var remoteVideoStream in args.AddedRemoteVideoStreams)
    {
        this.DispatcherQueue.TryEnqueue(async () => {
            RemoteVideo.Source = MediaSource.CreateFromUri(await remoteVideoStream.Start());
            RemoteVideo.MediaPlayer.Play();
        });
    }

    foreach (var remoteVideoStream in args.RemovedRemoteVideoStreams)
    {
        remoteVideoStream.Stop();
    }
}

private async void Agent_OnCallsUpdatedAsync(object sender, CallsUpdatedEventArgs args)
{
    foreach (var call in args.AddedCalls)
    {
        foreach (var remoteParticipant in call.RemoteParticipants)
        {
            var remoteParticipantMRI = remoteParticipant.Identifier.ToString();
            this.remoteParticipantDictionary.TryAdd(remoteParticipantMRI, remoteParticipant);
            await AddVideoStreamsAsync(remoteParticipant.VideoStreams);
            remoteParticipant.OnVideoStreamsUpdated += Call_OnVideoStreamsUpdatedAsync;
        }
    }
}

private async void Call_OnRemoteParticipantsUpdatedAsync(object sender, ParticipantsUpdatedEventArgs args)
{
    foreach (var remoteParticipant in args.AddedParticipants)
    {
        String remoteParticipantMRI = remoteParticipant.Identifier.ToString();
        this.remoteParticipantDictionary.TryAdd(remoteParticipantMRI, remoteParticipant);
        await AddVideoStreamsAsync(remoteParticipant.VideoStreams);
        remoteParticipant.OnVideoStreamsUpdated += Call_OnVideoStreamsUpdatedAsync;
    }

    foreach (var remoteParticipant in args.RemovedParticipants)
    {
        String remoteParticipantMRI = remoteParticipant.Identifier.ToString();
        this.remoteParticipantDictionary.Remove(remoteParticipantMRI);
    }
}

Rendera fjärrvideor

För varje fjärrvideoström kopplar du den till MediaPlayerElement.

private async Task AddVideoStreamsAsync(IReadOnlyList<RemoteVideoStream> remoteVideoStreams)
{
    foreach (var remoteVideoStream in remoteVideoStreams)
    {
        var remoteUri = await remoteVideoStream.Start();

        this.DispatcherQueue.TryEnqueue(() => {
            RemoteVideo.Source = MediaSource.CreateFromUri(remoteUri);
            RemoteVideo.MediaPlayer.Play();
        });
    }
}

Uppdatering av samtalstillstånd

Vi måste rensa videoåtergivningarna när anropet är frånkopplat och hantera ärendet när fjärrdeltagarna först ansluter samtalet.

private async void Call_OnStateChanged(object sender, PropertyChangedEventArgs args)
{
    switch (((Call)sender).State)
    {
        case CallState.Disconnected:
            this.DispatcherQueue.TryEnqueue(() => { =>
            {
                LocalVideo.Source = null;
                RemoteVideo.Source = null;
            });
            break;

        case CallState.Connected:
            foreach (var remoteParticipant in call.RemoteParticipants)
            {
                String remoteParticipantMRI = remoteParticipant.Identifier.ToString();
                remoteParticipantDictionary.TryAdd(remoteParticipantMRI, remoteParticipant);
                await AddVideoStreams(remoteParticipant.VideoStreams);
                remoteParticipant.OnVideoStreamsUpdated += Call_OnVideoStreamsUpdated;
            }
            break;

        default:
            break;
    }
}

Avsluta samtal

Avsluta det aktuella samtalet när Hang Up knappen klickas. Lägg till implementeringen i HangupButton_Click för att avsluta ett anrop med den callAgent som vi skapade och ta ned händelsehanterare för deltagaruppdatering och samtalstillstånd.

this.call.OnRemoteParticipantsUpdated -= Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged -= Call_OnStateChangedAsync;
await this.call.HangUpAsync(new HangUpOptions());

Kör koden

Du kan skapa och köra koden i Visual Studio. För lösningsplattformar stöder ARM64vi , x64 och x86.

Du kan göra ett utgående videosamtal genom att ange ett användar-ID i textfältet och klicka på Start Call knappen.

Obs! Samtal 8:echo123 stoppar videoströmmen eftersom ekoroboten inte stöder videoströmning.

Mer information om användar-ID:t (identitet) finns i guiden Användaråtkomsttoken .