Aan de slag met het voorbeeld van de aanroepende hero

In het Hero-voorbeeld van de Azure Communication Services-groep aanroepen wordt gedemonstreert hoe de Web-SDK voor het aanroepen van communicatieservices kan worden gebruikt om een groepsgesprekservaring te bouwen.

In deze quickstart leert u hoe het voorbeeld werkt voordat u het voorbeeld uitvoert op uw lokale computer en vervolgens het voorbeeld implementeert in Azure met behulp van uw eigen Azure Communication Services-resources.

Code downloaden

Zoek het project voor dit voorbeeld op GitHub. Een versie van het voorbeeld met functies die momenteel beschikbaar zijn als openbare preview, zoals Teams Interop en Gespreksopname , vindt u in een afzonderlijke vertakking.

Implementeren op Azure

Overzicht

Het voorbeeld heeft zowel een toepassing aan de clientzijde als een toepassing aan de serverzijde. De toepassing aan de clientzijde is een React/Redux-webtoepassing die gebruikmaakt van het Fluent UI-framework van Microsoft. Met deze toepassing worden aanvragen verzonden naar een ASP.NET Core-toepassing aan de serverzijde zodat de toepassing aan de clientzijde kan worden verbonden met Azure.

Het voorbeeld ziet er als volgt uit:

Schermopname van de landingspagina van de voorbeeldtoepassing.

Wanneer de knop Een gesprek starten kiest, wordt door de webtoepassing een toegangstoken voor gebruikers opgehaald bij de toepassing op de server. Vervolgens wordt dit token gebruikt om de client-app met Azure Communication Services te verbinden. Zodra het token is opgehaald, wordt u gevraagd de camera en microfoon op te geven die u wilt gebruiken. U kunt uw apparaten uitschakelen/inschakelen met wisselknoppen:

Schermopname van het scherm voorafgaand aan het gesprek van de voorbeeldtoepassing.

Zodra u uw weergavenaam en apparaten hebt geconfigureerd, kunt u deelnemen aan de gesprekssessie. U ziet het hoofdgesprekscanvas waarin de belangrijkste oproepervaring zich bevindt.

Schermopname van het hoofdscherm van de voorbeeldtoepassing.

Onderdelen van het hoofdgespreksscherm:

  • Mediagalerie: het hoofdpodium waar deelnemers worden weergegeven. Als deelnemers hun camera hebben ingeschakeld, wordt hier hun videofeed weergegeven. Elke deelnemer beschikt over een afzonderlijke tegel waarop hun weergavenaam en videostream (indien beschikbaar) worden weergegeven
  • Koptekst: Hier bevinden de primaire oproepbesturingselementen zich om instellingen en zijbalk van deelnemers in of uit te schakelen, video in of uit te schakelen, scherm te delen en het gesprek te verlaten.
  • Zijbalk: hier worden informatie over deelnemers en instellingen weergegeven wanneer u de besturingselementen in de koptekst gebruikt. U kunt het onderdeel verwijderen door op X te klikken in de rechterbovenhoek. De zijbalk van deelnemers bevat een lijst met deelnemers en een koppeling om meer gebruikers uit te nodigen om te chatten. In de zijbalk met instellingen kunt u de microfoon- en camera-instellingen configureren.

Hieronder vindt u meer informatie over vereisten en stappen voor het instellen van het voorbeeld.

Vereisten

Voordat u het voorbeeld voor de eerste keer uitvoert

  1. Open een instantie van PowerShell, Windows Terminal, de opdrachtprompt of een vergelijkbare service en ga naar de map waarnaar u het voorbeeld wilt klonen.

    git clone https://github.com/Azure-Samples/communication-services-web-calling-hero.git
    
  2. Haal de Connection String azure-portal op of gebruik de Azure CLI.

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

    Zie Een Azure Communications-resource maken voor meer informatie over verbindingsreeksen

  3. Zodra u het Connection Stringbestand hebt, voegt u de verbindingsreeks toe aan het bestand samples/Server/appsetting.json. Voer in de variabele uw verbindingsreeks in: ResourceConnectionString.

  4. Haal de Endpoint string azure-portal op of gebruik de Azure CLI.

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

    Zie Een Azure Communication Resources maken voor meer informatie over eindpunttekenreeksen

  5. Wanneer u de tekenreeks voor het Endpoint Stringeindpunt hebt weergegeven, voegt u de eindpunttekenreeks toe aan het bestand samples/Server/appsetting.json . Voer uw eindpunttekenreeks in de variabele in EndpointUrl

