Introdução ao exemplo de herói chamador
O Exemplo de Herói de Chamada de Grupo dos Serviços de Comunicação do Azure demonstra como o SDK da Web de Chamada dos Serviços de Comunicação pode ser usado para criar uma experiência de chamada em grupo.
Neste Guia de início rápido de exemplo, aprendemos como o exemplo funciona antes de executá-lo em sua máquina local e, em seguida, implantá-lo no Azure usando seus próprios recursos dos Serviços de Comunicação do Azure.
Transferir código
Encontre o projeto para este exemplo no GitHub. Uma versão do exemplo que inclui recursos atualmente em visualização pública, como Interoperabilidade do Teams e Gravação de Chamadas, pode ser encontrada em uma ramificação separada.
Descrição geral
O exemplo tem um aplicativo do lado do cliente e um aplicativo do lado do servidor. O aplicativo do lado do cliente é um aplicativo Web React/Redux que usa a estrutura de interface do usuário Fluent da Microsoft. Este aplicativo envia solicitações para um aplicativo do lado do servidor ASP.NET Core que ajuda o aplicativo do lado do cliente a se conectar ao Azure.
Veja como é o exemplo:
Quando você pressiona o botão "Iniciar uma chamada", o aplicativo Web busca um token de acesso de usuário do aplicativo do lado do servidor. Esse token é usado para conectar o aplicativo cliente aos Serviços de Comunicação do Azure. Depois que o token for recuperado, você será solicitado a especificar a câmera e o microfone que deseja usar. Pode desativar/ativar os seus dispositivos com controlos de alternância:
Depois de configurar seu nome de exibição e dispositivos, você pode ingressar na sessão de chamada. Você verá a tela de chamada principal onde mora a experiência principal de chamada.
Componentes da tela principal de chamada:
- Galeria de Mídia: O palco principal onde os participantes são mostrados. Se um participante tiver a câmara ativada, o feed de vídeo é apresentado aqui. Cada participante tem um bloco individual que mostra seu nome de exibição e fluxo de vídeo (quando houver)
- Cabeçalho: É aqui que os principais controles de chamada estão localizados para alternar as configurações e a barra lateral do participante, ativar e desativar o vídeo, compartilhar a tela e sair da chamada.
- Barra lateral: é onde as informações de participantes e configurações são mostradas quando alternados usando os controles no cabeçalho. O componente pode ser descartado usando o 'X' no canto superior direito. A barra lateral dos participantes mostra uma lista de participantes e um link para convidar mais usuários para o bate-papo. A barra lateral de configurações permite que você defina as configurações do microfone e da câmera.
Abaixo, você pode encontrar mais informações sobre pré-requisitos e etapas para configurar o exemplo.
Pré-requisitos
- Uma conta do Azure com uma subscrição ativa. Para obter detalhes, consulte Criar uma conta gratuitamente
- Node.js (12.18.4 e superior)
- Código do Visual Studio (compilação estável)
- Um recurso dos Serviços de Comunicação do Azure. Para obter detalhes, consulte Criar um recurso dos Serviços de Comunicação do Azure. Você precisa gravar sua cadeia de conexão de recurso para este início rápido.
Antes de executar a amostra pela primeira vez
Abra uma instância do PowerShell, Terminal do Windows, Prompt de Comando ou equivalente e navegue até o diretório para o qual você deseja clonar o exemplo.
git clone https://github.com/Azure-Samples/communication-services-web-calling-hero.git
Obtenha o
Connection String
no portal do Azure ou usando a CLI do Azure.az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
Para obter mais informações sobre cadeias de conexão, consulte Criar recursos de comunicação do Azure
Depois de obter o
Connection String
arquivo , adicione a cadeia de conexão ao arquivo samples/Server/appsetting.json . Insira sua cadeia de conexão na variável:ResourceConnectionString
.Obtenha o
Endpoint string
no portal do Azure ou usando a CLI do Azure.az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
Para obter mais informações sobre cadeias de caracteres de ponto de extremidade, consulte Criar recursos de comunicação do Azure
Depois de obter o
Endpoint String
arquivo , adicione a cadeia de caracteres do ponto de extremidade ao arquivo samples/Server/appsetting.json . Insira sua cadeia de caracteres de ponto de extremidade na variávelEndpointUrl
Execução local
Instalar dependências
npm run setup
Iniciar o aplicativo de chamada
npm run start
Isso abre um servidor cliente na porta 3000 que serve os arquivos do site e um servidor de api na porta 8080 que executa funcionalidades como cunhar tokens para participantes de chamadas.
Resolução de Problemas
O aplicativo mostra uma tela "Navegador não suportado", mas estou em um navegador compatível.
Se o seu aplicativo estiver sendo servido por um nome de host diferente de localhost, você deverá fornecer tráfego por https e não http.
Publicar no Azure
npm run setup
npm run build
npm run package
- Use a extensão do Azure e implante o diretório Calling/dist em seu serviço de aplicativo
Clean up resources (Limpar recursos)
Se quiser limpar e remover uma assinatura dos Serviços de Comunicação, você pode excluir o recurso ou grupo de recursos. A exclusão do grupo de recursos também exclui quaisquer outros recursos associados a ele. Saiba mais sobre a limpeza de recursos.
Próximos passos
Para obter mais informações, consulte os seguintes artigos:
- Familiarize-se com o uso do SDK de chamada
- Saiba mais sobre como as chamadas funcionam
Leitura adicional
- Exemplos - Encontre mais exemplos e exemplos na nossa página de visão geral de exemplos.
- Redux - Gerenciamento de estado do lado do cliente
- FluentUI - Biblioteca de interface do usuário com tecnologia Microsoft
- React - Biblioteca para a criação de interfaces de utilizador
- ASP.NET Core - Framework para a construção de aplicações web
O Exemplo de Herói de Chamada de Grupo dos Serviços de Comunicação do Azure para iOS demonstra como o SDK do iOS de Chamada de Serviços de Comunicação pode ser usado para criar uma experiência de chamada em grupo que inclui voz e vídeo. Neste exemplo de início rápido, você aprenderá como configurar e executar o exemplo. Uma visão geral do exemplo é fornecida para contextualização.
Transferir código
Encontre o projeto para este exemplo no GitHub.
Descrição geral
O exemplo é um aplicativo iOS nativo que usa os SDKs iOS dos Serviços de Comunicação do Azure para criar uma experiência de chamada que apresenta chamadas de voz e vídeo. O aplicativo usa um componente do lado do servidor para provisionar tokens de acesso que são usados para inicializar o SDK dos Serviços de Comunicação do Azure. Para configurar esse componente do lado do servidor, sinta-se à vontade para seguir o tutorial Serviço Confiável com Funções do Azure.
Veja como é o exemplo:
Quando você pressiona o botão "Iniciar nova chamada", o aplicativo iOS solicita que você insira seu nome de exibição para usar na chamada.
Depois de tocar em "Seguinte" no ecrã "Iniciar chamada", tem a oportunidade de partilhar o ID de grupo da chamada através da folha de partilha do iOS.
O aplicativo também permite que você ingresse em uma chamada existente dos Serviços de Comunicação do Azure especificando o ID da chamada existente ou o link de ID de equipe.
Depois de participar de uma chamada, você será solicitado a dar permissão ao aplicativo para acessar sua câmera e microfone, se ainda não estiver autorizado. Tenha em mente que, como todos os aplicativos baseados em AVFoundation, a verdadeira funcionalidade de áudio e vídeo só está disponível em hardware real.
Depois de configurar seu nome de exibição e participar da chamada, você verá a tela principal da chamada onde reside a experiência principal de chamada.
Componentes da tela principal de chamada:
- Galeria de Mídia: O palco principal onde os participantes são mostrados. Se um participante tiver a câmara ativada, o feed de vídeo é apresentado aqui. Cada participante tem um bloco individual que mostra seu nome de exibição e fluxo de vídeo (quando houver). A galeria suporta vários participantes e é atualizada quando os participantes são adicionados ou removidos para a chamada.
- Barra de Ação: é onde os principais controles de chamada estão localizados. Estes controlos permitem-lhe ligar/desligar o vídeo e o microfone, partilhar o ecrã e sair da chamada.
Abaixo, você encontrará mais informações sobre pré-requisitos e etapas para configurar o exemplo.
Pré-requisitos
- Uma conta do Azure com uma subscrição ativa. Para obter detalhes, consulte Criar uma conta gratuitamente.
- Um Mac com Xcode, juntamente com um certificado de programador válido instalado no seu Porta-chaves.
- Um recurso dos Serviços de Comunicação do Azure. Para obter detalhes, consulte Criar um recurso dos Serviços de Comunicação do Azure.
- Uma Função do Azure executando o Ponto de Extremidade de Autenticação para buscar tokens de acesso.
Executando a amostra localmente
O exemplo de chamada de grupo pode ser executado localmente usando XCode. Os desenvolvedores podem usar seu dispositivo físico ou um emulador para testar o aplicativo.
Antes de executar a amostra pela primeira vez
- Instale dependências executando
pod install
o . - Abra
AzureCalling.xcworkspace
no XCode. - Crie um arquivo de texto na raiz, chame
AppSettings.xcconfig
e defina o valor:communicationTokenFetchUrl = <your authentication endpoint, without the https:// component>
Executar amostra
Crie e execute o exemplo no XCode, usando o destino AzureCalling no simulador ou dispositivo de sua escolha.
(Opcional) Protegendo um ponto de extremidade de autenticação
Para fins de demonstração, este exemplo usa um ponto de extremidade acessível publicamente por padrão para buscar um token de acesso dos Serviços de Comunicação do Azure. Para cenários de produção, recomendamos usar seu próprio endpoint seguro para provisionar seus próprios tokens.
Com configuração adicional, este exemplo dá suporte à conexão a um ponto de extremidade protegido pelo Microsoft Entra ID (ID do Microsoft Entra) para que o logon do usuário seja necessário para que o aplicativo busque um token de acesso dos Serviços de Comunicação do Azure. Veja os passos abaixo:
- Habilite a autenticação do Microsoft Entra em seu aplicativo.
- Vá para a página de visão geral do aplicativo registrado em Registros de aplicativos do Microsoft Entra. Tome nota do
Application (client) ID
,Directory (tenant) ID
,Application ID URI
- Crie um
AppSettings.xcconfig
arquivo na raiz, se ainda não estiver presente, e adicione os valores:communicationTokenFetchUrl = <Application ID URI, without the https:// component> aadClientId = <Application (client) ID> aadTenantId = <Directory (tenant) ID>
Clean up resources (Limpar recursos)
Se quiser limpar e remover uma assinatura dos Serviços de Comunicação, você pode excluir o recurso ou grupo de recursos. A exclusão do grupo de recursos também exclui quaisquer outros recursos associados a ele. Saiba mais sobre a limpeza de recursos.
Próximos passos
Para obter mais informações, consulte os seguintes artigos:
- Familiarize-se com o uso do SDK de chamada
- Saiba mais sobre como as chamadas funcionam
Leitura adicional
- Azure Communication GitHub - Encontre mais exemplos e informações na página oficial do GitHub
- Exemplos - Encontre mais exemplos e exemplos na nossa página de visão geral de exemplos.
- Recursos de Chamada de Comunicação do Azure - Para saber mais sobre a chamada iOS sdk -Azure Communication iOS Calling SDK
O Exemplo de Herói de Chamada de Grupo dos Serviços de Comunicação do Azure para Android demonstra como o SDK de Chamada de Serviços de Comunicação para Android pode ser usado para criar uma experiência de chamada em grupo que inclua voz e vídeo. Neste exemplo de início rápido, você aprenderá como configurar e executar o exemplo. Uma visão geral do exemplo é fornecida para contextualização.
Transferir código
Encontre o projeto para este exemplo no GitHub.
Descrição geral
O exemplo é um aplicativo Android nativo que usa a biblioteca de cliente da interface do usuário do Android dos Serviços de Comunicação do Azure para criar uma experiência de chamada que apresenta chamadas de voz e vídeo. O aplicativo usa um componente do lado do servidor para provisionar tokens de acesso que são usados para inicializar o SDK dos Serviços de Comunicação do Azure. Para configurar esse componente do lado do servidor, sinta-se à vontade para seguir o tutorial Serviço Confiável com Funções do Azure.
Veja como é o exemplo:
Quando você pressiona o botão "Iniciar nova chamada", o aplicativo Android solicita que você insira seu nome de exibição para usar na chamada.
Depois de tocar em "Seguinte" na página "Iniciar uma chamada", tem a oportunidade de partilhar o "ID de Chamada de Grupo".
O aplicativo permite que você ingresse em uma chamada existente dos Serviços de Comunicação do Azure especificando a ID da chamada existente ou o link e o nome para exibição da ID da reunião das equipes.
Depois de participar de uma chamada, você será solicitado a dar permissão ao aplicativo para acessar sua câmera e microfone, se ainda não estiver autorizado. Você verá a tela de chamada principal onde vive a experiência principal de chamada.
Componentes da tela principal de chamada:
- Galeria de Mídia: O palco principal onde os participantes são mostrados. Se um participante tiver a câmara ativada, o feed de vídeo é apresentado aqui. Cada participante tem um bloco individual que mostra seu nome de exibição e fluxo de vídeo (quando houver). A galeria suporta vários participantes e é atualizada quando os participantes são adicionados ou removidos para a chamada.
- Barra de Ação: é onde os principais controles de chamada estão localizados. Estes controlos permitem-lhe ligar/desligar o vídeo e o microfone, partilhar o ecrã e sair da chamada.
Abaixo, você encontrará mais informações sobre pré-requisitos e etapas para configurar o exemplo.
Pré-requisitos
- Uma conta do Azure com uma subscrição ativa. Para obter detalhes, consulte Criar uma conta gratuitamente.
- Android Studio em execução no seu computador
- Um recurso dos Serviços de Comunicação do Azure. Para obter detalhes, consulte Criar um recurso dos Serviços de Comunicação do Azure.
- Uma Função do Azure executando o Ponto de Extremidade de Autenticação para buscar tokens de acesso.
Executando a amostra localmente
O exemplo de chamada em grupo pode ser executado localmente usando o Android Studio. Os desenvolvedores podem usar seu dispositivo físico ou um emulador para testar o aplicativo.
Antes de executar a amostra pela primeira vez
- Abra o Android Studio e selecione
Open an Existing Project
- Abra a pasta dentro da
AzureCalling
versão baixada para o exemplo. - Expanda o aplicativo/ativos para atualizar
appSettings.properties
o . Defina o valor da chavecommunicationTokenFetchUrl
para ser a URL do seu Ponto de Extremidade de Autenticação configurado como um pré-requisito.
Executar amostra
Crie e execute o exemplo no Android Studio.
(Opcional) Protegendo um ponto de extremidade de autenticação
Para fins de demonstração, este exemplo usa um ponto de extremidade acessível publicamente por padrão para buscar um token dos Serviços de Comunicação do Azure. Para cenários de produção, recomendamos usar seu próprio endpoint seguro para provisionar seus próprios tokens.
Com configuração adicional, este exemplo dá suporte à conexão a um ponto de extremidade protegido pelo Microsoft Entra ID (ID do Microsoft Entra) para que o logon do usuário seja necessário para que o aplicativo busque um token dos Serviços de Comunicação do Azure. Veja os passos abaixo:
Habilite a autenticação do Microsoft Entra em seu aplicativo.
Vá para a página de visão geral do aplicativo registrado em Registros de aplicativos do Microsoft Entra. Tome nota do
Package name
,Signature hash
,MSAL Configutaion
.
Edite
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
e definaisAADAuthEnabled
para ativar o Microsoft Entra ID.Edite
AndroidManifest.xml
e definaandroid:path
como o hash de assinatura do keystore. (Opcional. O valor atual usa hash do bundled debug.keystore. Se for usado um armazenamento de chaves diferente, isso deverá ser atualizado.)<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 a configuração do MSAL Android do portal do Azure e cole no
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
. Incluir "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
e defina o valor da chavecommunicationTokenFetchUrl
para ser a URL do seu ponto de extremidade de autenticação seguro.Editar
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
e definir o valor para a chaveaadScopes
a partir deAzure Active Directory
Expose an API
escoposDefina o valor para
graphURL
inAzureCalling/app/assets/appSettings.properties
como o ponto de extremidade da API do Graph para buscar informações do usuário.Edite
AzureCalling/app/src/main/assets/appSettings.properties
e defina o valor da chavetenant
para habilitar o login silencioso para que o usuário não precise ser autenticado repetidamente ao reiniciar o aplicativo.
Clean up resources (Limpar recursos)
Se quiser limpar e remover uma assinatura dos Serviços de Comunicação, você pode excluir o recurso ou grupo de recursos. A exclusão do grupo de recursos também exclui quaisquer outros recursos associados a ele. Saiba mais sobre a limpeza de recursos.
Próximos passos
Para obter mais informações, consulte os seguintes artigos:
- Familiarize-se com o uso do SDK de chamada
- Saiba mais sobre como as chamadas funcionam
Leitura adicional
- Azure Communication GitHub - Encontre mais exemplos e informações na página oficial do GitHub
- Exemplos - Encontre mais exemplos e exemplos na nossa página de visão geral de exemplos.
- Recursos de Chamada de Comunicação do Azure - Para saber mais sobre o SDK de chamada do Android -SDK de Chamada do Android de Comunicação do Azure
O Exemplo de Herói de Chamada de Grupo dos Serviços de Comunicação do Azure para Windows demonstra como o SDK do Windows de Chamada de Serviços de Comunicação pode ser usado para criar uma experiência de chamada em grupo que inclui voz e vídeo. Neste exemplo, você aprenderá a configurar e executar o exemplo. Uma visão geral do exemplo é fornecida para contextualização.
Neste guia de início rápido, você aprenderá a iniciar uma chamada de vídeo 1:1 usando o SDK de Chamada dos Serviços de Comunicação do Azure para Windows.
Código de exemplo UWP
Pré-requisitos
Para concluir este tutorial, precisa dos seguintes pré-requisitos:
Uma conta do Azure com uma subscrição ativa. Crie uma conta gratuitamente.
Instale o Visual Studio 2022 com a carga de trabalho de desenvolvimento da Plataforma Universal do Windows.
Um recurso de Serviços de Comunicação implantado. Crie um recurso de Serviços de Comunicação. Você precisa gravar sua cadeia de conexão para este início rápido.
Um Token de Acesso de Usuário para seu Serviço de Comunicação do Azure. Você também pode usar a CLI do Azure e executar o comando com sua cadeia de conexão para criar um usuário e um token de acesso.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Para obter detalhes, consulte Usar a CLI do Azure para criar e gerenciar tokens de acesso.
Configuração
Criação do projeto
No Visual Studio, crie um novo projeto com o modelo Aplicativo em Branco (Universal Windows) para configurar um aplicativo da Plataforma Universal do Windows (UWP) de página única.
Instalar o pacote
Clique com o botão direito do mouse em seu projeto e vá para Manage Nuget Packages
instalar Azure.Communication.Calling.WindowsClient
a versão 1.2.0-beta.1 ou superior. Certifique-se de que a opção Incluir pré-liberado está marcada.
Pedir acesso
Vá para Package.appxmanifest
e clique em Capabilities
.
Verifique Internet (Client & Server)
para obter acesso de entrada e saída à Internet.
Verifique Microphone
para acessar o feed de áudio do microfone.
Verifique WebCam
para acessar a câmera do dispositivo.
Adicione o seguinte código ao seu Package.appxmanifest
clicando com o botão direito do mouse e escolhendo View Code.
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
Configurar a estrutura do aplicativo
Precisamos configurar um layout básico para anexar nossa lógica. Para fazer uma chamada de saída, precisamos de um TextBox
para fornecer o ID de usuário do destinatário. Precisamos também de um Start Call
botão e de um Hang Up
botão.
Também precisamos visualizar o vídeo local e renderizar o vídeo remoto do outro participante. Portanto, precisamos de dois elementos para exibir os fluxos de vídeo.
Abra o MainPage.xaml
do seu projeto e substitua o conteúdo pela seguinte implementação.
<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>
Abra para App.xaml.cs
(clique com o botão direito do mouse e escolha View Code) e adicione esta linha ao topo:
using CallingQuickstart;
Abra o (clique com o botão direito do MainPage.xaml.cs
mouse e escolha View Code) e substitua o conteúdo pela seguinte implementação:
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 objeto
As seguintes classes e interfaces lidam com alguns dos principais recursos do SDK de Chamada dos Serviços de Comunicação do Azure:
Nome | Descrição |
---|---|
CallClient |
O CallClient é o principal ponto de entrada para a biblioteca de cliente de chamada. |
CallAgent |
O CallAgent é usado para iniciar e participar de chamadas. |
CommunicationCall |
O CommunicationCall é usado para gerenciar chamadas feitas ou associadas. |
CallTokenCredential |
O CallTokenCredential é usado como a credencial de token para instanciar o CallAgent . |
CommunicationUserIdentifier |
O CommunicationUserIdentifier é usado para representar a identidade do usuário, que pode ser uma das seguintes opções: CommunicationUserIdentifier , PhoneNumberIdentifier ou CallingApplication . |
Autenticar o cliente
Para inicializar um CallAgent
, você precisa de um Token de Acesso de Usuário. Geralmente esse token é gerado a partir de um serviço com autenticação específica para o aplicativo. Para obter mais informações sobre tokens de acesso de usuário, consulte o guia Tokens de acesso de usuário.
Para o início rápido, substitua <AUTHENTICATION_TOKEN>
por um token de acesso de usuário gerado para seu recurso do Serviço de Comunicação do Azure.
Depois de ter um token, inicialize uma CallAgent
instância com ele, o que nos permite fazer e receber chamadas. Para acessar as câmeras no dispositivo, também precisamos obter a instância do Gerenciador de Dispositivos.
Adicione o seguinte código à InitCallAgentAndDeviceManagerAsync
função.
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
}
}
Iniciar uma chamada com vídeo
Adicione a implementação ao CallButton_Click
para iniciar uma chamada com vídeo. Precisamos enumerar as câmeras com a instância do gerenciador de dispositivos e construir LocalOutgoingVideoStream
. Precisamos definir o VideoOptions
com LocalVideoStream
e passá-lo com startCallOptions
para definir as opções iniciais para a chamada. Ao anexar LocalOutgoingVideoStream
a um MediaElement
, podemos ver a visualização do 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;
}
Adicione os métodos para iniciar ou ingressar nos diferentes tipos de chamada (chamada 1:1 dos Serviços de Comunicação do Azure, chamada telefônica 1:1, chamada do Grupo dos Serviços de Comunicação do Azure, participação na reunião do Teams, etc.).
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 } }
};
}
Adicione o código para criar o LocalVideoStream dependendo da câmera selecionada no CameraList_SelectionChanged
método.
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);
}
Aceitar uma chamada recebida
Adicione a implementação ao OnIncomingCallAsync
para atender uma chamada recebida com vídeo, passe o LocalVideoStream
para acceptCallOptions
.
var incomingCall = args.IncomingCall;
var acceptCallOptions = new AcceptCallOptions() {
IncomingVideoOptions = new IncomingVideoOptions()
{
IncomingVideoStreamKind = VideoStreamKind.RemoteIncoming
}
};
_ = await incomingCall.AcceptAsync(acceptCallOptions);
Participantes remotos e fluxos de vídeo remotos
Todos os participantes remotos estão disponíveis através da RemoteParticipants
coleta em uma instância de chamada. Uma vez que a chamada se conecta (CallState.Connected
), podemos acessar os participantes remotos da chamada e lidar com os fluxos de vídeo remotos.
Nota
Quando um usuário ingressa em uma chamada, ele pode acessar os participantes remotos atuais por meio da RemoteParticipants
coleção. O RemoteParticipantsUpdated
evento não será acionado para esses participantes existentes. Esse evento só será acionado quando um participante remoto entrar ou sair da chamada enquanto o usuário já estiver na chamada.
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;
}
}
Renderizar vídeos remotos
Para cada fluxo de vídeo remoto, anexe-o MediaElement
ao .
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();
});
}
}
Atualização do estado da chamada
Precisamos limpar os renderizadores de vídeo assim que a chamada for desconectada e lidar com o caso quando os participantes remotos entrarem inicialmente na chamada.
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;
}
}
Terminar uma chamada
Termine a chamada atual quando o Hang Up
botão for clicado. Adicione a implementação ao HangupButton_Click para encerrar uma chamada com o callAgent que criamos e destrua os manipuladores de eventos de atualização e estado de chamada do participante.
var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
try
{
await call.HangUpAsync(new HangUpOptions() { ForEveryone = true });
}
catch(Exception ex)
{
}
}
Executar o código
Você pode criar e executar o código no Visual Studio. Para plataformas de solução, suportamos ARM64
e x86
x64
.
Você pode fazer uma chamada de vídeo de saída fornecendo um ID de usuário no campo de texto e clicando no Start Call
botão.
Nota: A chamada 8:echo123
interrompe o fluxo de vídeo porque o echo bot não suporta streaming de vídeo.
Para obter mais informações sobre IDs de usuário (identidade), consulte o guia de Tokens de Acesso de Usuário.
Código de exemplo do WinUI 3
Pré-requisitos
Para concluir este tutorial, precisa dos seguintes pré-requisitos:
Uma conta do Azure com uma subscrição ativa. Crie uma conta gratuitamente.
Instale o Visual Studio 2022 e o Windows App SDK versão 1.2 preview 2.
Compreensão básica de como criar um aplicativo WinUI 3. Criar seu primeiro projeto WinUI 3 (Windows App SDK) é um bom recurso para começar.
Um recurso de Serviços de Comunicação implantado. Crie um recurso de Serviços de Comunicação. Você precisa gravar sua cadeia de conexão para este início rápido.
Um Token de Acesso de Usuário para seu Serviço de Comunicação do Azure. Você também pode usar a CLI do Azure e executar o comando com sua cadeia de conexão para criar um usuário e um token de acesso.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Para obter detalhes, consulte Usar a CLI do Azure para criar e gerenciar tokens de acesso.
Configuração
Criação do projeto
No Visual Studio, crie um novo projeto com o modelo Aplicativo em branco, empacotado (WinUI 3 na área de trabalho) para configurar um aplicativo WinUI 3 de página única.
Instalar o pacote
Clique com o botão direito do mouse em seu projeto e vá para instalar Azure.Communication.Calling.WindowsClient
a Manage Nuget Packages
versão 1.0.0 ou superior. Certifique-se de que a opção Incluir pré-liberado está marcada.
Pedir acesso
Adicione o seguinte código ao seu app.manifest
:
<file name="RtmMvrMf.dll">
<activatableClass name="VideoN.VideoSchemeHandler" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>
Configurar a estrutura do aplicativo
Precisamos configurar um layout básico para anexar nossa lógica. Para fazer uma chamada de saída, precisamos de um TextBox
para fornecer o ID de usuário do destinatário. Precisamos também de um Start Call
botão e de um Hang Up
botão.
Também precisamos visualizar o vídeo local e renderizar o vídeo remoto do outro participante. Portanto, precisamos de dois elementos para exibir os fluxos de vídeo.
Abra o MainWindow.xaml
do seu projeto e substitua o conteúdo pela seguinte implementação.
<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>
Abra para App.xaml.cs
(clique com o botão direito do mouse e escolha View Code) e adicione esta linha ao topo:
using CallingQuickstart;
Abra o (clique com o botão direito do MainWindow.xaml.cs
mouse e escolha View Code) e substitua o conteúdo pela seguinte implementação:
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 objeto
As seguintes classes e interfaces lidam com alguns dos principais recursos do SDK de Chamada dos Serviços de Comunicação do Azure:
Nome | Descrição |
---|---|
CallClient |
O CallClient é o principal ponto de entrada para a biblioteca de cliente de chamada. |
CallAgent |
O CallAgent é usado para iniciar e participar de chamadas. |
CommunicationCall |
O CommunicationCall é usado para gerenciar chamadas feitas ou associadas. |
CallTokenCredential |
O CallTokenCredential é usado como a credencial de token para instanciar o CallAgent . |
CommunicationUserIdentifier |
O CommunicationUserIdentifier é usado para representar a identidade do usuário, que pode ser uma das seguintes opções: CommunicationUserIdentifier , PhoneNumberIdentifier ou CallingApplication . |
Autenticar o cliente
Para inicializar um CallAgent
, você precisa de um Token de Acesso de Usuário. Geralmente esse token é gerado a partir de um serviço com autenticação específica para o aplicativo. Para obter mais informações sobre tokens de acesso de usuário, consulte o guia Tokens de acesso de usuário.
Para o início rápido, substitua <AUTHENTICATION_TOKEN>
por um token de acesso de usuário gerado para seu recurso do Serviço de Comunicação do Azure.
Depois de ter um token, inicialize uma CallAgent
instância com ele, o que nos permite fazer e receber chamadas. Para acessar as câmeras no dispositivo, também precisamos obter a instância do Gerenciador de Dispositivos.
Adicione o seguinte código à InitCallAgentAndDeviceManagerAsync
função.
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;
Iniciar uma chamada com vídeo
Adicione a implementação ao CallButton_Click
para iniciar uma chamada com vídeo. Precisamos enumerar as câmeras com a instância do gerenciador de dispositivos e construir LocalVideoStream
. Precisamos definir o VideoOptions
com LocalVideoStream
e passá-lo com startCallOptions
para definir as opções iniciais para a chamada. Ao anexar LocalVideoStream
a um MediaPlayerElement
, podemos ver a visualização do vídeo local.
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;
Aceitar uma chamada recebida
Adicione a implementação ao Agent_OnIncomingCallAsync
para atender uma chamada recebida com vídeo, passe o LocalVideoStream
para 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);
Participantes remotos e fluxos de vídeo remotos
Todos os participantes remotos estão disponíveis através da RemoteParticipants
coleta em uma instância de chamada. Uma vez que a chamada está conectada, podemos acessar os participantes remotos da chamada e lidar com os fluxos de vídeo remotos.
Nota
Quando um usuário ingressa em uma chamada, ele pode acessar os participantes remotos atuais por meio da RemoteParticipants
coleção. O OnRemoteParticipantsUpdated
evento não será acionado para esses participantes existentes. Esse evento só será acionado quando um participante remoto entrar ou sair da chamada enquanto o usuário já estiver na chamada.
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);
}
}
Renderizar vídeos remotos
Para cada fluxo de vídeo remoto, anexe-o MediaPlayerElement
ao .
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();
});
}
}
Atualização do estado da chamada
Precisamos limpar os renderizadores de vídeo assim que a chamada for desconectada e lidar com o caso quando os participantes remotos entrarem inicialmente na chamada.
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;
}
}
Terminar uma chamada
Termine a chamada atual quando o Hang Up
botão for clicado. Adicione a implementação ao HangupButton_Click para encerrar uma chamada com o callAgent que criamos e destrua os manipuladores de eventos de atualização e estado de chamada do participante.
this.call.OnRemoteParticipantsUpdated -= Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged -= Call_OnStateChangedAsync;
await this.call.HangUpAsync(new HangUpOptions());
Executar o código
Você pode criar e executar o código no Visual Studio. Para plataformas de solução, suportamos ARM64
e x86
x64
.
Você pode fazer uma chamada de vídeo de saída fornecendo um ID de usuário no campo de texto e clicando no Start Call
botão.
Nota: A chamada 8:echo123
interrompe o fluxo de vídeo porque o echo bot não suporta streaming de vídeo.
Para obter mais informações sobre IDs de usuário (identidade), consulte o guia de Tokens de Acesso de Usuário.