Começar com o exemplo de destaque de chamada
O Exemplo de Destaque de Chamadas em Grupo dos Serviços de Comunicação do Azure demonstra como o SDK da Web de Chamadas dos Serviços de Comunicação pode ser usado para criar uma experiência de chamada em grupo.
Neste início rápido de exemplo, aprendemos como o exemplo funciona antes de o executarmos em seu computador local e, em seguida, implantamos o exemplo no Azure usando seus próprios recursos de Serviços de Comunicação do Azure.
Código de download
Localize o projeto para este exemplo no GitHub. No momento, uma versão do exemplo que inclui recursos, como a Interoperabilidade do Teams e a Gravação de Chamada está em visualização pública e pode ser localizada em um branch separado.
Visã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. Esse aplicativo envia solicitações a um aplicativo do lado do servidor ASP.NET Core que ajuda o aplicativo do lado do cliente a se conectar ao Azure.
Aqui está um exemplo:
Quando você pressiona o botão "Iniciar uma chamada", o aplicativo Web busca um token de acesso do 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 é recuperado, você é solicitado a especificar a câmera e o microfone que deseja usar. Você pode desabilitar/habilitar seus dispositivos com controles de alternância:
Depois de configurar o nome de exibição e os dispositivos, você pode ingressar na sessão de chamada. Você verá a tela principal de chamada na qual está a experiência de chamada principal.
Componentes da tela principal de chamada:
- Galeria de Mídia: a fase principal em que os participantes são mostrados. Se um participante tiver a câmera habilitada, o feed de vídeo dele será mostrado aqui. Cada participante tem um bloco individual que mostra seu nome de exibição e fluxo de vídeo (quando há um)
- Cabeçalho: É aí que os controles de chamada primários estão localizados para alternar as configurações e a barra lateral do participante, ativar/desativar vídeo e combinação, compartilhar a tela e sair da chamada.
- Barra lateral: é nela que as informações de participantes e configurações são mostradas quando alternadas 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 chat. A barra lateral de configurações permite que você defina as configurações de microfone e câmera.
Confira abaixo mais informações sobre os pré-requisitos e as etapas para configurar o exemplo.
Pré-requisitos
- Uma conta do Azure com uma assinatura ativa. Para obter detalhes, confira Criar uma conta gratuitamente
- Node.js (12.18.4 e superiores)
- Visual Studio Code (compilação estável)
- Um recurso dos Serviços de Comunicação do Azure. Para obter detalhes, confira Criar um recurso dos Serviços de Comunicação do Azure. É necessário registrar a cadeia de conexão do recurso desse início rápido.
Antes de executar o exemplo 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
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, confira Criar Recursos de Comunicação do Azure
Depois de obter o
Connection String
, adicione a cadeia de conexão ao arquivo samples/Server/appsetting.json. Insira a cadeia de conexão na variável:ResourceConnectionString
.Obtenha
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 pontos de extremidade, confira Criar Recursos de Comunicação do Azure
Depois de obter o
Endpoint String
, adicione a cadeia do ponto de extremidade ao arquivo samples/Server/appsetting.json. Insira a cadeia de conexão na variável:EndpointUrl
Execução local
Instalar dependências
npm run setup
Inicie o aplicativo da chamada
npm run start
Isso abre um servidor cliente na porta 3000 que atende aos arquivos do site e um servidor de API na porta 8080 que executa funcionalidades como tokens de mineração para participantes da chamada.
Solução de problemas
O aplicativo mostra uma tela "Navegador sem suporte", mas estou em um navegador com suporte.
Se o aplicativo estiver sendo servido em um nome de host diferente do localhost, você deverá atender ao tráfego por https e não por http.
Publicar no Azure
npm run setup
npm run build
npm run package
- Use a extensão do Azure e implante o diretório De chamada/dist em seu serviço de aplicativo
Limpar os recursos
Se quiser limpar e remover uma assinatura dos Serviços de Comunicação, exclua o recurso ou o grupo de recursos. Excluir o grupo de recursos também exclui todos os recursos associados a ele. Saiba mais sobre como limpar recursos.
Próximas etapas
Para obter mais informações, consulte os seguintes artigos:
- Familiarize-se com o uso do SDK de Chamada
- Saiba mais sobre como a chamada funciona
Leituras adicionais
- Amostras – encontre mais amostras e exemplos em nossa página de visão geral de amostras.
- Redux – gerenciamento de estado do lado do cliente
- FluentUI – biblioteca de interface do usuário da Microsoft
- React – biblioteca para criar interfaces do usuário
- ASP.NET Core – Estrutura para criar aplicativos Web
O Exemplo de Destaque de Chamadas em Grupo para iOS dos Serviços de Comunicação do Azure demonstra como o SDK de Chamada para iOS dos Serviços de Comunicação pode ser usado para criar uma experiência de chamada em grupo que inclua voz e vídeo. Neste exemplo de guia de início rápido, você aprenderá a configurar e executar o exemplo. Uma visão geral do exemplo é fornecida para o contexto.
Código de download
Localize o projeto para este exemplo no GitHub.
Visão geral
O exemplo é um aplicativo iOS nativo que usa os SDKs para iOS dos Serviços de Comunicação do Azure para criar uma experiência de chamada com 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 o Azure Functions.
Aqui está um exemplo:
Quando você pressiona o botão "Iniciar chamada", o aplicativo iOS solicita que você insira seu nome de exibição para uso na chamada.
Depois de tocar em "Avançar" na tela "Iniciar chamada", você tem a oportunidade de compartilhar a ID do grupo da chamada por meio da planilha de compartilhamento do iOS.
O aplicativo também 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 da ID do Teams.
Depois de ingressar em uma chamada, você precisará fornecer permissão ao aplicativo para acessar sua câmera e seu microfone, se ainda não tiver feito isso. Tenha em mente que, assim como em todos os aplicativos baseados em AVFoundation, a verdadeira funcionalidade de áudio e vídeo só está disponível no hardware real.
Depois de configurar seu nome de exibição e ingressar na chamada, você verá a tela de chamada principal que hospeda a experiência de chamada principal.
Componentes da tela principal de chamada:
- Galeria de Mídia: a fase principal em que os participantes são mostrados. Se um participante tiver a câmera habilitada, o feed de vídeo dele será mostrado aqui. Cada participante tem um bloco individual que mostra o nome de exibição e o fluxo de vídeo (quando houver). A galeria dá suporte a vários participantes e é atualizada quando os participantes são adicionados à chamada ou removidos dela.
- Barra de Ação: é nela que os controles de chamada primários estão localizados. Esses controles permitem ativar/desativar o vídeo e o microfone, compartilhar a tela e sair da chamada.
Abaixo, você encontrará mais informações sobre os pré-requisitos e as etapas para configurar o exemplo.
Pré-requisitos
- Uma conta do Azure com uma assinatura ativa. Para obter detalhes, confira Criar uma conta gratuitamente.
- Um Mac executando Xcode, juntamente com um certificado de desenvolvedor válido instalado em seu conjunto de chaves.
- Um recurso dos Serviços de Comunicação do Azure. Para obter detalhes, confira Criar um recurso dos Serviços de Comunicação do Azure.
- Uma função do Azure que executa o ponto de extremidade de autenticação para buscar tokens de acesso.
Como executar o exemplo localmente
O exemplo de chamada em grupo pode ser executado localmente com o Xcode. Os desenvolvedores podem usar o dispositivo físico ou um emulador para testar o aplicativo.
Antes de executar o exemplo pela primeira vez
- Instale as dependências executando
pod install
. - Abra
AzureCalling.xcworkspace
no Xcode. - Crie um arquivo de texto na raiz, chamado
AppSettings.xcconfig
, e defina o valor:communicationTokenFetchUrl = <your authentication endpoint, without the https:// component>
Executar o exemplo
Compile e execute o exemplo no XCode, usando o destino AzureCalling no simulador ou dispositivo de sua escolha.
(Opcional) Como proteger um ponto de extremidade de autenticação
Para fins de demonstração, esse exemplo usa um ponto de extremidade publicamente acessível 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 um ponto de extremidade próprio protegido para provisionar seus tokens.
Com uma configuração adicional, este exemplo dá suporte à conexão com um ponto de extremidade protegido da ID do Microsoft Entra (Microsoft Entra ID) 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. Confira as etapas 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. Anote a
Application (client) ID
, aDirectory (tenant) ID
e oApplication ID URI
- Crie um arquivo
AppSettings.xcconfig
na raiz, se ele 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>
Limpar os recursos
Se quiser limpar e remover uma assinatura dos Serviços de Comunicação, exclua o recurso ou o grupo de recursos. Excluir o grupo de recursos também exclui todos os recursos associados a ele. Saiba mais sobre como limpar recursos.
Próximas etapas
Para obter mais informações, consulte os seguintes artigos:
- Familiarize-se com o uso do SDK de Chamada
- Saiba mais sobre como a chamada funciona
Leituras adicionais
- GitHub de Comunicação do Azure – Encontre mais exemplos e informações na página oficial do GitHub
- Amostras – encontre mais amostras e exemplos em nossa página de visão geral de amostras.
- Recursos de Chamada de Comunicação do Azure: para saber mais sobre o SDK de Chamada para iOS, confira SDK de Chamada para iOS de Comunicação do Azure
O Exemplo de Destaque de Chamadas em Grupo para Android dos Serviços de Comunicação do Azure demonstra como o SDK de Chamada do Android dos Serviços de Comunicação pode ser usado para criar uma experiência de chamada em grupo que inclua voz e vídeo. Neste exemplo de guia de início rápido, você aprenderá a configurar e executar o exemplo. Uma visão geral do exemplo é fornecida para o contexto.
Código de download
Localize o projeto para este exemplo no GitHub.
Visão geral
O exemplo é um aplicativo Android nativo que usa a biblioteca de clientes da IU do Android dos Serviços de Comunicação do Azure para criar uma experiência de chamada com 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 o Azure Functions.
Aqui está um exemplo:
Quando você pressiona o botão "Iniciar chamada", o aplicativo Android solicita que você insira seu nome de exibição para uso na chamada.
Depois de tocar em "Avançar" na página "Iniciar chamada", você tem a oportunidade de compartilhar a "ID da chamada de grupo".
O aplicativo permite que você ingresse em uma chamada existente dos Serviços de Comunicação do Azure especificando a ID dessa chamada ou o link da ID da reunião do Teams e o nome de exibição.
Depois de ingressar em uma chamada, você precisará fornecer permissão ao aplicativo para acessar sua câmera e seu microfone, se ainda não tiver feito isso. Você verá a tela principal de chamada na qual está a experiência de chamada principal.
Componentes da tela principal de chamada:
- Galeria de Mídia: a fase principal em que os participantes são mostrados. Se um participante tiver a câmera habilitada, o feed de vídeo dele será mostrado aqui. Cada participante tem um bloco individual que mostra o nome de exibição e o fluxo de vídeo (quando houver). A galeria dá suporte a vários participantes e é atualizada quando os participantes são adicionados à chamada ou removidos dela.
- Barra de Ação: é nela que os controles de chamada primários estão localizados. Esses controles permitem ativar/desativar o vídeo e o microfone, compartilhar a tela e sair da chamada.
Abaixo, você encontrará mais informações sobre os pré-requisitos e as etapas para configurar o exemplo.
Pré-requisitos
- Uma conta do Azure com uma assinatura ativa. Para obter detalhes, confira Criar uma conta gratuitamente.
- Android Studio em execução no computador
- Um recurso dos Serviços de Comunicação do Azure. Para obter detalhes, confira Criar um recurso dos Serviços de Comunicação do Azure.
- Uma função do Azure que executa o ponto de extremidade de autenticação para buscar tokens de acesso.
Como executar o exemplo localmente
O exemplo de chamada em grupo pode ser executado localmente com o Android Studio. Os desenvolvedores podem usar o dispositivo físico ou um emulador para testar o aplicativo.
Antes de executar o exemplo pela primeira vez
- Abra o Android Studio e selecione
Open an Existing Project
- Abra a pasta
AzureCalling
dentro da versão baixada do exemplo. - Expanda app/assets para atualizar
appSettings.properties
. Defina o valor da chavecommunicationTokenFetchUrl
como a URL para o ponto de extremidade de autenticação com um pré-requisito.
Executar o exemplo
Compile e execute o exemplo no Android Studio.
(Opcional) Como proteger um ponto de extremidade de autenticação
Para fins de demonstração, esse exemplo usa um ponto de extremidade publicamente acessível por padrão para buscar um token dos Serviços de Comunicação do Azure. Para cenários de produção, recomendamos usar um ponto de extremidade próprio protegido para provisionar seus tokens.
Com uma configuração adicional, este exemplo dá suporte à conexão a um ponto de extremidade protegido da ID do Microsoft Entra (Microsoft Entra ID) 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. Confira as etapas 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. Anote o
Package name
,Signature hash
,MSAL Configutaion
.
Edite
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
e definaisAADAuthEnabled
para habilitar o Microsoft Entra ID.Edite
AndroidManifest.xml
e definaandroid:path
como o hash de assinatura do repositório de chaves. (Opcional. O valor atual usa hash do pacote debug.keystore. Se for usado um repositório de chaves diferente, ele 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 da MSAL Android do portal do Azure e cole-a em
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
. Inclua "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
como a URL para o ponto de extremidade de autenticação seguro.Edite
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
e defina o valor da chaveaadScopes
dos escoposAzure Active Directory
Expose an API
Defina o valor de
graphURL
emAzureCalling/app/assets/appSettings.properties
como o ponto de extremidade da API do Graph para buscar as informações do usuário.Edite
AzureCalling/app/src/main/assets/appSettings.properties
e defina o valor da chavetenant
a fim de habilitar o logon silencioso para que o usuário não precise ser autenticado várias vezes durante a reinicialização do aplicativo.
Limpar os recursos
Se quiser limpar e remover uma assinatura dos Serviços de Comunicação, exclua o recurso ou o grupo de recursos. Excluir o grupo de recursos também exclui todos os recursos associados a ele. Saiba mais sobre como limpar recursos.
Próximas etapas
Para obter mais informações, consulte os seguintes artigos:
- Familiarize-se com o uso do SDK de Chamada
- Saiba mais sobre como a chamada funciona
Leituras adicionais
- GitHub de Comunicação do Azure – Encontre mais exemplos e informações na página oficial do GitHub
- Amostras – encontre mais amostras e exemplos em nossa página de visão geral de amostras.
- Recursos de Chamada de Comunicação do Azure: para saber mais sobre o SDK de Chamada para Android, confira SDK de Chamada para Android de Comunicação do Azure
O Exemplo de Destaque de Chamadas em Grupo para Windows dos Serviços de Comunicação do Azure demonstra como o SDK de Chamada para Windows dos Serviços de Comunicação pode ser usado para criar uma experiência de chamada em grupo que inclua voz e vídeo. Neste exemplo, você aprende a configurar e executar o exemplo. Uma visão geral do exemplo é fornecida para o contexto.
Neste guia de início rápido, você aprenderá a iniciar uma chamada de vídeo individual 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, você precisará dos seguintes pré-requisitos:
Uma conta do Azure com uma assinatura ativa. Crie uma conta gratuitamente.
Instale o Visual Studio 2022 com a carga de trabalho de desenvolvimento da Plataforma Universal do Windows.
Um recurso dos Serviços de Comunicação implantado. Crie um recurso dos Serviços de Comunicação. Você precisa gravar sua cadeia de conexão nesse início rápido.
Um Token de Acesso do Usuário para o 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, confira Usar a CLI do Azure para criar e gerenciar tokens de acesso.
Configurando
Criação do projeto
No Visual Studio, crie um novo projeto com o modelo Aplicativo em branco (Universal do Windows) para configurar um aplicativo UWP (Plataforma Universal do Windows de página única).
Instalar o pacote
Clique com o botão direito do mouse em seu projeto e acesse Manage Nuget Packages
para instalar Azure.Communication.Calling.WindowsClient
1.2.0-beta.1 ou versão superior. Certifique-se de que Incluir Pré-lançamento esteja marcado.
Solicitar acesso
Vá até Package.appxmanifest
e clique em Capabilities
.
Verifique Internet (Client & Server)
para obter acesso de entrada e saída à internet.
Marque Microphone
para acessar o feed de áudio do microfone.
Marque WebCam
para acessar a câmera do dispositivo.
Adicione o código a seguir ao seu Package.appxmanifest
clicando com o botão direito do mouse e escolhendo Exibir código.
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
Configurar o framework de aplicativos
Precisamos configurar um layout básico para anexar nossa lógica. Para fazer uma chamada de saída, precisamos de um TextBox
para fornecer a ID de usuário do receptor. Também precisamos de um botão Start Call
e de um botão Hang Up
.
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 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 o App.xaml.cs
(clique com o botão direito do mouse e escolha Exibir código) e adicione essa linha à parte superior:
using CallingQuickstart;
Abra o MainPage.xaml.cs
(clique com o botão direito do mouse e escolha Exibir código) 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 cuidam de alguns dos principais recursos do SDK de Chamada da Interface do Usuário dos Serviços de Comunicação do Azure:
Nome | Descrição |
---|---|
CallClient |
O CallClient é o ponto de entrada principal para a biblioteca de clientes de Chamada. |
CallAgent |
O CallAgent é usado para iniciar e ingressar em chamadas. |
CommunicationCall |
O CommunicationCall é usado para gerenciar chamadas iniciadas ou ingressadas. |
CallTokenCredential |
O CallTokenCredential é usado como a credencial de token de segurança para criar uma instância 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ê precisará de um Token de Acesso de Usuário. Geralmente, esse token é gerado de um serviço com autenticação específica para o aplicativo. Para saber mais sobre tokens de acesso do usuário, confira o guia Tokens de acesso do usuário.
Para o guia de início rápido, substitua <AUTHENTICATION_TOKEN>
por um token de acesso de usuário gerado para o recurso do Serviço de Comunicação do Azure.
Assim que tiver um token, inicialize uma instância CallAgent
com ele, o que nos permitirá fazer e receber chamadas. Para acessar as câmeras do dispositivo, também precisamos obter a instância do Gerenciador de Dispositivos.
Adicione o seguinte código à função 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
}
}
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 e o constructo do gerenciador de dispositivos LocalOutgoingVideoStream
. Precisamos definir o VideoOptions
com LocalVideoStream
e passá-lo com startCallOptions
para definir as opções iniciais da chamada. Ao anexar LocalOutgoingVideoStream
a um MediaElement
, podemos visualizar o 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 (Serviços de Comunicação do Azure 1:1, chamada telefônica 1:1, chamada de grupo de Serviços de Comunicação do Azure, ingresso 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 método CameraList_SelectionChanged
.
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 de entrada
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);
Participante remoto e fluxos de vídeo remotos
Todos os participantes remotos estão disponíveis por meio da coleção RemoteParticipants
em uma instância de chamada. Depois que a chamada estiver conectada (CallState.Connected
), poderemos acessar os participantes remotos da chamada e lidar com os fluxos de vídeo remotos.
Observação
Quando um usuário entra em uma chamada, ele pode acessar os participantes remotos atuais por meio da coleção RemoteParticipants
. O evento RemoteParticipantsUpdated
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 ao MediaElement
.
private async Task AddVideoStreamsAsync(IReadOnlyList<RemoteVideoStream> remoteVideoStreams)
{
foreach (var remoteVideoStream in remoteVideoStreams)
{
var remoteUri = await remoteVideoStream.Start();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
RemoteVideo.Source = remoteUri;
RemoteVideo.Play();
});
}
}
Atualização do estado de chamada
Precisamos limpar os renderizadores de vídeo depois que a chamada for desconectada e tratar o caso quando os participantes remotos ingressarem 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;
}
}
Encerrar uma chamada
Finalize a chamada atual quando o botão Hang Up
for clicado. Adicione a implementação ao HangupButton_Click para encerrar uma chamada com o callAgent que criamos e destrua a atualização do participante e os manipuladores de eventos de estado de chamada.
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, oferecemos suporte a ARM64
, x64
e x86
.
Você pode fazer uma chamada de vídeo de saída fornecendo uma ID de usuário no campo de texto e clicando no botão Start Call
.
Observação: chamar 8:echo123
interromperá o fluxo de vídeo porque o bot de eco não dá suporte ao streaming de vídeo.
Para obter mais informações sobre IDs (identidade) de usuário, verifique o guia Tokens de acesso do usuário.
Código de exemplo do WinUI 3
Pré-requisitos
Para concluir este tutorial, você precisará dos seguintes pré-requisitos:
Uma conta do Azure com uma assinatura 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 (SDK do Aplicativo Windows) é um bom recurso para começar.
Um recurso dos Serviços de Comunicação implantado. Crie um recurso dos Serviços de Comunicação. Você precisa gravar sua cadeia de conexão nesse início rápido.
Um Token de Acesso do Usuário para o 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, confira Usar a CLI do Azure para criar e gerenciar tokens de acesso.
Configurando
Criação do projeto
No Visual Studio, crie um novo projeto com o modelo Blank App, Packaged (WinUI 3 in Desktop) 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 acesse Manage Nuget Packages
para instalar Azure.Communication.Calling.WindowsClient
1.0.0 ou versão superior. Certifique-se de que Incluir Pré-lançamento esteja marcado.
Solicitar acesso
Adicione o seguinte código à sua app.manifest
:
<file name="RtmMvrMf.dll">
<activatableClass name="VideoN.VideoSchemeHandler" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>
Configurar o framework de aplicativos
Precisamos configurar um layout básico para anexar nossa lógica. Para fazer uma chamada de saída, precisamos de um TextBox
para fornecer a ID de usuário do receptor. Também precisamos de um botão Start Call
e de um botão Hang Up
.
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 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 o App.xaml.cs
(clique com o botão direito do mouse e escolha Exibir código) e adicione essa linha à parte superior:
using CallingQuickstart;
Abra o MainWindow.xaml.cs
(clique com o botão direito do mouse e escolha Exibir código) 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 cuidam de alguns dos principais recursos do SDK de Chamada da Interface do Usuário dos Serviços de Comunicação do Azure:
Nome | Descrição |
---|---|
CallClient |
O CallClient é o ponto de entrada principal para a biblioteca de clientes de Chamada. |
CallAgent |
O CallAgent é usado para iniciar e ingressar em chamadas. |
CommunicationCall |
O CommunicationCall é usado para gerenciar chamadas iniciadas ou ingressadas. |
CallTokenCredential |
O CallTokenCredential é usado como a credencial de token de segurança para criar uma instância 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ê precisará de um Token de Acesso de Usuário. Geralmente, esse token é gerado de um serviço com autenticação específica para o aplicativo. Para saber mais sobre tokens de acesso do usuário, confira o guia Tokens de acesso do usuário.
Para o guia de início rápido, substitua <AUTHENTICATION_TOKEN>
por um token de acesso de usuário gerado para o recurso do Serviço de Comunicação do Azure.
Assim que tiver um token, inicialize uma instância de CallAgent
com ele, o que nos permitirá fazer e receber chamadas. Para acessar as câmeras do dispositivo, também precisamos obter a instância do Gerenciador de Dispositivos.
Adicione o seguinte código à função 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;
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 e o constructo do gerenciador de dispositivos LocalVideoStream
. Precisamos definir o VideoOptions
com LocalVideoStream
e passá-lo com startCallOptions
para definir as opções iniciais da chamada. Ao anexar LocalVideoStream
a um MediaPlayerElement
, podemos visualizar o 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 de entrada
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);
Participante remoto e fluxos de vídeo remotos
Todos os participantes remotos estão disponíveis por meio da coleção RemoteParticipants
em uma instância de chamada. Quando a chamada estiver conectada, podemos acessar os participantes remotos da chamada e identificar os fluxos de vídeo remotos.
Observação
Quando um usuário entra em uma chamada, ele pode acessar os participantes remotos atuais por meio da coleção RemoteParticipants
. O evento OnRemoteParticipantsUpdated
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 ao MediaPlayerElement
.
private async Task AddVideoStreamsAsync(IReadOnlyList<RemoteVideoStream> remoteVideoStreams)
{
foreach (var remoteVideoStream in remoteVideoStreams)
{
var remoteUri = await remoteVideoStream.Start();
this.DispatcherQueue.TryEnqueue(() => {
RemoteVideo.Source = MediaSource.CreateFromUri(remoteUri);
RemoteVideo.MediaPlayer.Play();
});
}
}
Atualização do estado de chamada
Precisamos limpar os renderizadores de vídeo depois que a chamada for desconectada e tratar o caso quando os participantes remotos ingressarem 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;
}
}
Encerrar uma chamada
Finalize a chamada atual quando o botão Hang Up
for clicado. Adicione a implementação ao HangupButton_Click para encerrar uma chamada com o callAgent que criamos e destrua a atualização do participante e os manipuladores de eventos de estado de chamada.
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, oferecemos suporte a ARM64
, x64
e x86
.
Você pode fazer uma chamada de vídeo de saída fornecendo uma ID de usuário no campo de texto e clicando no botão Start Call
.
Observação: chamar 8:echo123
interromperá o fluxo de vídeo porque o bot de eco não dá suporte ao streaming de vídeo.
Para obter mais informações sobre IDs (identidade) de usuário, verifique o guia Tokens de acesso do usuário.