Lokaal uitvoeren

  1. Afhankelijkheden installeren

    npm run setup
    
  2. De aanroepende app starten

    npm run start
    

    Hiermee opent u een clientserver op poort 3000 die de websitebestanden dient en een API-server op poort 8080 die functionaliteit uitvoert, zoals munttokens voor oproepdeelnemers.

Probleemoplossing

  • In de app wordt een scherm 'Niet-ondersteunde browser' weergegeven, maar ik gebruik een ondersteunde browser.

    Als uw app wordt geleverd via een andere hostnaam dan localhost, moet u verkeer via https en niet http leveren.

Publiceren naar Azure

  1. npm run setup
  2. npm run build
  3. npm run package
  4. De Azure-extensie gebruiken en de map Aanroepen/verwijderen implementeren in uw app-service

Resources opschonen

Als u een Communication Services-abonnement wilt opschonen en verwijderen, kunt u de resource of resourcegroep verwijderen. Als u de resourcegroep verwijdert, worden ook alle bijbehorende resources verwijderd. Meer informatie over het opschonen van resources.

Volgende stappen

Raadpleeg voor meer informatie de volgende artikelen:

Meer artikelen

  • Voorbeelden - Vind meer voorbeelden en voorbeelden op onze overzichtspagina met voorbeelden.
  • Redux: statusbeheer op de client
  • FluentUI: door Microsoft ondersteunde bibliotheek voor de gebruikersinterface
  • React: bibliotheek voor het ontwikkelen van gebruikersinterfaces
  • ASP.NET Core: een framework voor het bouwen van webtoepassingen

In het Hero-voorbeeld van de Azure Communication Services-groep bellen voor iOS ziet u hoe de Communication Services Calling iOS SDK kan worden gebruikt om een groepsgesprekservaring te bouwen die spraak en video bevat. In deze quickstart leert u hoe u het voorbeeld instelt en uitvoert. Er wordt een overzicht gegeven van het voorbeeld voor context.

Code downloaden

Zoek het project voor dit voorbeeld op GitHub.

Overzicht

Het voorbeeld is een systeemeigen iOS-toepassing die gebruikmaakt van de Azure Communication Services iOS SDK's om een belervaring te bouwen die zowel spraak- als videogesprekken bevat. De toepassing maakt gebruik van een onderdeel aan de serverzijde om toegangstokens in te richten die vervolgens worden gebruikt om de Azure Communication Services SDK te initialiseren. Als u dit onderdeel aan de serverzijde wilt configureren, kunt u de vertrouwde service volgen met Azure Functions .

Het voorbeeld ziet er als volgt uit:

Schermopname van de landingspagina van de voorbeeldtoepassing.

Wanneer u op de knop Nieuwe oproep starten drukt, wordt u door de iOS-toepassing gevraagd uw weergavenaam in te voeren die u voor het gesprek wilt gebruiken.

Schermopname van het scherm voorafgaand aan het gesprek van de voorbeeldtoepassing.

Nadat u op Volgende hebt getikt op het scherm Gesprek starten, hebt u de mogelijkheid om de groeps-id van de oproep te delen via het iOS-shareblad.

Schermopname van het scherm groeps-id delen van de voorbeeldtoepassing.

Met de toepassing kunt u ook deelnemen aan een bestaande Azure Communication Services-aanroep door de koppeling naar de id of de teams-id van de bestaande aanroep op te geven.

Schermopname van het scherm join-oproep van de voorbeeldtoepassing.

