Začínáme s ukázkou volajícího hrdiny
Ukázka volání skupinových služeb Azure Communication Services Hero ukazuje, jak lze k vytvoření prostředí skupinového volání použít sadu SDK pro volání komunikačních služeb.
V tomto ukázkovém rychlém startu se dozvíte, jak ukázka funguje, než ukázku spustíme na místním počítači, a pak ukázku nasadíme do Azure pomocí vlastních prostředků Azure Communication Services.
Stažení kódu
Najděte projekt pro tuto ukázku na GitHubu. Verze ukázky, která obsahuje funkce, které jsou aktuálně ve verzi Public Preview, jako je Spolupráce v Teams a Nahrávání hovorů, najdete v samostatné větvi.
Přehled
Ukázka obsahuje aplikaci na straně klienta i serverovou aplikaci. Klientská aplikace je webová aplikace React/Redux, která používá rozhraní Fluent UI od Microsoftu. Tato aplikace odesílá požadavky do aplikace na straně serveru ASP.NET Core, která pomáhá aplikaci na straně klienta připojit se k Azure.
Ukázka vypadá takto:
Když stisknete tlačítko Spustit volání, webová aplikace načte přístupový token uživatele z aplikace na straně serveru. Tento token se pak použije k připojení klientské aplikace ke službě Azure Communication Services. Po načtení tokenu se zobrazí výzva k zadání kamery a mikrofonu, který chcete použít. Zařízení můžete zakázat nebo povolit pomocí přepínacích ovládacích prvků:
Jakmile nakonfigurujete zobrazované jméno a zařízení, můžete se připojit k relaci volání. Zobrazí se plátno hlavního volání, kde se nachází základní prostředí volání.
Součásti hlavní volající obrazovky:
- Galerie médií: Hlavní fáze, kde se zobrazují účastníci. Pokud má účastník povolenou kameru, zobrazí se zde informační kanál videa. Každý účastník má samostatnou dlaždici, která zobrazuje zobrazované jméno a video stream (pokud existuje).
- Záhlaví: Tady se nacházejí ovládací prvky primárního volání pro přepínání nastavení a bočního panelu účastníků, zapnutí nebo vypnutí videa, sdílení obrazovky a opuštění hovoru.
- Boční panel: Tady se při přepínání pomocí ovládacích prvků v záhlaví zobrazují informace o účastnících a nastaveních. Komponentu lze zavřít pomocí symbolu X v pravém horním rohu. Na bočním panelu účastníků se zobrazuje seznam účastníků a odkaz pro pozvání dalších uživatelů do chatu. Boční panel nastavení umožňuje konfigurovat nastavení mikrofonu a kamery.
Níže najdete další informace o požadavcích a krocích pro nastavení ukázky.
Požadavky
- Účet Azure s aktivním předplatným. Podrobnosti najdete v tématu Vytvoření účtu zdarma.
- Node.js (12.18.4 a vyšší)
- Visual Studio Code (stabilní sestavení)
- Prostředek Azure Communication Services. Podrobnosti najdete v tématu Vytvoření prostředku Azure Communication Services. Pro účely tohoto rychlého startu musíte zaznamenat připojovací řetězec prostředku.
Před prvním spuštěním ukázky
Otevřete instanci PowerShellu, Terminál Windows, příkazového řádku nebo ekvivalent a přejděte do adresáře, do kterého chcete ukázku naklonovat.
git clone https://github.com/Azure-Samples/communication-services-web-calling-hero.git
Získejte azure
Connection String
z webu Azure Portal nebo pomocí Azure CLI.az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
Další informace o připojovací řetězec najdete v tématu Vytvoření komunikačních prostředků Azure.
Jakmile ho získáte
Connection String
, přidejte připojovací řetězec do souboru samples/Server/appsetting.json. Zadejte připojovací řetězec do proměnné:ResourceConnectionString
.Získejte azure
Endpoint string
z webu Azure Portal nebo pomocí Azure CLI.az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
Další informace o řetězcích koncových bodů najdete v tématu Vytvoření komunikačních prostředků Azure.
Jakmile získáte
Endpoint String
řetězec koncového bodu, přidejte do souboru samples/Server/appsetting.json . Zadejte řetězec koncového bodu do proměnné.EndpointUrl
Místní spuštění
Instalace závislostí
npm run setup
Spuštění volající aplikace
npm run start
Tím se otevře klientský server na portu 3000, který obsluhuje soubory webu, a server rozhraní API na portu 8080, který provádí funkce, jako je vytěsňování tokenů pro účastníky volání.
Řešení problému
Aplikace zobrazuje obrazovku Nepodporovaný prohlížeč, ale jsem v podporovaném prohlížeči.
Pokud se vaše aplikace obsluhuje přes jiný název hostitele než localhost, musíte obsluhovat provoz přes https a ne http.
Publikování do Azure
npm run setup
npm run build
npm run package
- Použití rozšíření Azure a nasazení adresáře Volání/dist do služby App Service
Vyčištění prostředků
Pokud chcete vyčistit a odebrat předplatné služby Communication Services, můžete odstranit prostředek nebo skupinu prostředků. Odstraněním skupiny prostředků se odstraní také všechny ostatní prostředky, které jsou k ní přidružené. Přečtěte si další informace o čištění prostředků.
Další kroky
Další informace najdete v následujících článcích:
- Seznámení s používáním sady SDK pro volání
- Další informace o fungování volání
Další čtení
- Ukázky – další ukázky a příklady najdete na stránce s přehledem ukázek.
- Redux – Správa stavu na straně klienta
- FluentUI – Knihovna uživatelského rozhraní Microsoftu
- React – Knihovna pro vytváření uživatelských rozhraní
- ASP.NET Core – architektura pro vytváření webových aplikací
Ukázka volání skupinových služeb Azure Communication Services pro iOS ukazuje, jak lze sadu SDK pro volání komunikačních služeb pro iOS použít k vytvoření skupinového volání, které zahrnuje hlas a video. V tomto ukázkovém rychlém startu se dozvíte, jak nastavit a spustit ukázku. Přehled ukázky je k dispozici pro kontext.
Stažení kódu
Najděte projekt pro tuto ukázku na GitHubu.
Přehled
Ukázka je nativní aplikace pro iOS, která používá sady SDK služby Azure Communication Services pro iOS k vytvoření volajícího prostředí, které obsahuje hlasové i videohovory. Aplikace používá komponentu na straně serveru ke zřízení přístupových tokenů, které se pak používají k inicializaci sady SDK služby Azure Communication Services. Pokud chcete nakonfigurovat tuto součást na straně serveru, můžete postupovat podle kurzu k důvěryhodné službě pomocí služby Azure Functions .
Ukázka vypadá takto:
Když stisknete tlačítko "Zahájit nový hovor", aplikace pro iOS vás vyzve k zadání zobrazovaného jména, které se má pro hovor použít.
Po klepnutí na tlačítko Další na obrazovce Zahájit hovor máte možnost sdílet ID skupiny hovoru prostřednictvím share listu pro iOS.
Aplikace také umožňuje připojit se k existujícímu volání služby Azure Communication Services zadáním ID existujícího volání nebo odkazu NA ID týmu.
Po připojení k hovoru se zobrazí výzva, abyste aplikaci dali oprávnění pro přístup k fotoaparátu a mikrofonu, pokud ještě nemáte oprávnění. Mějte na paměti, že stejně jako všechny aplikace založené na AVFoundation jsou skutečné funkce zvuku a videa dostupné pouze na skutečném hardwaru.
Jakmile nakonfigurujete zobrazované jméno a připojíte se k hovoru, uvidíte plátno hlavního volání, kde se nachází základní prostředí volání.
Součásti hlavní volající obrazovky:
- Galerie médií: Hlavní fáze, kde se zobrazují účastníci. Pokud má účastník povolenou kameru, zobrazí se zde informační kanál videa. Každý účastník má samostatnou dlaždici, která zobrazuje zobrazované jméno a video stream (pokud existuje). Galerie podporuje více účastníků a aktualizuje se při přidání nebo odebrání účastníků do hovoru.
- Panel akcí: Tady se nacházejí primární ovládací prvky volání. Tyto ovládací prvky umožňují zapnout nebo vypnout video a mikrofon, sdílet obrazovku a opustit hovor.
Níže najdete další informace o požadavcích a krocích pro nastavení ukázky.
Požadavky
- Účet Azure s aktivním předplatným. Podrobnosti najdete v tématu Vytvoření účtu zdarma.
- Mac se systémem Xcode spolu s platným certifikátem vývojáře nainstalovaným do klíčenky.
- Prostředek Azure Communication Services. Podrobnosti najdete v tématu Vytvoření prostředku Azure Communication Services.
- Funkce Azure, která spouští koncový bod ověřování pro načtení přístupových tokenů.
Místní spuštění ukázky
Ukázku volání skupiny je možné spustit místně pomocí XCode. Vývojáři můžou k otestování aplikace použít fyzické zařízení nebo emulátor.
Před prvním spuštěním ukázky
- Nainstalujte závislosti spuštěním
pod install
příkazu . - Otevřete
AzureCalling.xcworkspace
v XCode. - Vytvořte textový soubor v kořenovém adresáři a
AppSettings.xcconfig
nastavte hodnotu:communicationTokenFetchUrl = <your authentication endpoint, without the https:// component>
Spuštění ukázky
Sestavte a spusťte ukázku v XCode pomocí cíle AzureCalling na simulátoru nebo zařízení podle vašeho výběru.
(Volitelné) Zabezpečení koncového bodu ověřování
Pro demonstrační účely tato ukázka ve výchozím nastavení používá veřejně přístupný koncový bod k načtení přístupového tokenu služby Azure Communication Services. V produkčních scénářích doporučujeme ke zřízení vlastních tokenů použít vlastní zabezpečený koncový bod.
Tato ukázka s další konfigurací podporuje připojení ke koncovému bodu chráněnému microsoft entra ID (Microsoft Entra ID), aby se pro aplikaci vyžadovalo přihlášení uživatele k načtení přístupového tokenu služby Azure Communication Services. Projděte si následující kroky:
- Povolte v aplikaci ověřování Microsoft Entra.
- V části Registrace aplikací Microsoft Entra přejděte na stránku s přehledem zaregistrované aplikace. Poznamenejte
Application (client) ID
si ,Directory (tenant) ID
Application ID URI
- Vytvořte
AppSettings.xcconfig
soubor v kořenovém adresáři, pokud ještě není k dispozici, a přidejte hodnoty:communicationTokenFetchUrl = <Application ID URI, without the https:// component> aadClientId = <Application (client) ID> aadTenantId = <Directory (tenant) ID>
Vyčištění prostředků
Pokud chcete vyčistit a odebrat předplatné služby Communication Services, můžete odstranit prostředek nebo skupinu prostředků. Odstraněním skupiny prostředků se odstraní také všechny ostatní prostředky, které jsou k ní přidružené. Přečtěte si další informace o čištění prostředků.
Další kroky
Další informace najdete v následujících článcích:
- Seznámení s používáním sady SDK pro volání
- Další informace o fungování volání
Další čtení
- Azure Communication GitHub – Další příklady a informace najdete na oficiální stránce GitHubu.
- Ukázky – další ukázky a příklady najdete na stránce s přehledem ukázek.
- Funkce volání azure Communication – Další informace o volání sady SDK pro iOS – Azure Communication iOS Calling SDK
Ukázka volání skupiny Azure Communication Services pro Android ukazuje, jak lze sadu SDK pro volání komunikačních služeb pro Android použít k vytvoření skupinového volání, které zahrnuje hlas a video. V tomto ukázkovém rychlém startu se dozvíte, jak nastavit a spustit ukázku. Přehled ukázky je k dispozici pro kontext.
Stažení kódu
Najděte projekt pro tuto ukázku na GitHubu.
Přehled
Ukázka je nativní aplikace pro Android, která používá klientskou knihovnu uživatelského rozhraní Androidu v Azure Communication Services k vytvoření volajícího prostředí, které obsahuje hlasové i videohovory. Aplikace používá komponentu na straně serveru ke zřízení přístupových tokenů, které se pak používají k inicializaci sady SDK služby Azure Communication Services. Pokud chcete nakonfigurovat tuto součást na straně serveru, můžete postupovat podle kurzu k důvěryhodné službě pomocí služby Azure Functions .
Ukázka vypadá takto:
Když stisknete tlačítko Zahájit nový hovor, aplikace pro Android vás vyzve k zadání zobrazovaného jména, které se má pro hovor použít.
Po klepnutí na tlačítko Další na stránce Zahájit hovor máte možnost sdílet ID skupinového hovoru.
Aplikace umožňuje připojit se k existujícímu volání služby Azure Communication Services zadáním ID existujícího hovoru nebo odkazu na ID schůzky týmů a zobrazovaného jména.
Po připojení k hovoru se zobrazí výzva, abyste aplikaci dali oprávnění pro přístup k fotoaparátu a mikrofonu, pokud ještě nemáte oprávnění. Uvidíte plátno hlavního volání, kde se nachází základní prostředí volání.
Součásti hlavní volající obrazovky:
- Galerie médií: Hlavní fáze, kde se zobrazují účastníci. Pokud má účastník povolenou kameru, zobrazí se zde informační kanál videa. Každý účastník má samostatnou dlaždici, která zobrazuje zobrazované jméno a video stream (pokud existuje). Galerie podporuje více účastníků a aktualizuje se při přidání nebo odebrání účastníků do hovoru.
- Panel akcí: Tady se nacházejí primární ovládací prvky volání. Tyto ovládací prvky umožňují zapnout nebo vypnout video a mikrofon, sdílet obrazovku a opustit hovor.
Níže najdete další informace o požadavcích a krocích pro nastavení ukázky.
Požadavky
- Účet Azure s aktivním předplatným. Podrobnosti najdete v tématu Vytvoření účtu zdarma.
- Android Studio spuštěné na vašem počítači
- Prostředek Azure Communication Services. Podrobnosti najdete v tématu Vytvoření prostředku Azure Communication Services.
- Funkce Azure, která spouští koncový bod ověřování pro načtení přístupových tokenů.
Místní spuštění ukázky
Ukázku volání skupiny je možné spustit místně pomocí Android Studia. Vývojáři můžou k otestování aplikace použít fyzické zařízení nebo emulátor.
Před prvním spuštěním ukázky
- Otevřete Android Studio a vyberte
Open an Existing Project
AzureCalling
Otevřete složku uvnitř stažené verze pro ukázku.- Rozbalte aplikaci nebo prostředky, které chcete aktualizovat
appSettings.properties
. Nastavte hodnotu klíčecommunicationTokenFetchUrl
tak, aby byla adresa URL vašeho koncového bodu ověřování nastavená jako předpoklad.
Spuštění ukázky
Sestavte a spusťte ukázku v Android Studiu.
(Volitelné) Zabezpečení koncového bodu ověřování
Pro demonstrační účely tato ukázka ve výchozím nastavení používá veřejně přístupný koncový bod k načtení tokenu Azure Communication Services. V produkčních scénářích doporučujeme ke zřízení vlastních tokenů použít vlastní zabezpečený koncový bod.
V případě další konfigurace tato ukázka podporuje připojení ke koncovému bodu chráněnému Microsoft Entra ID (Microsoft Entra ID), aby se pro aplikaci vyžadovalo přihlášení uživatele k načtení tokenu služby Azure Communication Services. Projděte si následující kroky:
Povolte v aplikaci ověřování Microsoft Entra.
V části Registrace aplikací Microsoft Entra přejděte na stránku s přehledem zaregistrované aplikace. Povšimněte
Package name
si ,Signature hash
,MSAL Configuration
.
Upravte
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
a nastavteisAADAuthEnabled
povolení MICROSOFT Entra ID.Upravte
AndroidManifest.xml
a nastavteandroid:path
hodnotu hash podpisu úložiště klíčů. (Volitelné. Aktuální hodnota používá hodnotu hash z bundled debug.keystore. Pokud se používá jiné úložiště klíčů, je nutné ho aktualizovat.)<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>
Zkopírujte konfiguraci MSAL Pro Android z webu Azure Portal a vložte do
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
souboru . Zahrnout "account_mode": "SINGLE"{ "client_id": "", "authorization_user_agent": "DEFAULT", "redirect_uri": "", "account_mode" : "SINGLE", "authorities": [ { "type": "AAD", "audience": { "type": "AzureADMyOrg", "tenant_id": "" } } ] }
Upravte
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
a nastavte hodnotu klíčecommunicationTokenFetchUrl
tak, aby byla adresa URL vašeho zabezpečeného koncového bodu ověřování.Úprava
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
a nastavení hodnoty klíčeaadScopes
zAzure Active Directory
Expose an API
oborůNastavte hodnotu
graphURL
inAzureCalling/app/assets/appSettings.properties
jako koncový bod rozhraní Graph API pro načtení informací o uživateli.Upravte
AzureCalling/app/src/main/assets/appSettings.properties
a nastavte hodnotu klíčetenant
, aby bylo možné povolit tiché přihlášení, aby se uživatel nemusel znovu ověřovat a znovu při restartování aplikace.
Vyčištění prostředků
Pokud chcete vyčistit a odebrat předplatné služby Communication Services, můžete odstranit prostředek nebo skupinu prostředků. Odstraněním skupiny prostředků se odstraní také všechny ostatní prostředky, které jsou k ní přidružené. Přečtěte si další informace o čištění prostředků.
Další kroky
Další informace najdete v následujících článcích:
- Seznámení s používáním sady SDK pro volání
- Další informace o fungování volání
Další čtení
- Azure Communication GitHub – Další příklady a informace najdete na oficiální stránce GitHubu.
- Ukázky – další ukázky a příklady najdete na stránce s přehledem ukázek.
- Funkce volání azure Communication – Další informace o volání sady Android SDK – Azure Communication Android Calling SDK
Ukázka volání skupiny Azure Communication Services pro Windows ukazuje, jak lze sadu Windows SDK pro volání komunikačních služeb použít k vytvoření skupinového volání, které zahrnuje hlas a video. V této ukázce se dozvíte, jak nastavit a spustit ukázku. Přehled ukázky je k dispozici pro kontext.
V tomto rychlém startu se dozvíte, jak spustit videohovor ve verzi 1:1 pomocí sady SDK pro volání služeb Azure Communication Services pro Windows.
Ukázkový kód UPW
Požadavky
Pro absolvování tohoto kurzu musí být splněné následující požadavky:
Účet Azure s aktivním předplatným. Vytvoření účtu zdarma
Nainstalujte sadu Visual Studio 2022 s Univerzální platforma Windows úlohou vývoje.
Nasazený prostředek komunikační služby. Vytvořte prostředek komunikační služby. Pro účely tohoto rychlého startu musíte zaznamenat připojovací řetězec.
Přístupový token uživatele pro vaši službu Azure Communication Service. K vytvoření uživatele a přístupového tokenu můžete také použít Azure CLI a spustit příkaz se svým připojovací řetězec.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Podrobnosti najdete v tématu Použití Azure CLI k vytváření a správě přístupových tokenů.
Nastavení
Vytvoření projektu
V sadě Visual Studio vytvořte nový projekt pomocí šablony Prázdná aplikace (Univerzální windows) pro nastavení jednostránka Univerzální platforma Windows (UPW).
Nainstalujte balíček .
Klikněte pravým tlačítkem na projekt a přejděte na Manage Nuget Packages
instalaci Azure.Communication.Calling.WindowsClient
verze 1.2.0-beta.1 nebo vyšší verze. Ujistěte se, že je zaškrtnuté políčko Zahrnout předběžné verze.
Vyžádat si přístup
Přejděte na Package.appxmanifest
a klikněte na Capabilities
.
Zkontrolujte Internet (Client & Server)
, jestli chcete získat příchozí a odchozí přístup k internetu.
Zkontrolujte Microphone
přístup ke zvukovému kanálu mikrofonu.
Zkontrolujte WebCam
přístup ke kameře zařízení.
Kliknutím pravým tlačítkem myši a zvolením možnosti Zobrazit kód přidejte následující kód.Package.appxmanifest
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
Nastavení architektury aplikace
Potřebujeme nakonfigurovat základní rozložení pro připojení naší logiky. Abychom mohli umístit odchozí hovor, musíme TextBox
zadat ID uživatele volaného. Potřebujeme Start Call
také tlačítko a Hang Up
tlačítko.
Potřebujeme také zobrazit náhled místního videa a vykreslit vzdálené video druhého účastníka. Potřebujeme tedy dva prvky k zobrazení streamů videa.
MainPage.xaml
Otevřete projekt a nahraďte obsah následující implementací.
<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>
Otevřete ( App.xaml.cs
klikněte pravým tlačítkem myši a zvolte Zobrazit kód) a přidejte tento řádek do horní části:
using CallingQuickstart;
MainPage.xaml.cs
Otevřete (klikněte pravým tlačítkem myši a zvolte Zobrazit kód) a nahraďte obsah následující implementací:
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
}
}
}
Objektový model
Následující třídy a rozhraní zpracovávají některé z hlavních funkcí sady SDK pro volání služeb Azure Communication Services:
Název | Popis |
---|---|
CallClient |
Jedná se CallClient o hlavní vstupní bod do klientské knihovny volání. |
CallAgent |
Slouží CallAgent ke spuštění a připojení k voláním. |
CommunicationCall |
Slouží CommunicationCall ke správě umístěných nebo připojených hovorů. |
CallTokenCredential |
Slouží CallTokenCredential jako přihlašovací údaje tokenu k vytvoření instance CallAgent . |
CommunicationUserIdentifier |
Slouží CommunicationUserIdentifier k reprezentaci identity uživatele, což může být jedna z následujících možností: CommunicationUserIdentifier nebo PhoneNumberIdentifier CallingApplication . |
Ověření klienta
K inicializaci CallAgent
potřebujete přístupový token uživatele. Obecně platí, že tento token se generuje ze služby s ověřováním specifickým pro aplikaci. Další informace o přístupových tokenech uživatelů najdete v průvodci uživatelskými přístupovými tokeny .
V tomto rychlém startu nahraďte <AUTHENTICATION_TOKEN>
přístupovým tokenem uživatele vygenerovaným pro prostředek služby Azure Communication Service.
Jakmile máte token, inicializujete CallAgent
s ní instanci, která nám umožní provádět a přijímat volání. Abychom měli přístup k fotoaparátům na zařízení, musíme také získat Správce zařízení instanci.
Do funkce přidejte následující kód 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
}
}
Zahájení hovoru s videem
Přidejte implementaci k CallButton_Click
zahájení hovoru s videem. Potřebujeme vytvořit výčet fotoaparátů s instancí správce zařízení a konstruktorem LocalOutgoingVideoStream
. Potřebujeme nastavit a VideoOptions
LocalVideoStream
předat ho startCallOptions
, abychom nastavili počáteční možnosti volání. Když se připojíte LocalOutgoingVideoStream
k objektu MediaElement
, uvidíme náhled místního videa.
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;
}
Přidejte metody pro zahájení nebo připojení k různým typům volání (1:1 volání služeb Azure Communication Services, telefonní hovor 1:1, skupinový hovor služby Azure Communication Services, připojení ke schůzce Teams atd.).
private async Task<CommunicationCall> StartAcsCallAsync(string acsCallee)
{
var options = await GetStartCallOptionsAsync();
var call = await this.callAgent.StartCallAsync( new [] { new UserCallIdentifier(acsCallee) }, options);
return call;
}
private async Task<CommunicationCall> StartPhoneCallAsync(string acsCallee, string alternateCallerId)
{
var options = await GetStartCallOptionsAsync();
options.AlternateCallerId = new PhoneNumberCallIdentifier(alternateCallerId);
var call = await this.callAgent.StartCallAsync( new [] { new PhoneNumberCallIdentifier(acsCallee) }, options);
return call;
}
private async Task<CommunicationCall> JoinGroupCallByIdAsync(Guid groupId)
{
var joinCallOptions = await GetJoinCallOptionsAsync();
var groupCallLocator = new GroupCallLocator(groupId);
var call = await this.callAgent.JoinAsync(groupCallLocator, joinCallOptions);
return call;
}
private async Task<CommunicationCall> JoinTeamsMeetingByLinkAsync(Uri teamsCallLink)
{
var joinCallOptions = await GetJoinCallOptionsAsync();
var teamsMeetingLinkLocator = new TeamsMeetingLinkLocator(teamsCallLink.AbsoluteUri);
var call = await callAgent.JoinAsync(teamsMeetingLinkLocator, joinCallOptions);
return call;
}
private async Task<StartCallOptions> GetStartCallOptionsAsync()
{
return new StartCallOptions() {
OutgoingAudioOptions = new OutgoingAudioOptions() { IsOutgoingAudioMuted = true, OutgoingAudioStream = micStream },
OutgoingVideoOptions = new OutgoingVideoOptions() { OutgoingVideoStreams = new OutgoingVideoStream[] { cameraStream } }
};
}
private async Task<JoinCallOptions> GetJoinCallOptionsAsync()
{
return new JoinCallOptions() {
OutgoingAudioOptions = new OutgoingAudioOptions() { IsOutgoingAudioMuted = true },
OutgoingVideoOptions = new OutgoingVideoOptions() { OutgoingVideoStreams = new OutgoingVideoStream[] { cameraStream } }
};
}
Přidejte kód pro vytvoření LocalVideoStream v závislosti na vybrané kameře v CameraList_SelectionChanged
metodě.
var selectedCamera = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamera);
var localUri = await cameraStream.StartPreviewAsync();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
LocalVideo.Source = MediaSource.CreateFromUri(localUri);
});
if (call != null)
{
await call?.StartVideoAsync(cameraStream);
}
Přijetí příchozího hovoru
Přidejte implementaci do OnIncomingCallAsync
příchozího hovoru s videem, předejte ho LocalVideoStream
.acceptCallOptions
var incomingCall = args.IncomingCall;
var acceptCallOptions = new AcceptCallOptions() {
IncomingVideoOptions = new IncomingVideoOptions()
{
IncomingVideoStreamKind = VideoStreamKind.RemoteIncoming
}
};
_ = await incomingCall.AcceptAsync(acceptCallOptions);
Vzdálený účastník a vzdálené video streamy
Všichni vzdálení účastníci jsou k dispozici prostřednictvím RemoteParticipants
kolekce v instanci volání. Jakmile se hovor připojí (CallState.Connected
), můžeme přistupovat ke vzdáleným účastníkům hovoru a zpracovávat vzdálené streamy videa.
Poznámka:
Když se uživatel připojí k hovoru, bude mít přístup k aktuálním vzdáleným účastníkům prostřednictvím RemoteParticipants
kolekce. Událost RemoteParticipantsUpdated
se pro tyto stávající účastníky neaktivuje. Tato událost se aktivuje jenom v případě, že se vzdálený účastník připojí nebo opustí hovor, když je uživatel již v hovoru.
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;
}
}
Vykreslení vzdálených videí
Pro každý vzdálený video stream, připojte ho MediaElement
k .
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();
});
}
}
Aktualizace stavu volání
Jakmile se hovor odpojí, musíme vykreslovat vykreslovací moduly videa a zpracovat případ, když se vzdálení účastníci poprvé připojí k hovoru.
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;
}
}
Ukončení hovoru
Ukončení aktuálního hovoru po kliknutí na Hang Up
tlačítko Přidejte implementaci do HangupButton_Click pro ukončení volání pomocí callAgent, který jsme vytvořili, a odbourejte obslužné rutiny událostí stavu volání a aktualizace účastníka.
var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
try
{
await call.HangUpAsync(new HangUpOptions() { ForEveryone = true });
}
catch(Exception ex)
{
}
}
Spuštění kódu
Kód můžete sestavit a spustit v sadě Visual Studio. Pro platformy řešení podporujeme ARM64
x64
a x86
.
Odchozí videohovor můžete provést tak, že do textového pole zadáte ID uživatele a kliknete na Start Call
tlačítko.
Poznámka: Volání 8:echo123
zastaví stream videa, protože robot echo nepodporuje streamování videa.
Další informace o ID uživatele (identitě) najdete v průvodci přístupové tokeny uživatele.
Vzorový kód WinUI 3
Požadavky
Pro absolvování tohoto kurzu musí být splněné následující požadavky:
Účet Azure s aktivním předplatným. Vytvoření účtu zdarma
Nainstalujte Visual Studio 2022 a Windows App SDK verze 1.2 Preview 2.
Základní znalosti o tom, jak vytvořit aplikaci WinUI 3 Vytvoření prvního projektu WinUI 3 (Windows App SDK) je dobrým zdrojem, se kterým můžete začít.
Nasazený prostředek komunikační služby. Vytvořte prostředek komunikační služby. Pro účely tohoto rychlého startu musíte zaznamenat připojovací řetězec.
Přístupový token uživatele pro vaši službu Azure Communication Service. K vytvoření uživatele a přístupového tokenu můžete také použít Azure CLI a spustit příkaz se svým připojovací řetězec.
az communication identity token issue --scope voip --connection-string "yourConnectionString"
Podrobnosti najdete v tématu Použití Azure CLI k vytváření a správě přístupových tokenů.
Nastavení
Vytvoření projektu
V sadě Visual Studio vytvořte nový projekt pomocí šablony Prázdná aplikace zabalená (WinUI 3 v desktopové verzi) pro nastavení jednostráňové aplikace WinUI 3.
Nainstalujte balíček .
Klikněte pravým tlačítkem na projekt a přejděte na Manage Nuget Packages
instalaci Azure.Communication.Calling.WindowsClient
verze 1.0.0 nebo vyšší verze. Ujistěte se, že je zaškrtnuté políčko Zahrnout předběžné verze.
Vyžádat si přístup
Do svého počítače app.manifest
přidejte následující kód:
<file name="RtmMvrMf.dll">
<activatableClass name="VideoN.VideoSchemeHandler" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>
Nastavení architektury aplikace
Potřebujeme nakonfigurovat základní rozložení pro připojení naší logiky. Abychom mohli umístit odchozí hovor, musíme TextBox
zadat ID uživatele volaného. Potřebujeme Start Call
také tlačítko a Hang Up
tlačítko.
Potřebujeme také zobrazit náhled místního videa a vykreslit vzdálené video druhého účastníka. Potřebujeme tedy dva prvky k zobrazení streamů videa.
MainWindow.xaml
Otevřete projekt a nahraďte obsah následující implementací.
<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>
Otevřete ( App.xaml.cs
klikněte pravým tlačítkem myši a zvolte Zobrazit kód) a přidejte tento řádek do horní části:
using CallingQuickstart;
MainWindow.xaml.cs
Otevřete (klikněte pravým tlačítkem myši a zvolte Zobrazit kód) a nahraďte obsah následující implementací:
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();
});
}
}
}
Objektový model
Následující třídy a rozhraní zpracovávají některé z hlavních funkcí sady SDK pro volání služeb Azure Communication Services:
Název | Popis |
---|---|
CallClient |
Jedná se CallClient o hlavní vstupní bod do klientské knihovny volání. |
CallAgent |
Slouží CallAgent ke spuštění a připojení k voláním. |
CommunicationCall |
Slouží CommunicationCall ke správě umístěných nebo připojených hovorů. |
CallTokenCredential |
Slouží CallTokenCredential jako přihlašovací údaje tokenu k vytvoření instance CallAgent . |
CommunicationUserIdentifier |
Slouží CommunicationUserIdentifier k reprezentaci identity uživatele, což může být jedna z následujících možností: CommunicationUserIdentifier nebo PhoneNumberIdentifier CallingApplication . |
Ověření klienta
K inicializaci CallAgent
potřebujete přístupový token uživatele. Obecně platí, že tento token se generuje ze služby s ověřováním specifickým pro aplikaci. Další informace o přístupových tokenech uživatelů najdete v průvodci uživatelskými přístupovými tokeny .
V tomto rychlém startu nahraďte <AUTHENTICATION_TOKEN>
přístupovým tokenem uživatele vygenerovaným pro prostředek služby Azure Communication Service.
Jakmile s ní inicializujete CallAgent
token, který nám umožní provádět a přijímat volání. Abychom měli přístup k fotoaparátům na zařízení, musíme také získat Správce zařízení instanci.
Do funkce přidejte následující kód 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;
Zahájení hovoru s videem
Přidejte implementaci k CallButton_Click
zahájení hovoru s videem. Potřebujeme vytvořit výčet fotoaparátů s instancí správce zařízení a konstruktorem LocalVideoStream
. Potřebujeme nastavit a VideoOptions
LocalVideoStream
předat ho startCallOptions
, abychom nastavili počáteční možnosti volání. Když se připojíte LocalVideoStream
k objektu MediaPlayerElement
, uvidíme náhled místního videa.
var startCallOptions = new StartCallOptions();
if (this.deviceManager.Cameras?.Count > 0)
{
var videoDeviceInfo = this.deviceManager.Cameras?.FirstOrDefault();
if (videoDeviceInfo != null)
{
var selectedCamera = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamera);
var localUri = await cameraStream.StartPreviewAsync();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
LocalVideo.Source = MediaSource.CreateFromUri(localUri);
});
startCallOptions.VideoOptions = new OutgoingVideoOptions(new[] { cameraStream });
}
}
var callees = new ICommunicationIdentifier[1]
{
new CommunicationUserIdentifier(CalleeTextBox.Text.Trim())
};
this.call = await this.callAgent.StartCallAsync(callees, startCallOptions);
this.call.OnRemoteParticipantsUpdated += Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged += Call_OnStateChangedAsync;
Přijetí příchozího hovoru
Přidejte implementaci do Agent_OnIncomingCallAsync
příchozího hovoru s videem, předejte ho LocalVideoStream
.acceptCallOptions
var acceptCallOptions = new AcceptCallOptions();
if (this.deviceManager.Cameras?.Count > 0)
{
var videoDeviceInfo = this.deviceManager.Cameras?.FirstOrDefault();
if (videoDeviceInfo != null)
{
var selectedCamera = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamera);
var localUri = await cameraStream.StartPreviewAsync();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
LocalVideo.Source = MediaSource.CreateFromUri(localUri);
});
acceptCallOptions.VideoOptions = new OutgoingVideoOptions(new[] { localVideoStream });
}
}
call = await incomingCall.AcceptAsync(acceptCallOptions);
Vzdálený účastník a vzdálené video streamy
Všichni vzdálení účastníci jsou k dispozici prostřednictvím RemoteParticipants
kolekce v instanci volání. Jakmile je hovor připojený, můžeme získat přístup ke vzdáleným účastníkům hovoru a zpracovat vzdálené streamy videa.
Poznámka:
Když se uživatel připojí k hovoru, bude mít přístup k aktuálním vzdáleným účastníkům prostřednictvím RemoteParticipants
kolekce. Událost OnRemoteParticipantsUpdated
se pro tyto stávající účastníky neaktivuje. Tato událost se aktivuje jenom v případě, že se vzdálený účastník připojí nebo opustí hovor, když je uživatel již v hovoru.
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);
}
}
Vykreslení vzdálených videí
Pro každý vzdálený video stream, připojte ho MediaPlayerElement
k .
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();
});
}
}
Aktualizace stavu volání
Jakmile se hovor odpojí, musíme vykreslovat vykreslovací moduly videa a zpracovat případ, když se vzdálení účastníci poprvé připojí k hovoru.
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;
}
}
Ukončení hovoru
Ukončení aktuálního hovoru po kliknutí na Hang Up
tlačítko Přidejte implementaci do HangupButton_Click pro ukončení volání pomocí callAgent, který jsme vytvořili, a odbourejte obslužné rutiny událostí stavu volání a aktualizace účastníka.
this.call.OnRemoteParticipantsUpdated -= Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged -= Call_OnStateChangedAsync;
await this.call.HangUpAsync(new HangUpOptions());
Spuštění kódu
Kód můžete sestavit a spustit v sadě Visual Studio. Pro platformy řešení podporujeme ARM64
x64
a x86
.
Odchozí videohovor můžete provést tak, že do textového pole zadáte ID uživatele a kliknete na Start Call
tlačítko.
Poznámka: Volání 8:echo123
zastaví stream videa, protože robot echo nepodporuje streamování videa.
Další informace o ID uživatele (identitě) najdete v průvodci přístupové tokeny uživatele.