Introduzione all'esempio hero chiamante
L'esempio Servizi di comunicazione di Azure Group Calling Hero illustra come usare Communication Services Calling Web SDK per creare un'esperienza di chiamata a un gruppo.
In questa guida introduttiva di esempio si apprenderà come funziona l'esempio prima di eseguire l'esempio nel computer locale e quindi distribuire l'esempio in Azure usando le proprie risorse Servizi di comunicazione di Azure.
Scaricare il codice
Trovare il progetto per questo esempio in GitHub. Una versione dell'esempio che include le funzionalità attualmente in anteprima pubblica, ad esempio Interoperabilità di Teams e Registrazione delle chiamate, è disponibile in un ramo separato.
Panoramica
L'esempio include sia un'applicazione lato client che un'applicazione lato server. L'applicazione lato client è un'applicazione Web React/Redux che usa il framework Fluent UI di Microsoft. Questa applicazione invia richieste a un'applicazione lato server ASP.NET Core tramite la quale l'applicazione lato client si connette ad Azure.
L'esempio ha l'aspetto seguente:
Quando si preme il pulsante "Start a call" (Avvia una chiamata), l'applicazione Web recupera un token di accesso utente dall'applicazione lato server. Questo token viene quindi usato per connettere l'app client a Servizi di comunicazione di Azure. Una volta recuperato il token, viene richiesto di specificare la fotocamera e il microfono da usare. È possibile disabilitare/abilitare i dispositivi con l'interruttore:
Dopo aver configurato il nome visualizzato e i dispositivi, è possibile partecipare alla sessione di chiamata. Verrà visualizzato l'area di disegno delle chiamate principale in cui si trova l'esperienza di chiamata principale.
Componenti della schermata principale della chiamata:
- Media Gallery: la fase principale in cui vengono visualizzati i partecipanti. Se un partecipante ha la fotocamera abilitata, il suo feed video viene visualizzato qui. A ogni partecipante è associato un singolo riquadro che mostra il nome visualizzato e il flusso video (se presente)
- Intestazione: qui si trovano i controlli delle chiamate primari per attivare/disattivare le impostazioni e la barra laterale del partecipante, attivare/disattivare il video, condividere lo schermo e lasciare la chiamata.
- Barra laterale: qui vengono visualizzate le informazioni sui partecipanti e sulle impostazioni quando vengono attivati o disattivati usando i controlli nell'intestazione. Il componente può essere rimosso usando la 'X' nell'angolo in alto a destra. La barra laterale dei partecipanti mostra un elenco di partecipanti e un collegamento per invitare altri utenti a chattare. La barra laterale delle impostazioni consente di configurare il microfono e la fotocamera.
Di seguito sono disponibili altre informazioni sui prerequisiti e sui passaggi per configurare l'esempio.
Prerequisiti
- Un account Azure con una sottoscrizione attiva. Per informazioni dettagliate, vedere Creare un account gratuito
- Node.js (12.18.4 e versioni successive)
- Visual Studio Code (build stabile)
- Risorsa Servizi di comunicazione di Azure. Per informazioni dettagliate, vedere Creare una risorsa Servizi di comunicazione di Azure. Per questa guida introduttiva è necessario registrare il stringa di connessione delle risorse.
Prima di eseguire l'esempio per la prima volta
Aprire un'istanza di PowerShell, Terminale Windows, prompt dei comandi o equivalente e passare alla directory in cui clonare l'esempio.
git clone https://github.com/Azure-Samples/communication-services-web-calling-hero.git
Ottenere dal
Connection String
portale di Azure o usando l'interfaccia della riga di comando di Azure.az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
Per altre informazioni sulle stringhe di connessione, vedere Creare risorse di comunicazione di Azure
Dopo aver visualizzato
Connection String
, aggiungere il stringa di connessione al file samples/Server/appsetting.json. Immettere la stringa di connessione nella variabile:ResourceConnectionString
.Ottenere dal
Endpoint string
portale di Azure o usando l'interfaccia della riga di comando di Azure.az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
Per altre informazioni sulle stringhe di endpoint, vedere Creare un'istanza di Risorse di comunicazione di Azure
Dopo aver visualizzato
Endpoint String
, aggiungere la stringa dell'endpoint al file samples/Server/appsetting.json . Immettere la stringa dell'endpoint nella variabileEndpointUrl
Esecuzione locale
Installare le dipendenze
npm run setup
Avviare l'app chiamante
npm run start
Verrà aperto un server client sulla porta 3000 che serve i file del sito Web e un server API sulla porta 8080 che esegue funzionalità come token di coniazione per i partecipanti alla chiamata.
Risoluzione dei problemi
L'app mostra una schermata "Browser non supportato", ma sono in un browser supportato.
Se l'app viene servita tramite un nome host diverso da localhost, è necessario gestire il traffico tramite https e non http.
Pubblicare in Azure
npm run setup
npm run build
npm run package
- Usare l'estensione di Azure e distribuire la directory Calling/dist nel servizio app
Pulire le risorse
Se si vuole pulire e rimuovere una sottoscrizione a Servizi di comunicazione, è possibile eliminare la risorsa o il gruppo di risorse. L'eliminazione del gruppo di risorse comporta anche l'eliminazione di tutte le altre risorse associate. Altre informazioni sulla pulizia delle risorse.
Passaggi successivi
Per altre informazioni, vedere gli articoli seguenti:
- Acquisire familiarità con l'USO di Calling SDK
- Leggere altre informazioni sul funzionamento delle chiamate
Altre letture
- Esempi: trovare altri esempi ed esempi nella pagina di panoramica degli esempi.
- Redux: gestione dello stato lato client
- FluentUI - Libreria dell'interfaccia utente di Microsoft
- React - Libreria per la compilazione di interfacce utente
- ASP.NET Core - Framework per la compilazione di applicazioni Web
L'esempio Servizi di comunicazione di Azure Group Calling Hero per iOS illustra come usare Communication Services Calling iOS SDK per creare un'esperienza di chiamata di gruppo che include voce e video. In questa guida introduttiva di esempio si apprenderà come configurare ed eseguire l'esempio. Viene fornita una panoramica dell'esempio per il contesto.
Scaricare il codice
Trovare il progetto per questo esempio in GitHub.
Panoramica
L'esempio è un'applicazione iOS nativa che usa gli SDK iOS Servizi di comunicazione di Azure per creare un'esperienza di chiamata che include sia chiamate vocali che videochiamate. L'applicazione usa un componente lato server per effettuare il provisioning dei token di accesso che vengono quindi usati per inizializzare Servizi di comunicazione di Azure SDK. Per configurare questo componente lato server, è possibile seguire l'esercitazione servizio attendibile con Funzioni di Azure.
L'esempio ha l'aspetto seguente:
Quando si preme il pulsante "Avvia nuova chiamata", l'applicazione iOS richiede di immettere il nome visualizzato da usare per la chiamata.
Dopo aver toccato "Avanti" nella schermata "Avvia chiamata", è possibile condividere l'ID gruppo della chiamata tramite il foglio di condivisione iOS.
L'applicazione consente anche di partecipare a una chiamata Servizi di comunicazione di Azure esistente specificando l'ID o l'ID team esistente.
Dopo aver aggiunto una chiamata, verrà richiesto di concedere all'applicazione l'autorizzazione per accedere alla fotocamera e al microfono, se non è già autorizzato. Tieni presente che, come tutte le app basate su AVFoundation, la vera funzionalità audio e video è disponibile solo su hardware reale.
Dopo aver configurato il nome visualizzato e aggiunto alla chiamata, verrà visualizzato l'area di disegno delle chiamate principale in cui si trova l'esperienza di chiamata principale.
Componenti della schermata principale della chiamata:
- Media Gallery: la fase principale in cui vengono visualizzati i partecipanti. Se un partecipante ha la fotocamera abilitata, il suo feed video viene visualizzato qui. Ogni partecipante ha un singolo riquadro che mostra il nome visualizzato e il flusso video (quando ne esiste uno). La raccolta supporta più partecipanti e viene aggiornata quando i partecipanti vengono aggiunti o rimossi alla chiamata.
- Barra delle azioni: è la posizione in cui si trovano i controlli delle chiamate primari. Questi controlli consentono di attivare/disattivare il video e il microfono, condividere lo schermo e lasciare la chiamata.
Di seguito sono disponibili ulteriori informazioni sui prerequisiti e i passaggi da seguire per configurare l'esempio.
Prerequisiti
- Un account Azure con una sottoscrizione attiva. Per informazioni dettagliate vedere Creare un account gratuito.
- Un Mac che esegue Xcode, insieme a un certificato dello sviluppatore valido installato nel portachiavi.
- Risorsa Servizi di comunicazione di Azure. Per informazioni dettagliate, vedere Creare una risorsa Servizi di comunicazione di Azure.
- Funzione di Azure che esegue l'endpoint di autenticazione per recuperare i token di accesso.
Esecuzione dell'esempio in locale
L'esempio di chiamata di gruppo può essere eseguito in locale usando XCode. Gli sviluppatori possono usare il dispositivo fisico o un emulatore per testare l'applicazione.
Prima di eseguire l'esempio per la prima volta
- Installare le dipendenze eseguendo
pod install
. - Aprire
AzureCalling.xcworkspace
in XCode. - Creare un file di testo nella radice, chiamato
AppSettings.xcconfig
e impostare il valore:communicationTokenFetchUrl = <your authentication endpoint, without the https:// component>
Eseguire l'esempio
Compilare ed eseguire l'esempio in XCode usando la destinazione AzureCalling nel simulatore o nel dispositivo preferito.
(Facoltativo) Protezione di un endpoint di autenticazione
A scopo dimostrativo, questo esempio usa un endpoint accessibile pubblicamente per impostazione predefinita per recuperare un token di accesso Servizi di comunicazione di Azure. Per gli scenari di produzione, è consigliabile usare il proprio endpoint protetto per effettuare il provisioning di token personalizzati.
Con una configurazione aggiuntiva, questo esempio supporta la connessione a un endpoint protetto microsoft Entra ID (Microsoft Entra ID) in modo che l'account di accesso dell'utente sia necessario affinché l'app recuperi un token di accesso Servizi di comunicazione di Azure. Vedere i passaggi seguenti:
- Abilitare l'autenticazione Di Microsoft Entra nell'app.
- Passare alla pagina di panoramica dell'app registrata in Registrazioni app Microsoft Entra. Prendere nota di
Application (client) ID
, ,Directory (tenant) ID
Application ID URI
- Creare un
AppSettings.xcconfig
file nella radice, se non è già presente e aggiungere i valori:communicationTokenFetchUrl = <Application ID URI, without the https:// component> aadClientId = <Application (client) ID> aadTenantId = <Directory (tenant) ID>
Pulire le risorse
Se si vuole pulire e rimuovere una sottoscrizione a Servizi di comunicazione, è possibile eliminare la risorsa o il gruppo di risorse. L'eliminazione del gruppo di risorse comporta anche l'eliminazione di tutte le altre risorse associate. Altre informazioni sulla pulizia delle risorse.
Passaggi successivi
Per altre informazioni, vedere gli articoli seguenti:
- Acquisire familiarità con l'USO di Calling SDK
- Leggere altre informazioni sul funzionamento delle chiamate
Altre letture
- Pagina GitHub dei servizi di comunicazione di Azure - Nella pagina ufficiale di GitHub sono disponibili altri esempi e informazioni
- Esempi: trovare altri esempi ed esempi nella pagina di panoramica degli esempi.
- Funzionalità per chiamate di comunicazione di Azure: per altre informazioni sulla chiamata di iOS SDK -Azure Communication iOS Calling SDK
L'esempio Servizi di comunicazione di Azure Group Calling Hero per Android illustra come usare Communication Services Calling Android SDK per creare un'esperienza di chiamata di gruppo che include voce e video. In questa guida introduttiva di esempio si apprenderà come configurare ed eseguire l'esempio. Viene fornita una panoramica dell'esempio per il contesto.
Scaricare il codice
Trovare il progetto per questo esempio in GitHub.
Panoramica
L'esempio è un'applicazione Android nativa che usa la libreria client dell'interfaccia utente Android Servizi di comunicazione di Azure per creare un'esperienza di chiamata che include sia chiamate vocali che videochiamate. L'applicazione usa un componente lato server per effettuare il provisioning dei token di accesso che vengono quindi usati per inizializzare Servizi di comunicazione di Azure SDK. Per configurare questo componente lato server, è possibile seguire l'esercitazione servizio attendibile con Funzioni di Azure.
L'esempio ha l'aspetto seguente:
Quando si preme il pulsante "Avvia nuova chiamata", l'applicazione Android richiede di immettere il nome visualizzato da usare per la chiamata.
Dopo aver toccato "Avanti" nella pagina "Avvia una chiamata", è possibile condividere l'ID chiamata di gruppo.
L'applicazione consente di partecipare a una chiamata Servizi di comunicazione di Azure esistente specificando l'ID della chiamata esistente o l'ID riunione team e il nome visualizzato.
Dopo aver aggiunto una chiamata, verrà richiesto di concedere all'applicazione l'autorizzazione per accedere alla fotocamera e al microfono, se non è già autorizzato. Verrà visualizzato l'area di disegno delle chiamate principale in cui si trova l'esperienza di chiamata principale.
Componenti della schermata principale della chiamata:
- Media Gallery: la fase principale in cui vengono visualizzati i partecipanti. Se un partecipante ha la fotocamera abilitata, il suo feed video viene visualizzato qui. Ogni partecipante ha un singolo riquadro che mostra il nome visualizzato e il flusso video (quando ne esiste uno). La raccolta supporta più partecipanti e viene aggiornata quando i partecipanti vengono aggiunti o rimossi alla chiamata.
- Barra delle azioni: è la posizione in cui si trovano i controlli delle chiamate primari. Questi controlli consentono di attivare/disattivare il video e il microfono, condividere lo schermo e lasciare la chiamata.
Di seguito sono disponibili ulteriori informazioni sui prerequisiti e i passaggi da seguire per configurare l'esempio.
Prerequisiti
- Un account Azure con una sottoscrizione attiva. Per informazioni dettagliate vedere Creare un account gratuito.
- Android Studio in esecuzione nel computer
- Risorsa Servizi di comunicazione di Azure. Per informazioni dettagliate, vedere Creare una risorsa Servizi di comunicazione di Azure.
- Funzione di Azure che esegue l'endpoint di autenticazione per recuperare i token di accesso.
Esecuzione dell'esempio in locale
L'esempio di chiamata di gruppo può essere eseguito in locale usando Android Studio. Gli sviluppatori possono usare il dispositivo fisico o un emulatore per testare l'applicazione.
Prima di eseguire l'esempio per la prima volta
- Aprire Android Studio e selezionare
Open an Existing Project
- Aprire la cartella all'interno della
AzureCalling
versione scaricata per l'esempio. - Espandere app/asset per aggiornare
appSettings.properties
. Impostare il valore per la chiavecommunicationTokenFetchUrl
come URL per l'endpoint di autenticazione configurato come prerequisito.
Eseguire l'esempio
Compilare ed eseguire l'esempio in Android Studio.
(Facoltativo) Protezione di un endpoint di autenticazione
A scopo dimostrativo, questo esempio usa un endpoint accessibile pubblicamente per impostazione predefinita per recuperare un token Servizi di comunicazione di Azure. Per gli scenari di produzione, è consigliabile usare il proprio endpoint protetto per effettuare il provisioning di token personalizzati.
Con una configurazione aggiuntiva, questo esempio supporta la connessione a un endpoint protetto microsoft Entra ID (Microsoft Entra ID) in modo che l'account di accesso utente sia necessario per l'app per recuperare un token di Servizi di comunicazione di Azure. Vedere i passaggi seguenti:
Abilitare l'autenticazione Di Microsoft Entra nell'app.
Passare alla pagina di panoramica dell'app registrata in Registrazioni app Microsoft Entra. Prendere nota di
Package name
,Signature hash
,MSAL Configutaion
.
Modificare
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
e impostareisAADAuthEnabled
per abilitare Microsoft Entra ID.Modificare
AndroidManifest.xml
e impostare l'hashandroid:path
della firma dell'archivio chiavi. (Facoltativo. Il valore corrente usa l'hash di debug.keystore in bundle. Se viene usato un archivio chiavi diverso, è necessario aggiornarlo.<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>
Copiare la configurazione di MSAL Android da portale di Azure e incollarla in
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
. Includere "account_mode": "SINGLE"{ "client_id": "", "authorization_user_agent": "DEFAULT", "redirect_uri": "", "account_mode" : "SINGLE", "authorities": [ { "type": "AAD", "audience": { "type": "AzureADMyOrg", "tenant_id": "" } } ] }
Modificare
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
e impostare il valore della chiavecommunicationTokenFetchUrl
come URL per l'endpoint di autenticazione sicuro.Modificare
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
e impostare il valore per la chiaveaadScopes
dagliAzure Active Directory
Expose an API
ambitiImpostare il valore per
graphURL
inAzureCalling/app/assets/appSettings.properties
come endpoint dell'API Graph per recuperare le informazioni utente.Modificare
AzureCalling/app/src/main/assets/appSettings.properties
e impostare il valore per la chiavetenant
per abilitare l'accesso invisibile all'utente in modo che l'utente non deve essere autenticato nuovamente e di nuovo durante il riavvio dell'applicazione.
Pulire le risorse
Se si vuole pulire e rimuovere una sottoscrizione a Servizi di comunicazione, è possibile eliminare la risorsa o il gruppo di risorse. L'eliminazione del gruppo di risorse comporta anche l'eliminazione di tutte le altre risorse associate. Altre informazioni sulla pulizia delle risorse.
Passaggi successivi
Per altre informazioni, vedere gli articoli seguenti:
- Acquisire familiarità con l'USO di Calling SDK
- Leggere altre informazioni sul funzionamento delle chiamate
Altre letture
- Pagina GitHub dei servizi di comunicazione di Azure - Nella pagina ufficiale di GitHub sono disponibili altri esempi e informazioni
- Esempi: trovare altri esempi ed esempi nella pagina di panoramica degli esempi.
- Funzionalità per chiamate di comunicazione di Azure: per altre informazioni sulla chiamata di Android SDK -Azure Communication Android Calling SDK
L'esempio Servizi di comunicazione di Azure Group Calling Hero per Windows illustra come usare Servizi di comunicazione che chiamano Windows SDK per creare un'esperienza di chiamata di gruppo che include voce e video. In questo esempio si apprenderà come configurare ed eseguire l'esempio. Viene fornita una panoramica dell'esempio per il contesto.
Questo argomento di avvio rapido illustra come avviare una videochiamata 1:1 usando Servizi di comunicazione di Azure Calling SDK per Windows.
Codice di esempio UWP
Prerequisiti
Per completare questa esercitazione è necessario soddisfare i prerequisiti seguenti:
Un account Azure con una sottoscrizione attiva. Creare un account gratuitamente.
Installare Visual Studio 2022 con piattaforma UWP (Universal Windows Platform) carico di lavoro sviluppo.
Una risorsa di Servizi di comunicazione distribuita. Creare una risorsa di Servizi di comunicazione. È necessario registrare il stringa di connessione per questa guida introduttiva.
Un token di accesso utente per il servizio di comunicazione di Azure. È anche possibile usare l'interfaccia della riga di comando di Azure ed eseguire il comando con il stringa di connessione per creare un utente e un token di accesso.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Per informazioni dettagliate, vedere Usare l'interfaccia della riga di comando di Azure per creare e gestire i token di accesso.
Configurazione
Creazione del progetto
In Visual Studio creare un nuovo progetto con il modello App vuota (Windows universale) per configurare un'app UWP (Single Page Piattaforma UWP (Universal Windows Platform)).
Installare il pacchetto
Fare clic con il pulsante destro del mouse sul progetto e passare a Manage Nuget Packages
per installare Azure.Communication.Calling.WindowsClient
la versione 1.2.0-beta.1 o superiore. Verificare che l'opzione Includi Preleased sia selezionata.
Richiedere l'accesso
Passare a Package.appxmanifest
e fare clic su Capabilities
.
Controllare Internet (Client & Server)
di ottenere l'accesso in ingresso e in uscita a Internet.
Controllare Microphone
di accedere al feed audio del microfono.
Controllare WebCam
di accedere alla fotocamera del dispositivo.
Aggiungere il codice seguente al Package.appxmanifest
proprio facendo clic con il pulsante destro del mouse e scegliendo Visualizza codice.
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
Configurare il framework dell'app
È necessario configurare un layout di base per collegare la logica. Per effettuare una chiamata in uscita, è necessario specificare TextBox
l'ID utente del chiamato. Abbiamo anche bisogno di un Start Call
pulsante e un Hang Up
pulsante.
È anche necessario visualizzare in anteprima il video locale ed eseguire il rendering del video remoto dell'altro partecipante. Sono quindi necessari due elementi per visualizzare i flussi video.
Aprire il MainPage.xaml
del progetto e sostituire il contenuto con l'implementazione seguente.
<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>
Aprire su App.xaml.cs
(fare clic con il pulsante destro del mouse e scegliere Visualizza codice) e aggiungere questa riga all'inizio:
using CallingQuickstart;
Aprire (fare clic con il pulsante destro del MainPage.xaml.cs
mouse e scegliere Visualizza codice) e sostituire il contenuto con l'implementazione seguente:
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
}
}
}
Modello a oggetti
Le classi e le interfacce seguenti gestiscono alcune delle principali funzionalità di Servizi di comunicazione di Azure Calling SDK:
Nome | Descrizione |
---|---|
CallClient |
CallClient è il punto di ingresso principale della libreria client chiamante. |
CallAgent |
Viene CallAgent utilizzato per avviare e partecipare alle chiamate. |
CommunicationCall |
L'oggetto CommunicationCall viene utilizzato per gestire le chiamate inserite o unite in join. |
CallTokenCredential |
Viene CallTokenCredential usato come credenziale del token per creare un'istanza di CallAgent . |
CommunicationUserIdentifier |
Viene CommunicationUserIdentifier usato per rappresentare l'identità dell'utente, che può essere una delle opzioni seguenti: CommunicationUserIdentifier o PhoneNumberIdentifier CallingApplication . |
Autenticare il client
Per inizializzare un , CallAgent
è necessario un token di accesso utente. In genere questo token viene generato da un servizio con autenticazione specifica per l'applicazione. Per altre informazioni sui token di accesso utente, vedere la Guida ai token di accesso utente.
Per la guida di avvio rapido, sostituire <AUTHENTICATION_TOKEN>
con un token di accesso utente generato per la risorsa del servizio di comunicazione di Azure.
Dopo aver ottenuto un token, inizializzare un'istanza CallAgent
con essa, che consente di effettuare e ricevere chiamate. Per accedere alle fotocamere nel dispositivo, è anche necessario ottenere Gestione dispositivi istanza.
Aggiungere il codice seguente alla InitCallAgentAndDeviceManagerAsync
funzione .
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
}
}
Avviare una chiamata con il video
Aggiungere l'implementazione a CallButton_Click
per avviare una chiamata con il video. È necessario enumerare le fotocamere con l'istanza di Gestione dispositivi e costruire LocalOutgoingVideoStream
. È necessario impostare VideoOptions
con LocalVideoStream
e passarlo con startCallOptions
per impostare le opzioni iniziali per la chiamata. LocalOutgoingVideoStream
Collegando a un MediaElement
oggetto , è possibile visualizzare l'anteprima del video locale.
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;
}
Aggiungere i metodi per avviare o partecipare ai diversi tipi di chiamata (1:1 Servizi di comunicazione di Azure chiamata, 1:1 telefonata, Servizi di comunicazione di Azure chiamata di gruppo, partecipazione alla riunione di Teams e così via).
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 } }
};
}
Aggiungere il codice per creare LocalVideoStream a seconda della fotocamera selezionata nel CameraList_SelectionChanged
metodo .
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);
}
Accettare una chiamata in ingresso
Aggiungere l'implementazione a per rispondere a OnIncomingCallAsync
una chiamata in ingresso con video, passare LocalVideoStream
a acceptCallOptions
.
var incomingCall = args.IncomingCall;
var acceptCallOptions = new AcceptCallOptions() {
IncomingVideoOptions = new IncomingVideoOptions()
{
IncomingVideoStreamKind = VideoStreamKind.RemoteIncoming
}
};
_ = await incomingCall.AcceptAsync(acceptCallOptions);
Partecipanti remoti e flussi video remoti
Tutti i partecipanti remoti sono disponibili tramite la raccolta in un'istanza RemoteParticipants
di chiamata. Una volta connessa la chiamata, è possibile accedere ai partecipanti remoti della chiamata e gestire i flussi video remoti.
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;
}
}
Eseguire il rendering di video remoti
Per ogni flusso video remoto, collegarlo all'oggetto 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();
});
}
}
Aggiornamento dello stato della chiamata
È necessario pulire i renderer video una volta disconnessa la chiamata e gestire il caso quando i partecipanti remoti partecipano inizialmente alla chiamata.
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;
}
}
Terminare una chiamata
Terminare la chiamata corrente quando si fa clic sul Hang Up
pulsante. Aggiungere l'implementazione al HangupButton_Click per terminare una chiamata con callAgent creato e rimuovere i gestori eventi di chiamata e aggiornamento del partecipante.
var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
try
{
await call.HangUpAsync(new HangUpOptions() { ForEveryone = true });
}
catch(Exception ex)
{
}
}
Eseguire il codice
È possibile compilare ed eseguire il codice in Visual Studio. Per le piattaforme di soluzioni, è supportato ARM64
, x64
e x86
.
È possibile effettuare una videochiamata in uscita specificando un ID utente nel campo di testo e facendo clic sul Start Call
pulsante.
Nota: la chiamata arresta 8:echo123
il flusso video perché echo bot non supporta lo streaming video.
Per altre informazioni sugli ID utente (identità) vedere la guida ai token di accesso utente.
Codice di esempio winUI 3
Prerequisiti
Per completare questa esercitazione è necessario soddisfare i prerequisiti seguenti:
Un account Azure con una sottoscrizione attiva. Creare un account gratuitamente.
Installare Visual Studio 2022 e SDK per app di Windows versione 1.2 preview 2.
Conoscenza di base di come creare un'app WinUI 3. Creare il primo progetto WinUI 3 (SDK per app di Windows) è una buona risorsa da cui iniziare.
Una risorsa di Servizi di comunicazione distribuita. Creare una risorsa di Servizi di comunicazione. È necessario registrare il stringa di connessione per questa guida introduttiva.
Un token di accesso utente per il servizio di comunicazione di Azure. È anche possibile usare l'interfaccia della riga di comando di Azure ed eseguire il comando con il stringa di connessione per creare un utente e un token di accesso.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Per informazioni dettagliate, vedere Usare l'interfaccia della riga di comando di Azure per creare e gestire i token di accesso.
Configurazione
Creazione del progetto
In Visual Studio creare un nuovo progetto con il modello App vuota, In pacchetto (WinUI 3 in Desktop) per configurare un'app WinUI 3 a pagina singola.
Installare il pacchetto
Fare clic con il pulsante destro del mouse sul progetto e passare a Manage Nuget Packages
per installare Azure.Communication.Calling.WindowsClient
la versione 1.0.0 o superiore. Verificare che l'opzione Includi Preleased sia selezionata.
Richiedere l'accesso
Aggiungere il codice seguente a app.manifest
:
<file name="RtmMvrMf.dll">
<activatableClass name="VideoN.VideoSchemeHandler" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>
Configurare il framework dell'app
È necessario configurare un layout di base per collegare la logica. Per effettuare una chiamata in uscita, è necessario specificare TextBox
l'ID utente del chiamato. Abbiamo anche bisogno di un Start Call
pulsante e un Hang Up
pulsante.
È anche necessario visualizzare in anteprima il video locale ed eseguire il rendering del video remoto dell'altro partecipante. Sono quindi necessari due elementi per visualizzare i flussi video.
Aprire il MainWindow.xaml
del progetto e sostituire il contenuto con l'implementazione seguente.
<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>
Aprire su App.xaml.cs
(fare clic con il pulsante destro del mouse e scegliere Visualizza codice) e aggiungere questa riga all'inizio:
using CallingQuickstart;
Aprire (fare clic con il pulsante destro del MainWindow.xaml.cs
mouse e scegliere Visualizza codice) e sostituire il contenuto con l'implementazione seguente:
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();
});
}
}
}
Modello a oggetti
Le classi e le interfacce seguenti gestiscono alcune delle principali funzionalità di Servizi di comunicazione di Azure Calling SDK:
Nome | Descrizione |
---|---|
CallClient |
CallClient è il punto di ingresso principale della libreria client chiamante. |
CallAgent |
Viene CallAgent utilizzato per avviare e partecipare alle chiamate. |
CommunicationCall |
L'oggetto CommunicationCall viene utilizzato per gestire le chiamate inserite o unite in join. |
CallTokenCredential |
Viene CallTokenCredential usato come credenziale del token per creare un'istanza di CallAgent . |
CommunicationUserIdentifier |
Viene CommunicationUserIdentifier usato per rappresentare l'identità dell'utente, che può essere una delle opzioni seguenti: CommunicationUserIdentifier o PhoneNumberIdentifier CallingApplication . |
Autenticare il client
Per inizializzare un , CallAgent
è necessario un token di accesso utente. In genere questo token viene generato da un servizio con autenticazione specifica per l'applicazione. Per altre informazioni sui token di accesso utente, vedere la Guida ai token di accesso utente.
Per la guida di avvio rapido, sostituire <AUTHENTICATION_TOKEN>
con un token di accesso utente generato per la risorsa del servizio di comunicazione di Azure.
Dopo aver inizializzato un CallAgent
token con esso, che consente di effettuare e ricevere chiamate. Per accedere alle fotocamere nel dispositivo, è anche necessario ottenere Gestione dispositivi istanza.
Aggiungere il codice seguente alla InitCallAgentAndDeviceManagerAsync
funzione .
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;
Avviare una chiamata con il video
Aggiungere l'implementazione a CallButton_Click
per avviare una chiamata con il video. È necessario enumerare le fotocamere con l'istanza di Gestione dispositivi e costruire LocalVideoStream
. È necessario impostare VideoOptions
con LocalVideoStream
e passarlo con startCallOptions
per impostare le opzioni iniziali per la chiamata. LocalVideoStream
Collegando a un MediaPlayerElement
oggetto , è possibile visualizzare l'anteprima del video locale.
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;
Accettare una chiamata in ingresso
Aggiungere l'implementazione a per rispondere a Agent_OnIncomingCallAsync
una chiamata in ingresso con video, passare LocalVideoStream
a 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);
Partecipanti remoti e flussi video remoti
Tutti i partecipanti remoti sono disponibili tramite la raccolta in un'istanza RemoteParticipants
di chiamata. Una volta connessa la chiamata, è possibile accedere ai partecipanti remoti della chiamata e gestire i flussi video remoti.
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);
}
}
Eseguire il rendering di video remoti
Per ogni flusso video remoto, collegarlo all'oggetto 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();
});
}
}
Aggiornamento dello stato della chiamata
È necessario pulire i renderer video una volta disconnessa la chiamata e gestire il caso quando i partecipanti remoti partecipano inizialmente alla chiamata.
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;
}
}
Terminare una chiamata
Terminare la chiamata corrente quando si fa clic sul Hang Up
pulsante. Aggiungere l'implementazione al HangupButton_Click per terminare una chiamata con callAgent creato e rimuovere i gestori eventi di chiamata e aggiornamento del partecipante.
this.call.OnRemoteParticipantsUpdated -= Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged -= Call_OnStateChangedAsync;
await this.call.HangUpAsync(new HangUpOptions());
Eseguire il codice
È possibile compilare ed eseguire il codice in Visual Studio. Per le piattaforme di soluzioni, è supportato ARM64
, x64
e x86
.
È possibile effettuare una videochiamata in uscita specificando un ID utente nel campo di testo e facendo clic sul Start Call
pulsante.
Nota: la chiamata arresta 8:echo123
il flusso video perché echo bot non supporta lo streaming video.
Per altre informazioni sugli ID utente (identità) vedere la guida ai token di accesso utente.