Nadat u deelneemt aan een gesprek, wordt u gevraagd om de toepassing toestemming te geven om toegang te krijgen tot uw camera en microfoon, als deze nog niet is geautoriseerd. Houd er rekening mee dat, net als alle AVFoundation-apps, echte audio- en videofunctionaliteit alleen beschikbaar is op echte hardware.

Zodra u uw weergavenaam hebt geconfigureerd en deelneemt aan het gesprek, ziet u het hoofdgesprekcanvas waarin de belangrijkste oproepervaring zich bevindt.

Schermopname van het hoofdscherm van de voorbeeldtoepassing.

Onderdelen van het hoofdgespreksscherm:

  • Mediagalerie: het hoofdpodium waar deelnemers worden weergegeven. Als deelnemers hun camera hebben ingeschakeld, wordt hier hun videofeed weergegeven. Elke deelnemer heeft een afzonderlijke tegel die de weergavenaam en videostream weergeeft (wanneer er een is). De galerie ondersteunt meerdere deelnemers en wordt bijgewerkt wanneer deelnemers aan het gesprek worden toegevoegd of verwijderd.
  • Actiebalk: hier bevinden zich de primaire oproepbesturingselementen. Met deze besturingselementen kunt u uw video en microfoon in-/uitschakelen, uw scherm delen en het gesprek verlaten.

Hieronder vindt u meer informatie over de vereisten en stappen voor het instellen van het voorbeeld.

Vereisten

Lokaal voorbeeld uitvoeren

Het voorbeeld van groepsgesprekken kan lokaal worden uitgevoerd met behulp van XCode. Ontwikkelaars kunnen hun fysieke apparaat of een emulator gebruiken om de toepassing te testen.

Voordat u het voorbeeld voor de eerste keer uitvoert

  1. Installeer afhankelijkheden door uit te voeren pod install.
  2. Open AzureCalling.xcworkspace in XCode.
  3. Maak een tekstbestand in de hoofdmap en AppSettings.xcconfig stel de waarde in:
    communicationTokenFetchUrl = <your authentication endpoint, without the https:// component>
    

Voorbeeld uitvoeren

Bouw en voer het voorbeeld uit in XCode met behulp van het AzureCalling-doel op de simulator of het apparaat van uw keuze.

(Optioneel) Een verificatie-eindpunt beveiligen

Voor demonstratiedoeleinden gebruikt dit voorbeeld standaard een openbaar toegankelijk eindpunt om een Azure Communication Services-toegangstoken op te halen. Voor productiescenario's raden we u aan uw eigen beveiligde eindpunt te gebruiken om uw eigen tokens in te richten.

Met aanvullende configuratie biedt dit voorbeeld ondersteuning voor het maken van verbinding met een met Microsoft Entra ID beveiligd eindpunt (Microsoft Entra ID), zodat gebruikersaanmelding is vereist voor de app om een Azure Communication Services-toegangstoken op te halen. Zie de onderstaande stappen:

  1. Schakel Microsoft Entra-verificatie in uw app in.
  2. Ga naar de overzichtspagina van uw geregistreerde app onder Microsoft Entra App Registrations. Noteer de Application (client) ID, , Directory (tenant) IDApplication ID URI

Microsoft Entra-configuratie in Azure Portal.

  1. Maak een AppSettings.xcconfig bestand in de hoofdmap als dit nog niet aanwezig is en voeg de waarden toe:
    communicationTokenFetchUrl = <Application ID URI, without the https:// component>
    aadClientId = <Application (client) ID>
    aadTenantId = <Directory (tenant) ID>
    

Resources opschonen

Als u een Communication Services-abonnement wilt opschonen en verwijderen, kunt u de resource of resourcegroep verwijderen. Als u de resourcegroep verwijdert, worden ook alle bijbehorende resources verwijderd. Meer informatie over het opschonen van resources.

Volgende stappen

Raadpleeg voor meer informatie de volgende artikelen:

Meer artikelen

