Introducción a la muestra de elementos principales de una llamada
En el ejemplo de elementos principales de llamada grupal de Azure Communication Services se muestra cómo se puede usar el SDK web de llamadas de Communication Services para crear una experiencia de llamada grupal.
En esta guía de inicio rápido con un ejemplo, se muestra cómo funciona el ejemplo antes de ejecutarlo en su equipo local y, después, lo implementa en Azure con sus propios recursos de Azure Communication Services.
Descarga de código
Busque el proyecto de este ejemplo en GitHub. En otra rama, hay una versión del ejemplo que incluye características que actualmente están en versión preliminar pública, como la interoperabilidad entre equipos y la grabación de llamadas.
Información general
El ejemplo tiene una aplicación del lado cliente y una aplicación del lado servidor. La aplicación del lado cliente es una aplicación web React/Redux que usa el marco de interfaz de usuario Fluent de Microsoft. Esta aplicación envía solicitudes a una aplicación del lado servidor de ASP.NET Core que ayuda a la aplicación del lado cliente a conectarse a Azure.
El ejemplo tendrá una apariencia similar a la siguiente:
Cuando se presiona el botón "Start a call", la aplicación web captura un token de acceso de usuario de la aplicación del lado servidor. A continuación, este token se usa para conectar la aplicación cliente con Azure Communication Services. Una vez recuperado el token, se le pide que especifique la cámara y el micrófono que quiere usar. Puede deshabilitar o habilitar los dispositivos con los controles de alternancia:
Una vez que configure el nombre para mostrar y los dispositivos, puede unirse a la sesión de llamada. Verá el lienzo de llamada principal en el que se encuentra la experiencia de llamada principal.
Componentes de la pantalla principal de llamada:
- Galería multimedia: la fase principal en la que se muestran los participantes. Si un participante tiene habilitada la cámara, aquí se muestra su fuente de vídeo. Cada participante tiene un icono individual que muestra su nombre para mostrar y la transmisión de vídeo (si hay alguna).
- Encabezado: aquí es donde se encuentran los controles de llamada principales para ajustar la configuración y la barra lateral de participantes, activar o desactivar el vídeo y mezclas, compartir la pantalla y abandonar la llamada.
- Barra lateral: aquí es donde se muestran los participantes y la información de configuración cuando se ajustan con los controles del encabezado. El componente se puede descartar con la "X" de la esquina superior derecha. En la barra lateral de participantes se muestra una lista de participantes y un vínculo para invitar a más usuarios a chatear. La barra lateral de configuración permite configurar las opciones del micrófono y la cámara.
A continuación se proporciona más información sobre los requisitos previos y los pasos para configurar el ejemplo.
Requisitos previos
- Una cuenta de Azure con una suscripción activa. Para más información, consulte Creación de una cuenta gratuita
- Node.js (12.18.4 y posterior)
- Visual Studio Code (compilación estable)
- Un recurso de Azure Communication Services. Para más información, consulte Creación de un recurso de Azure Communication Services. Debe registrar la cadena de conexión del recurso para esta guía de inicio rápido.
Antes de ejecutar el ejemplo por primera vez
Abra una instancia de PowerShell, Terminal Windows, símbolo del sistema o equivalente y navegue hasta el directorio donde le gustaría clonar el ejemplo.
git clone https://github.com/Azure-Samples/communication-services-web-calling-hero.git
Obtenga
Connection String
en Azure Portal o mediante la CLI de Azure.az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
Para obtener más información sobre las cadenas de conexión, consulte Creación de un recurso de Azure Communication Services.
Cuando obtenga el valor de
Connection String
, agréguelo al archivo samples/Server/appsetting.json. Escriba la cadena de conexión en la variable:ResourceConnectionString
.Obtenga
Endpoint string
en Azure Portal o mediante la CLI de Azure.az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
Para obtener más información sobre las cadenas de punto de conexión, consulte el artículo Creación de recursos de Azure Communication Services.
Cuando obtenga el valor de
Endpoint String
, agréguelo al archivo samples/Server/appsetting.json. Escriba la cadena de punto de conexión en la variableEndpointUrl
Ejecución local
Instalar dependencias
npm run setup
Inicio de la aplicación de llamada
npm run start
Esto abre una conexión cliente-servidor en el puerto 3000 que sirve los archivos del sitio web, así como un servidor de API en el puerto 8080 que realiza funciones como la creación de tokens para los participantes de las llamadas.
Solucionar problemas
La aplicación muestra una pantalla con un mensaje de "Explorador no compatible", pero estoy usando un explorador compatible.
Si la aplicación está dando servicio mediante un nombre de host distinto de localhost, deberá ofrecer el tráfico a través del protocolo https y no mediante http.
Publicar en Azure
npm run setup
npm run build
npm run package
- Use la extensión de Azure e implemente el directorio Calling/dist en el servicio de aplicaciones
Limpieza de recursos
Si quiere limpiar y quitar una suscripción a Communication Services, puede eliminar el recurso o grupo de recursos. Al eliminar el grupo de recursos, también se elimina cualquier otro recurso que esté asociado a él. Obtenga más información sobre la limpieza de recursos.
Pasos siguientes
Para más información, consulte los siguientes artículos.
- Familiarícese con el uso del SDK de llamadas.
- Más información sobre cómo funciona la llamada
Lecturas adicionales
- Ejemplos: encuentre más ejemplos en nuestra página de información general de ejemplos.
- Redux: Administración de estado del lado cliente
- FluentUI: Biblioteca de interfaz de usuario con tecnología de Microsoft
- React: Biblioteca para compilar interfaces de usuario
- ASP.NET Core: Marco para compilar aplicaciones web
El ejemplo de elementos principales de llamada de grupo para iOS de Azure Communication Services muestra cómo usar Calling SDK de Communication Services para iOS para crear una experiencia de llamada de grupo que incluya voz y vídeo. En este inicio rápido de ejemplo, aprenderá a configurar y ejecutar el ejemplo. Se proporciona información general del ejemplo con fines de contextualización.
Descarga de código
Busque el proyecto de este ejemplo en GitHub.
Información general
El ejemplo consiste en una aplicación iOS nativa que usa los SDK de Azure Communication Services para iOS para crear una experiencia de llamada que incluya llamadas de voz y vídeo. La aplicación usa un componente de servidor para aprovisionar los tokens de acceso que, posteriormente, se usan para inicializar el SDK de Azure Communication Services. Para configurar este componente de servidor, siga el tutorial Creación de un servicio de autenticación de confianza mediante Azure Functions.
El ejemplo tendrá una apariencia similar a la siguiente:
Al presionar el botón "Iniciar nueva llamada", la aplicación de iOS le pide que escriba el nombre para mostrar que se usará para la llamada.
Después de pulsar "Siguiente" en la pantalla "Iniciar llamada", podrá compartir el identificador de grupo de la llamada a través de la hoja de recursos compartidos de iOS.
La aplicación también le permite unirse a una llamada existente de Azure Communication Services mediante el identificador de esa llamada o el vínculo de identificador de Teams.
Después de unirse a una llamada, se le solicitará que conceda permiso a la aplicación para acceder a la cámara y el micrófono si aún no están autorizados. Tenga en cuenta que, al igual que todas las aplicaciones basadas en AVFoundation, la verdadera funcionalidad de audio y vídeo solo está disponible en hardware real.
Después de configurar el nombre para mostrar y unirse a la llamada, verá el lienzo de llamadas principal donde reside la experiencia de llamada principal.
Componentes de la pantalla principal de llamada:
- Galería multimedia: la fase principal en la que se muestran los participantes. Si un participante tiene habilitada la cámara, aquí se muestra su fuente de vídeo. Cada participante tiene un icono individual con su nombre para mostrar y la secuencia de vídeo (si la hay). La galería admite varios participantes y se actualiza al agregarlos o al quitarlos de la llamada.
- Barra de acciones: Aquí es donde se encuentran los principales controles de llamada. Estos controles permiten activar o desactivar el vídeo y el micrófono, compartir la pantalla y abandonar la llamada.
A continuación encontrará más información sobre los requisitos previos y los pasos para configurar el ejemplo.
Requisitos previos
- Una cuenta de Azure con una suscripción activa. Para más información, consulte Creación de una cuenta gratuita.
- Mac con Xcode, junto con un certificado de desarrollador válido instalado en el Llavero.
- Un recurso de Azure Communication Services. Para más información, consulte Creación de un recurso de Azure Communication Services.
- Una función de Azure que ejecuta el punto de conexión de autenticación para capturar tokens de acceso.
Ejecución local del ejemplo
El ejemplo de llamada de grupo se puede ejecutar localmente mediante XCode. Los desarrolladores pueden usar su dispositivo físico o un emulador para probar la aplicación.
Antes de ejecutar el ejemplo por primera vez
- Instale las dependencias mediante la ejecución de
pod install
. - Abra
AzureCalling.xcworkspace
en XCode. - Cree un archivo de texto en la raíz, denominado
AppSettings.xcconfig
y establezca el valor:communicationTokenFetchUrl = <your authentication endpoint, without the https:// component>
Ejecución del ejemplo
Compile y ejecute el ejemplo en XCode, utilizando el destino AzureCalling en el simulador o el dispositivo que prefiera.
(Opcional) Protección de un punto de conexión de autenticación
Con fines de demostración, en este ejemplo se usa de forma predeterminada un punto de conexión de acceso público para capturar un token de acceso de Azure Communication Services. En escenarios de producción, se recomienda usar un punto de conexión propio protegido para aprovisionar los tokens.
Mediante alguna configuración adicional, este ejemplo permite conectarse a un punto de conexión protegido de Microsoft Entra ID (Microsoft Entra ID) de manera que se solicite el inicio de sesión de usuario para que la aplicación capture un token de acceso de Azure Communication Services. Consulte los siguientes pasos:
- Habilite la autenticación de Microsoft Entra en la aplicación.
- Vaya a la página de información general de la aplicación registrada en Registros de aplicaciones de Microsoft Entra. Anote los valores de
Application (client) ID
,Directory (tenant) ID
,Application ID URI
.
- Cree un archivo
AppSettings.xcconfig
en la raíz si aún no está presente y agregue los valores:communicationTokenFetchUrl = <Application ID URI, without the https:// component> aadClientId = <Application (client) ID> aadTenantId = <Directory (tenant) ID>
Limpieza de recursos
Si quiere limpiar y quitar una suscripción a Communication Services, puede eliminar el recurso o grupo de recursos. Al eliminar el grupo de recursos, también se elimina cualquier otro recurso que esté asociado a él. Obtenga más información sobre la limpieza de recursos.
Pasos siguientes
Para más información, consulte los siguientes artículos.
- Familiarícese con el uso del SDK de llamadas.
- Más información sobre cómo funciona la llamada
Lecturas adicionales
- GitHub de Azure Communication: encuentre más ejemplos e información en la página oficial de GitHub.
- Ejemplos: encuentre más ejemplos en nuestra página de información general de ejemplos.
- Características de llamada de Azure Communication Services: para más información sobre el SDK de llamada para iOS, consulte Calling SDK de Azure Communication Services.
El ejemplo de elementos principales de llamada de grupo para Android de Azure Communication Services muestra cómo usar el SDK de llamadas de Communication Services para Android para crear una experiencia de llamada de grupo que incluya voz y vídeo. En este inicio rápido de ejemplo, aprenderá a configurar y ejecutar el ejemplo. Se proporciona información general del ejemplo con fines de contextualización.
Descarga de código
Busque el proyecto de este ejemplo en GitHub.
Información general
El ejemplo consiste en una aplicación Android nativa que usa la biblioteca de cliente de la interfaz de usuario de Azure Communication Services para Android para crear una experiencia de llamada que incluya llamadas de voz y vídeo. La aplicación usa un componente de servidor para aprovisionar los tokens de acceso que, posteriormente, se usan para inicializar el SDK de Azure Communication Services. Para configurar este componente de servidor, siga el tutorial Creación de un servicio de autenticación de confianza mediante Azure Functions.
El ejemplo tendrá una apariencia similar a la siguiente:
Al presionar el botón "Iniciar nueva llamada", la aplicación Android le pedirá que escriba el nombre para mostrar que se usará para la llamada.
Después de pulsar "Siguiente" en la página "Iniciar una llamada", podrá compartir el "Id. de llamada de grupo".
La aplicación también le permite unirse a una llamada existente de Azure Communication Services al especificar el identificador de esa llamada o el vínculo de identificador y el nombre para mostrar de la reunión de Teams.
Después de unirse a una llamada, se le solicitará que conceda permiso a la aplicación para acceder a la cámara y el micrófono si aún no están autorizados. Verá el panel de llamada principal en el que reside la experiencia de llamada.
Componentes de la pantalla principal de llamada:
- Galería multimedia: la fase principal en la que se muestran los participantes. Si un participante tiene habilitada la cámara, aquí se muestra su fuente de vídeo. Cada participante tiene un icono individual con su nombre para mostrar y la secuencia de vídeo (si la hay). La galería admite varios participantes y se actualiza al agregarlos o al quitarlos de la llamada.
- Barra de acciones: Aquí es donde se encuentran los principales controles de llamada. Estos controles permiten activar o desactivar el vídeo y el micrófono, compartir la pantalla y abandonar la llamada.
A continuación encontrará más información sobre los requisitos previos y los pasos para configurar el ejemplo.
Requisitos previos
- Una cuenta de Azure con una suscripción activa. Para más información, consulte Creación de una cuenta gratuita.
- Android Studio en ejecución en el equipo.
- Un recurso de Azure Communication Services. Para más información, consulte Creación de un recurso de Azure Communication Services.
- Una función de Azure que ejecuta el punto de conexión de autenticación para capturar tokens de acceso.
Ejecución local del ejemplo
El ejemplo de llamada de grupo se puede ejecutar localmente mediante Android Studio. Los desarrolladores pueden usar su dispositivo físico o un emulador para probar la aplicación.
Antes de ejecutar el ejemplo por primera vez
- Abra Android Studio y seleccione
Open an Existing Project
. - Abra la carpeta
AzureCalling
dentro de la versión descargada para el ejemplo. - Expanda las aplicaciones o recursos para actualizar
appSettings.properties
. Establezca el valor de la clavecommunicationTokenFetchUrl
para que sea la dirección URL del punto de conexión de autenticación configurado como requisito previo.
Ejecución del ejemplo
Compile y ejecute el ejemplo en Android Studio.
(Opcional) Protección de un punto de conexión de autenticación
Con fines de demostración, este ejemplo usa un punto de conexión de acceso público de forma predeterminada para capturar un token de Azure Communication Services. En escenarios de producción, se recomienda usar un punto de conexión propio protegido para aprovisionar los tokens.
Mediante alguna configuración adicional, este ejemplo permite conectarse a un punto de conexión protegido de Microsoft Entra ID (Microsoft Entra ID) de manera que se solicite el inicio de sesión de usuario para que la aplicación capture un token de Azure Communication Services. Consulte los siguientes pasos:
Habilite la autenticación de Microsoft Entra en la aplicación.
Vaya a la página de información general de la aplicación registrada en Registros de aplicaciones de Microsoft Entra. Anote los valores de
Package name
,Signature hash
,MSAL Configuration
.
Edición de
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
y establecimiento deisAADAuthEnabled
para habilitar Microsoft Entra ID.Edite
AndroidManifest.xml
y establezcaandroid:path
en el hash de firma del almacén de claves. (Opcional. El valor actual usa un hash de tipo debug.keystore que está incluido. Si se usa un almacén de claves diferente, debe actualizarse).<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>
Copie la configuración de MSAL para Android desde Azure Portal y péguela en
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
. Incluya "account_mode": "SINGLE".{ "client_id": "", "authorization_user_agent": "DEFAULT", "redirect_uri": "", "account_mode" : "SINGLE", "authorities": [ { "type": "AAD", "audience": { "type": "AzureADMyOrg", "tenant_id": "" } } ] }
Edite
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
y establezca el valor de la clavecommunicationTokenFetchUrl
para que sea la dirección URL del punto de conexión de autenticación.Edite
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
y establezca el valor de la claveaadScopes
desde los ámbitosExpose an API
deAzure Active Directory
.Establezca el valor de
graphURL
enAzureCalling/app/assets/appSettings.properties
como punto de conexión de Graph API para capturar información del usuario.Edite
AzureCalling/app/src/main/assets/appSettings.properties
y establezca el valor de la clavetenant
para habilitar el inicio de sesión silencioso para que el usuario no tenga que autenticarse de nuevo y de nuevo al reiniciar la aplicación.
Limpieza de recursos
Si quiere limpiar y quitar una suscripción a Communication Services, puede eliminar el recurso o grupo de recursos. Al eliminar el grupo de recursos, también se elimina cualquier otro recurso que esté asociado a él. Obtenga más información sobre la limpieza de recursos.
Pasos siguientes
Para más información, consulte los siguientes artículos.
- Familiarícese con el uso del SDK de llamadas.
- Más información sobre cómo funciona la llamada
Lecturas adicionales
- GitHub de Azure Communication: encuentre más ejemplos e información en la página oficial de GitHub.
- Ejemplos: encuentre más ejemplos en nuestra página de información general de ejemplos.
- Características de llamada de Azure Communication Services: para más información sobre el SDK de llamada para Android, consulte SDK de llamadas de Azure Communication Services.
El ejemplo de elementos principales de llamada de grupo para Windows de Azure Communication Services muestra cómo usar Calling SDK de Communication Services para Windows para crear una experiencia de llamada de grupo que incluya voz y vídeo. En este ejemplo, aprenderá a configurar y ejecutar el ejemplo. Se proporciona información general del ejemplo con fines de contextualización.
En este artículo de inicio rápido aprenderá a iniciar una videollamada 1:1 con el SDK de llamada de Azure Communication Services para Windows.
Código de ejemplo de UWP
Requisitos previos
Para completar este tutorial, debe cumplir los siguientes requisitos previos:
Una cuenta de Azure con una suscripción activa. Cree una cuenta gratuita.
Instale Visual Studio 2022 con la carga de trabajo de desarrollo de la Plataforma universal de Windows.
Un recurso de Communication Services implementado. Cree un recurso de Communication Services. Debe registrar la cadena de conexión para esta guía de inicio rápido.
Un token de acceso de usuario para su instancia de Azure Communication Services. También puede usar la CLI de Azure y ejecutar el comando siguiente con la cadena de conexión para crear un usuario y un token de acceso.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Para más información, consulte Uso de la CLI de Azure para crear y administrar tokens de acceso.
Instalación
Creación del proyecto
En Visual Studio, cree un proyecto con la plantilla Aplicación vacía (Windows universal) para configurar una aplicación para la Plataforma universal de Windows (UWP) de una sola página.
Instalar el paquete
Haga clic con el botón derecho en su proyecto y vaya a Manage Nuget Packages
para instalar la versión Azure.Communication.Calling.WindowsClient
1.2.0-beta.1 o superior. Asegúrese de que la casilla Incluir versión preliminar esté activada.
Solicitar acceso
Vaya a Package.appxmanifest
y haga clic en Capabilities
.
Compruebe Internet (Client & Server)
para obtener acceso entrante y saliente a Internet.
Compruebe Microphone
para acceder a la fuente de audio del micrófono.
Compruebe WebCam
para acceder a la cámara del dispositivo.
Agregue el código siguiente a Package.appxmanifest
, para lo que debe clic con el botón derecho y elegir View Code (Ver código).
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
Instalación del marco de la aplicación
Es necesario configurar un diseño básico para adjuntar la lógica. Para hacer una llamada saliente, se necesita un elemento TextBox
para proporcionar el id. de usuario del destinatario. También se necesita un botón Start Call
y un botón Hang Up
.
También es necesario obtener una vista previa del vídeo local y representar el vídeo remoto del otro participante. Por lo tanto, necesitamos dos elementos para mostrar las secuencias de vídeo.
Abra MainPage.xaml
del proyecto y reemplace el contenido por la siguiente implementación.
<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>
Ábralo en App.xaml.cs
(haga clic con el botón derecho y elija Ver código) y agregue esta línea al principio:
using CallingQuickstart;
Abra MainPage.xaml.cs
(haga clic con el botón derecho y elija Ver código) y reemplace el contenido por la siguiente implementación:
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
}
}
}
Modelo de objetos
Las siguientes clases e interfaces controlan algunas de las características principales del SDK de llamadas de Azure Communication Services:
Nombre | Descripción |
---|---|
CallClient |
CallClient es el punto de entrada principal a la biblioteca cliente de llamadas. |
CallAgent |
CallAgent se usa para iniciar llamadas y unirse a estas. |
CommunicationCall |
CommunicationCall se usa para administrar las llamadas realizadas o a las que se ha unido. |
CallTokenCredential |
CallTokenCredential se usa como la credencial del token para crear una instancia de CallAgent . |
CommunicationUserIdentifier |
CommunicationUserIdentifier se usa para representar la identidad del usuario, que puede ser una de las opciones siguientes: CommunicationUserIdentifier , PhoneNumberIdentifier o CallingApplication . |
Autenticar el cliente
Para inicializar CallAgent
, necesita un token de acceso de usuario. Por lo general, este token se genera desde un servicio con autenticación específica de la aplicación. Para obtener más información sobre los tokens de acceso de usuario, consulte la guía Tokens de acceso de usuario.
En el inicio rápido, reemplace <AUTHENTICATION_TOKEN>
por un token de acceso de usuario generado para el recurso de Azure Communication Service.
Una vez que tenga un token, inicialice una instancia de CallAgent
con él, lo que nos permite realizar y recibir llamadas. Para acceder a las cámaras del dispositivo, también es necesario obtener una instancia de Administrador de dispositivos.
Agregue el siguiente código a la función InitCallAgentAndDeviceManagerAsync
.
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
}
}
Inicio de una llamada con vídeo
Agregue la implementación a CallButton_Click
para iniciar una llamada con vídeo. Es necesario enumerar las cámaras con la instancia del administrador de dispositivos y construir LocalOutgoingVideoStream
. Es necesario establecer VideoOptions
con LocalVideoStream
y pasarlo con startCallOptions
para establecer las opciones iniciales de la llamada. Al adjuntar LocalOutgoingVideoStream
a MediaElement
, podemos ver la vista previa del vídeo local.
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;
}
Agregue los métodos para iniciar o unirse a los diferentes tipos de llamada (llamada de Azure Communication Services individual, llamada telefónica individual, llamada de grupo de Azure Communication Services, unión a reuniones de Teams, etc.).
private async Task<CommunicationCall> StartAcsCallAsync(string acsCallee)
{
var options = await GetStartCallOptionsAsync();
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 GetStartCallOptionsAsync();
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> GetStartCallOptionsAsync()
{
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 } }
};
}
Agregue el código para crear LocalVideoStream en función de la cámara seleccionada en el método CameraList_SelectionChanged
.
var selectedCamera = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamera);
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);
}
Aceptar una llamada entrante
Agregue la implementación a OnIncomingCallAsync
para responder a una llamada entrante con vídeo y pase LocalVideoStream
a acceptCallOptions
.
var incomingCall = args.IncomingCall;
var acceptCallOptions = new AcceptCallOptions() {
IncomingVideoOptions = new IncomingVideoOptions()
{
IncomingVideoStreamKind = VideoStreamKind.RemoteIncoming
}
};
_ = await incomingCall.AcceptAsync(acceptCallOptions);
Secuencias de vídeo remotas y participantes remotos
Todos los participantes remotos están disponibles mediante la colección RemoteParticipants
de una instancia de la llamada. Cuando la llamada se conecta (CallState.Connected
), podemos acceder a los participantes remotos de la llamada y controlar las secuencias de vídeo remotas.
Nota:
Cuando un usuario se une a una llamada, puede acceder a los participantes remotos actuales a través de la colección RemoteParticipants
. El evento RemoteParticipantsUpdated
no se desencadenará para estos participantes existentes. Este evento solo se desencadenará cuando un participante remoto se una o salga de la llamada mientras el usuario ya está en la llamada.
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;
}
}
Representación de vídeos remotos
Adjunte a MediaElement
cada secuencia de vídeo remota.
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();
});
}
}
Actualización del estado de la llamada
Necesitamos limpiar los representadores de vídeo una vez desconectada la llamada y controlar el caso cuando los participantes remotos se unen inicialmente a la llamada.
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;
}
}
Finalizar una llamada
Finalice la llamada actual cuando se haga clic en el botón Hang Up
. Agregue la implementación a HangupButton_Click para finalizar una llamada con el callAgent que creamos y desmonte la actualización del participante y llame a los controladores de eventos de estado de llamada.
var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
try
{
await call.HangUpAsync(new HangUpOptions() { ForEveryone = true });
}
catch(Exception ex)
{
}
}
Ejecución del código
Puede compilar y ejecutar el código en Visual Studio. Para las plataformas de la solución, se admiten ARM64
, x64
y x86
.
Para hacer una llamada de vídeo saliente, proporcione un id. de usuario en el campo de texto y haga clic en el botón Start Call
.
Nota: Al llamar a 8:echo123
se detiene la secuencia de vídeo porque echo bot no admite el streaming de vídeo.
Para más información sobre los identificadores de usuario, consulte la guía Tokens de acceso de usuario.
Código de ejemplo de WinUI 3
Requisitos previos
Para completar este tutorial, debe cumplir los siguientes requisitos previos:
Una cuenta de Azure con una suscripción activa. Cree una cuenta gratuita.
Instale Visual Studio 2022 y SDK de Aplicaciones para Windows versión preliminar 2 de la versión 1.2.
Conocimientos básicos sobre cómo crear una aplicación WinUI 3. Crear el primer proyecto de WinUI 3 (SDK de Aplicaciones para Windows) es un buen recurso con el que empezar.
Un recurso de Communication Services implementado. Cree un recurso de Communication Services. Debe registrar la cadena de conexión para esta guía de inicio rápido.
Un token de acceso de usuario para su instancia de Azure Communication Services. También puede usar la CLI de Azure y ejecutar el comando siguiente con la cadena de conexión para crear un usuario y un token de acceso.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Para más información, consulte Uso de la CLI de Azure para crear y administrar tokens de acceso.
Instalación
Creación del proyecto
En Visual Studio, cree un nuevo proyecto con la plantilla Aplicación en blanco, empaquetada (WinUI 3 en escritorio) para configurar una aplicación WinUI 3 de una sola página.
Instalar el paquete
Haga clic con el botón derecho en su proyecto y vaya a Manage Nuget Packages
para instalar la versión 1.0.0 o superior de Azure.Communication.Calling.WindowsClient
. Asegúrese de que la casilla Incluir versión preliminar esté activada.
Solicitar acceso
Agregue el siguiente código a su app.manifest
:
<file name="RtmMvrMf.dll">
<activatableClass name="VideoN.VideoSchemeHandler" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>
Instalación del marco de la aplicación
Es necesario configurar un diseño básico para adjuntar la lógica. Para hacer una llamada saliente, se necesita un elemento TextBox
para proporcionar el id. de usuario del destinatario. También se necesita un botón Start Call
y un botón Hang Up
.
También es necesario obtener una vista previa del vídeo local y representar el vídeo remoto del otro participante. Por lo tanto, necesitamos dos elementos para mostrar las secuencias de vídeo.
Abra MainWindow.xaml
del proyecto y reemplace el contenido por la siguiente implementación.
<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>
Ábralo en App.xaml.cs
(haga clic con el botón derecho y elija Ver código) y agregue esta línea al principio:
using CallingQuickstart;
Abra MainWindow.xaml.cs
(haga clic con el botón derecho y elija Ver código) y reemplace el contenido por la siguiente implementación:
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();
});
}
}
}
Modelo de objetos
Las siguientes clases e interfaces controlan algunas de las características principales del SDK de llamadas de Azure Communication Services:
Nombre | Descripción |
---|---|
CallClient |
CallClient es el punto de entrada principal a la biblioteca cliente de llamadas. |
CallAgent |
CallAgent se usa para iniciar llamadas y unirse a estas. |
CommunicationCall |
CommunicationCall se usa para administrar las llamadas realizadas o a las que se ha unido. |
CallTokenCredential |
CallTokenCredential se usa como la credencial del token para crear una instancia de CallAgent . |
CommunicationUserIdentifier |
CommunicationUserIdentifier se usa para representar la identidad del usuario, que puede ser una de las opciones siguientes: CommunicationUserIdentifier , PhoneNumberIdentifier o CallingApplication . |
Autenticar el cliente
Para inicializar CallAgent
, necesita un token de acceso de usuario. Por lo general, este token se genera desde un servicio con autenticación específica de la aplicación. Para obtener más información sobre los tokens de acceso de usuario, consulte la guía Tokens de acceso de usuario.
En el inicio rápido, reemplace <AUTHENTICATION_TOKEN>
por un token de acceso de usuario generado para el recurso de Azure Communication Service.
Una vez que tenga un token, inicialice una instancia de CallAgent
con él, lo que nos permite realizar y recibir llamadas. Para acceder a las cámaras del dispositivo, también es necesario obtener una instancia de Administrador de dispositivos.
Agregue el siguiente código a la función InitCallAgentAndDeviceManagerAsync
.
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;
Inicio de una llamada con vídeo
Agregue la implementación a CallButton_Click
para iniciar una llamada con vídeo. Es necesario enumerar las cámaras con la instancia del administrador de dispositivos y construir LocalVideoStream
. Es necesario establecer VideoOptions
con LocalVideoStream
y pasarlo con startCallOptions
para establecer las opciones iniciales de la llamada. Al adjuntar LocalVideoStream
a MediaPlayerElement
, podemos ver la vista previa del vídeo local.
var startCallOptions = new StartCallOptions();
if (this.deviceManager.Cameras?.Count > 0)
{
var videoDeviceInfo = this.deviceManager.Cameras?.FirstOrDefault();
if (videoDeviceInfo != null)
{
var selectedCamera = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamera);
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;
Aceptar una llamada entrante
Agregue la implementación a Agent_OnIncomingCallAsync
para responder a una llamada entrante con vídeo y pase LocalVideoStream
a acceptCallOptions
.
var acceptCallOptions = new AcceptCallOptions();
if (this.deviceManager.Cameras?.Count > 0)
{
var videoDeviceInfo = this.deviceManager.Cameras?.FirstOrDefault();
if (videoDeviceInfo != null)
{
var selectedCamera = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamera);
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);
Secuencias de vídeo remotas y participantes remotos
Todos los participantes remotos están disponibles mediante la colección RemoteParticipants
de una instancia de la llamada. Una vez conectada la llamada, podemos acceder a los participantes remotos de la llamada y controlar las secuencias de vídeo remotas.
Nota:
Cuando un usuario se une a una llamada, puede acceder a los participantes remotos actuales a través de la colección RemoteParticipants
. El evento OnRemoteParticipantsUpdated
no se desencadenará para estos participantes existentes. Este evento solo se desencadenará cuando un participante remoto se una o salga de la llamada mientras el usuario ya está en la llamada.
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);
}
}
Representación de vídeos remotos
Adjunte a MediaPlayerElement
cada secuencia de vídeo remota.
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();
});
}
}
Actualización del estado de la llamada
Necesitamos limpiar los representadores de vídeo una vez desconectada la llamada y controlar el caso cuando los participantes remotos se unen inicialmente a la llamada.
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;
}
}
Finalizar una llamada
Finalice la llamada actual cuando se haga clic en el botón Hang Up
. Agregue la implementación a HangupButton_Click para finalizar una llamada con el callAgent que creamos y desmonte la actualización del participante y llame a los controladores de eventos de estado de llamada.
this.call.OnRemoteParticipantsUpdated -= Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged -= Call_OnStateChangedAsync;
await this.call.HangUpAsync(new HangUpOptions());
Ejecución del código
Puede compilar y ejecutar el código en Visual Studio. Para las plataformas de la solución, se admiten ARM64
, x64
y x86
.
Para hacer una llamada de vídeo saliente, proporcione un id. de usuario en el campo de texto y haga clic en el botón Start Call
.
Nota: Al llamar a 8:echo123
se detiene la secuencia de vídeo porque echo bot no admite el streaming de vídeo.
Para más información sobre los identificadores de usuario, consulte la guía Tokens de acceso de usuario.