Het Hero-voorbeeld van de Azure Communication Services-groep bellen voor Android laat zien hoe de Communication Services Calling Android SDK kan worden gebruikt voor het bouwen van een groepsgesprekken met spraak en video. In deze quickstart leert u hoe u het voorbeeld instelt en uitvoert. Er wordt een overzicht gegeven van het voorbeeld voor context.

Code downloaden

Zoek het project voor dit voorbeeld op GitHub.

Overzicht

Het voorbeeld is een systeemeigen Android-toepassing die gebruikmaakt van de Azure Communication Services Android UI-clientbibliotheek om een belervaring te bouwen die zowel spraak- als videogesprekken bevat. De toepassing maakt gebruik van een onderdeel aan de serverzijde om toegangstokens in te richten die vervolgens worden gebruikt om de Azure Communication Services SDK te initialiseren. Als u dit onderdeel aan de serverzijde wilt configureren, kunt u de vertrouwde service volgen met Azure Functions .

Het voorbeeld ziet er als volgt uit:

Schermopname van de landingspagina van de voorbeeldtoepassing.

Wanneer u op de knop Nieuwe oproep starten drukt, wordt u in de Android-toepassing gevraagd uw weergavenaam in te voeren die u voor het gesprek wilt gebruiken.

Schermopname van het scherm voorafgaand aan het gesprek van de voorbeeldtoepassing.

Nadat u op 'Volgende' op de pagina 'Een gesprek starten' hebt getikt, hebt u de mogelijkheid om de 'Groepsoproep-id' te delen.

Schermopname van het scherm Groepsoproep-id delen van de voorbeeldtoepassing.

Met de toepassing kunt u deelnemen aan een bestaande Azure Communication Services-aanroep door de koppeling naar de id van de bestaande oproep of de vergaderings-id van teams en de weergavenaam op te geven.

Schermopname van het scherm join-oproep van de voorbeeldtoepassing.

Nadat u deelneemt aan een gesprek, wordt u gevraagd om de toepassing toestemming te geven om toegang te krijgen tot uw camera en microfoon, als deze nog niet is geautoriseerd. U ziet het hoofdgesprekscanvas waarin de belangrijkste gesprekservaring zich bevindt.

Schermopname van het hoofdscherm van de voorbeeldtoepassing.

Onderdelen van het hoofdgespreksscherm:

  • Mediagalerie: het hoofdpodium waar deelnemers worden weergegeven. Als deelnemers hun camera hebben ingeschakeld, wordt hier hun videofeed weergegeven. Elke deelnemer heeft een afzonderlijke tegel die de weergavenaam en videostream weergeeft (wanneer er een is). De galerie ondersteunt meerdere deelnemers en wordt bijgewerkt wanneer deelnemers aan het gesprek worden toegevoegd of verwijderd.
  • Actiebalk: hier bevinden zich de primaire oproepbesturingselementen. Met deze besturingselementen kunt u uw video en microfoon in-/uitschakelen, uw scherm delen en het gesprek verlaten.

Hieronder vindt u meer informatie over de vereisten en stappen voor het instellen van het voorbeeld.

Vereisten

Lokaal voorbeeld uitvoeren

Het voorbeeld van groepsgesprekken kan lokaal worden uitgevoerd met Behulp van Android Studio. Ontwikkelaars kunnen hun fysieke apparaat of een emulator gebruiken om de toepassing te testen.

Voordat u het voorbeeld voor de eerste keer uitvoert

  1. Open Android Studio en selecteer Open an Existing Project
  2. Open de map in de AzureCalling gedownloade versie voor het voorbeeld.
  3. Vouw app/assets uit om bij te werken appSettings.properties. Stel de waarde in voor de sleutel communicationTokenFetchUrl als de URL voor het verificatie-eindpunt dat is ingesteld als een vereiste.

Voorbeeld uitvoeren

Bouw en voer het voorbeeld uit in Android Studio.

(Optioneel) Een verificatie-eindpunt beveiligen

Voor demonstratiedoeleinden gebruikt dit voorbeeld standaard een openbaar toegankelijk eindpunt om een Azure Communication Services-token op te halen. Voor productiescenario's raden we u aan uw eigen beveiligde eindpunt te gebruiken om uw eigen tokens in te richten.

Met extra configuratie ondersteunt dit voorbeeld het maken van verbinding met een met Microsoft Entra ID beveiligd eindpunt (Microsoft Entra ID), zodat gebruikersaanmelding is vereist voor de app om een Azure Communication Services-token op te halen. Zie de onderstaande stappen:

  1. Schakel Microsoft Entra-verificatie in uw app in.

  2. Ga naar de overzichtspagina van uw geregistreerde app onder Microsoft Entra App Registrations. Noteer de Package name, , Signature hash. MSAL Configutaion

Microsoft Entra-configuratie in Azure Portal.

  1. Bewerken AzureCalling/app/src/main/res/raw/auth_config_single_account.json en instellen isAADAuthEnabled om Microsoft Entra-id in te schakelen.

  2. Bewerk AndroidManifest.xml en stel deze in android:path op hash voor sleutelopslaghandtekening. (Optioneel. De huidige waarde maakt gebruik van hash uit gebundelde foutopsporing.keystore. Als er een ander sleutelarchief wordt gebruikt, moet dit worden bijgewerkt.)

    <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. Kopieer de MSAL Android-configuratie vanuit de Azure-portal en plak deze in AzureCalling/app/src/main/res/raw/auth_config_single_account.json. Neem 'account_mode' op: 'ENKEL'

       {
          "client_id": "",
          "authorization_user_agent": "DEFAULT",
          "redirect_uri": "",
          "account_mode" : "SINGLE",
          "authorities": [
             {
                "type": "AAD",
                "audience": {
                "type": "AzureADMyOrg",
                "tenant_id": ""
                }
             }
          ]
       }
    
  4. Bewerk AzureCalling/app/src/main/res/raw/auth_config_single_account.json en stel de waarde in voor de sleutel communicationTokenFetchUrl als de URL voor uw beveiligde verificatie-eindpunt.

  5. De AzureCalling/app/src/main/res/raw/auth_config_single_account.json waarde voor de sleutel aadScopes bewerken en instellen vanuit Azure Active DirectoryExpose an API bereiken

  6. Stel de waarde voor graphURL in AzureCalling/app/assets/appSettings.properties als het Graph API-eindpunt om gebruikersgegevens op te halen.

  7. Bewerk AzureCalling/app/src/main/assets/appSettings.properties en stel de waarde voor de sleutel tenant in om stille aanmelding in te schakelen, zodat de gebruiker niet opnieuw en opnieuw hoeft te worden geverifieerd tijdens het opnieuw opstarten van de toepassing.

Resources opschonen

Als u een Communication Services-abonnement wilt opschonen en verwijderen, kunt u de resource of resourcegroep verwijderen. Als u de resourcegroep verwijdert, worden ook alle bijbehorende resources verwijderd. Meer informatie over het opschonen van resources.

Volgende stappen

Raadpleeg voor meer informatie de volgende artikelen:

Meer artikelen

In het Hero-voorbeeld van de Azure Communication Services-groep bellen voor Windows ziet u hoe de Communication Services Calling Windows SDK kan worden gebruikt om een groepsgesprekken te bouwen die spraak en video bevat. In dit voorbeeld leert u hoe u het voorbeeld instelt en uitvoert. Er wordt een overzicht gegeven van het voorbeeld voor context.

In deze quickstart leert u hoe u een 1:1-videogesprek start met behulp van de Azure Communication Services Calling SDK voor Windows.

UWP-voorbeeldcode

Vereisten

Voor het voltooien van deze zelfstudie moet aan de volgende vereisten worden voldaan:

Instellen

Het project maken

Maak in Visual Studio een nieuw project met de sjabloon Blank App (Universal Windows) om een UWP-app (single page Universeel Windows-platform) in te stellen.

Schermopname van het venster Nieuw UWP-project in Visual Studio.

Het pakket installeren

Klik met de rechtermuisknop op uw project en ga naar Manage Nuget Packages 1.2.0-beta.1 of superieure versie te installerenAzure.Communication.Calling.WindowsClient. Zorg ervoor dat Preleased opnemen is ingeschakeld.

Toegang aanvragen

Ga naar Package.appxmanifest en klik op Capabilities. Controleer Internet (Client & Server) of u binnenkomende en uitgaande toegang tot internet krijgt. Controleer Microphone of u toegang wilt krijgen tot de audiofeed van de microfoon. Controleer WebCam of u toegang hebt tot de camera van het apparaat.

Voeg de volgende code toe aan uw Package.appxmanifest door met de rechtermuisknop te klikken en Code weergeven te kiezen.

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

Stel het app-framework in

We moeten een eenvoudige indeling configureren om onze logica te koppelen. Om een uitgaande oproep te kunnen plaatsen, moeten TextBox we de gebruikers-id van de aanroepende gebruiker opgeven. We hebben ook een Start Call knop en een Hang Up knop nodig. We moeten ook een voorbeeld van de lokale video bekijken en de externe video van de andere deelnemer weergeven. We hebben dus twee elementen nodig om de videostreams weer te geven.

Open het MainPage.xaml project en vervang de inhoud door de volgende implementatie.

<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>

Open (klik met App.xaml.cs de rechtermuisknop en kies Code weergeven) en voeg deze regel toe aan de bovenkant:

using CallingQuickstart;

Open de (klik met de MainPage.xaml.cs rechtermuisknop en kies Code weergeven) en vervang de inhoud door de volgende implementatie:

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

Objectmodel

De volgende klassen en interfaces verwerken enkele van de belangrijkste functies van de Azure Communication Services Calling SDK:

Name Beschrijving
CallClient Het CallClient is het belangrijkste toegangspunt voor de clientbibliotheek voor aanroepen.
CallAgent Het CallAgent wordt gebruikt om oproepen te starten en eraan deel te nemen.
CommunicationCall Het CommunicationCall wordt gebruikt voor het beheren van geplaatste of gekoppelde oproepen.
CallTokenCredential De CallTokenCredential wordt gebruikt als de tokenreferentie om de CallAgent.
CommunicationUserIdentifier Het CommunicationUserIdentifier wordt gebruikt om de identiteit van de gebruiker weer te geven. Dit kan een van de volgende opties zijn: CommunicationUserIdentifier, PhoneNumberIdentifier of CallingApplication.

De client verifiëren

Als u een CallAgentinitialisatie wilt uitvoeren, hebt u een token voor gebruikerstoegang nodig. Over het algemeen wordt dit token gegenereerd op basis van een service met verificatie die specifiek is voor de toepassing. Raadpleeg de handleiding gebruikerstoegangstokens voor meer informatie over tokens voor gebruikerstoegang.

Voor de quickstart vervangt u <AUTHENTICATION_TOKEN> door een gebruikerstoegangstoken dat voor uw Azure Communication Service-resource is gegenereerd.

Zodra u een token hebt, initialiseert u er een CallAgent exemplaar mee, zodat we oproepen kunnen plaatsen en ontvangen. Om toegang te krijgen tot de camera's op het apparaat, moeten we ook Apparaatbeheer exemplaar ophalen.

Voeg de volgende code toe aan de InitCallAgentAndDeviceManagerAsync functie.

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

Een gesprek starten met video

Voeg de implementatie toe aan de CallButton_Click implementatie om een gesprek te starten met video. We moeten de camera's inventariseren met apparaatbeheerexemplaren en constructie LocalOutgoingVideoStream. We moeten het VideoOptions instellen met LocalVideoStream en doorgeven om startCallOptions de eerste opties voor het gesprek in te stellen. Door een bijlage toe LocalOutgoingVideoStream te MediaElementvoegen, kunnen we het voorbeeld van de lokale video bekijken.

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

Voeg de methoden toe om de verschillende typen oproepen te starten of eraan deel te nemen (1:1 Azure Communication Services-oproep, 1:1 telefoongesprek, Azure Communication Services-groepsgesprek, deelnemen aan Teams-vergadering, enzovoort).

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

Voeg de code toe om de LocalVideoStream te maken, afhankelijk van de geselecteerde camera op de CameraList_SelectionChanged methode.

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

Een inkomende oproep accepteren

Voeg de implementatie toe aan de OnIncomingCallAsync implementatie om een inkomende oproep met video te beantwoorden, door te geven LocalVideoStream aan acceptCallOptions.

var incomingCall = args.IncomingCall;

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

_ = await incomingCall.AcceptAsync(acceptCallOptions);

Externe deelnemer en externe videostreams

Alle externe deelnemers zijn beschikbaar via de RemoteParticipants verzameling op een oproepexemplaren. Zodra de oproep is verbonden, hebben we toegang tot de externe deelnemers aan het gesprek en verwerken we de externe videostreams.


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

}

Externe video's weergeven

Voor elke externe videostream voegt u deze toe aan de 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();
        });
    }
}

Update van oproepstatus

We moeten de video-renderers opschonen zodra de oproep is verbroken en de case afhandelen wanneer de externe deelnemers in eerste instantie deelnemen aan het gesprek.

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

Een gesprek beëindigen

Beëindig het huidige gesprek wanneer op de Hang Up knop wordt geklikt. Voeg de implementatie toe aan de HangupButton_Click om een oproep te beëindigen met de callAgent die we hebben gemaakt en de gebeurtenis-handlers van de deelnemer bijwerken en aanroepen.

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

De code uitvoeren

U kunt de code bouwen en uitvoeren in Visual Studio. Voor oplossingsplatformen ondersteunen ARM64we , x64 en x86.

U kunt een uitgaande videogesprek voeren door een gebruikers-id op te geven in het tekstveld en op de Start Call knop te klikken.

Opmerking: bellen 8:echo123 stopt de videostream omdat echobot geen ondersteuning biedt voor videostreaming.

Raadpleeg de handleiding gebruikerstoegangstokens voor meer informatie over gebruikers-id's (identiteit).

WinUI 3-voorbeeldcode

Vereisten

Voor het voltooien van deze zelfstudie moet aan de volgende vereisten worden voldaan:

Instellen

Het project maken

Maak in Visual Studio een nieuw project met de sjabloon Blank App, Packaged (WinUI 3 in Desktop) om een WinUI 3-app met één pagina in te stellen.

Schermopname van het venster Nieuw WinUI-project in Visual Studio.

Het pakket installeren

Klik met de rechtermuisknop op uw project en ga naar Manage Nuget Packages 1.0.0 of superieure versie te installerenAzure.Communication.Calling.WindowsClient. Zorg ervoor dat Preleased opnemen is ingeschakeld.

Toegang aanvragen

Schermopname van het aanvragen van toegang tot internet en microfoon in Visual Studio.

Voeg de volgende code toe aan uw app.manifest:

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

Stel het app-framework in

We moeten een eenvoudige indeling configureren om onze logica te koppelen. Om een uitgaande oproep te kunnen plaatsen, moeten TextBox we de gebruikers-id van de aanroepende gebruiker opgeven. We hebben ook een Start Call knop en een Hang Up knop nodig. We moeten ook een voorbeeld van de lokale video bekijken en de externe video van de andere deelnemer weergeven. We hebben dus twee elementen nodig om de videostreams weer te geven.

Open het MainWindow.xaml project en vervang de inhoud door de volgende implementatie.

<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>

Open (klik met App.xaml.cs de rechtermuisknop en kies Code weergeven) en voeg deze regel toe aan de bovenkant:

using CallingQuickstart;

Open de (klik met de MainWindow.xaml.cs rechtermuisknop en kies Code weergeven) en vervang de inhoud door de volgende implementatie:

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

Objectmodel

De volgende klassen en interfaces verwerken enkele van de belangrijkste functies van de Azure Communication Services Calling SDK:

Name Beschrijving
CallClient Het CallClient is het belangrijkste toegangspunt voor de clientbibliotheek voor aanroepen.
CallAgent Het CallAgent wordt gebruikt om oproepen te starten en eraan deel te nemen.
CommunicationCall Het CommunicationCall wordt gebruikt voor het beheren van geplaatste of gekoppelde oproepen.
CallTokenCredential De CallTokenCredential wordt gebruikt als de tokenreferentie om de CallAgent.
CommunicationUserIdentifier Het CommunicationUserIdentifier wordt gebruikt om de identiteit van de gebruiker weer te geven. Dit kan een van de volgende opties zijn: CommunicationUserIdentifier, PhoneNumberIdentifier of CallingApplication.

De client verifiëren

Als u een CallAgentinitialisatie wilt uitvoeren, hebt u een token voor gebruikerstoegang nodig. Over het algemeen wordt dit token gegenereerd op basis van een service met verificatie die specifiek is voor de toepassing. Raadpleeg de handleiding gebruikerstoegangstokens voor meer informatie over tokens voor gebruikerstoegang.

Voor de quickstart vervangt u <AUTHENTICATION_TOKEN> door een gebruikerstoegangstoken dat voor uw Azure Communication Service-resource is gegenereerd.

Zodra u een token hebt geïnitialiseerd, kunt u hiermee een exemplaar initialiseren CallAgent , zodat we oproepen kunnen plaatsen en ontvangen. Om toegang te krijgen tot de camera's op het apparaat, moeten we ook Apparaatbeheer exemplaar ophalen.

Voeg de volgende code toe aan de InitCallAgentAndDeviceManagerAsync functie.

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;

Een gesprek starten met video

Voeg de implementatie toe aan de CallButton_Click implementatie om een gesprek te starten met video. We moeten de camera's inventariseren met apparaatbeheerexemplaren en constructie LocalVideoStream. We moeten het VideoOptions instellen met LocalVideoStream en doorgeven om startCallOptions de eerste opties voor het gesprek in te stellen. Door een bijlage toe LocalVideoStream te MediaPlayerElementvoegen, kunnen we het voorbeeld van de lokale video bekijken.

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;

Een inkomende oproep accepteren

Voeg de implementatie toe aan de Agent_OnIncomingCallAsync implementatie om een inkomende oproep met video te beantwoorden, door te geven LocalVideoStream aan 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);

Externe deelnemer en externe videostreams

Alle externe deelnemers zijn beschikbaar via de RemoteParticipants verzameling op een oproepexemplaren. Zodra de oproep is verbonden, hebben we toegang tot de externe deelnemers aan het gesprek en verwerken we de externe videostreams.

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

Externe video's weergeven

Voor elke externe videostream voegt u deze toe aan de 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();
        });
    }
}

Update van oproepstatus

We moeten de video-renderers opschonen zodra de oproep is verbroken en de case afhandelen wanneer de externe deelnemers in eerste instantie deelnemen aan het gesprek.

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

Een gesprek beëindigen

Beëindig het huidige gesprek wanneer op de Hang Up knop wordt geklikt. Voeg de implementatie toe aan de HangupButton_Click om een oproep te beëindigen met de callAgent die we hebben gemaakt en de gebeurtenis-handlers van de deelnemer bijwerken en aanroepen.

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

De code uitvoeren

U kunt de code bouwen en uitvoeren in Visual Studio. Voor oplossingsplatformen ondersteunen ARM64we , x64 en x86.

U kunt een uitgaande videogesprek voeren door een gebruikers-id op te geven in het tekstveld en op de Start Call knop te klikken.

Opmerking: bellen 8:echo123 stopt de videostream omdat echobot geen ondersteuning biedt voor videostreaming.

Raadpleeg de handleiding gebruikerstoegangstokens voor meer informatie over gebruikers-id's (identiteit).