Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Warning
Azure Communication Services wprowadza nowatorskie zmiany, a niektóre usługi są wycofywane. Dowiedz się więcej w przewodniku po zmianach emerytalnych i przełamowych.
Przykład Group Calling Hero Sample w usłudze Azure Communication Services pokazuje, jak za pomocą zestawu SDK wywołań dla sieci Web usługi Communication Services można utworzyć obsługę połączeń grupowych.
W tym przykładowym przewodniku Szybki start omówimy działanie przykładu przed jego uruchomieniem na komputerze lokalnym, a następnie jego wdrożeniem na platformie Azure przy użyciu własnych zasobów usługi Azure Communication Services.
Pobieranie kodu
Znajdź projekt dla tego przykładu w witrynie GitHub. Wersję przykładu zawierającą funkcje obecnie dostępne w publicznej wersji zapoznawczej, takie jak Teams Interop i Nagrywanie połączeń, można znaleźć w oddzielnej gałęzi.
Omówienie
Przykład zawiera zarówno aplikację po stronie klienta, jak i aplikację po stronie serwera. Aplikacja po stronie klienta to aplikacja internetowa React/Redux, która korzysta z platformy Fluent UI firmy Microsoft. Ta aplikacja wysyła żądania do aplikacji po stronie serwera ASP.NET Core, która pomaga aplikacji po stronie klienta nawiązywać połączenie z platformą Azure.
Oto jak wygląda przykład:
Po naciśnięciu przycisku "Uruchom wywołanie" aplikacja internetowa pobiera token dostępu użytkownika z aplikacji po stronie serwera. Ten token jest następnie używany do łączenia aplikacji klienckiej z usługami Azure Communication Services. Po pobraniu tokenu zostanie wyświetlony monit o określenie aparatu i mikrofonu, którego chcesz użyć. Możesz wyłączyć/włączyć urządzenia za pomocą kontrolek przełącznika:
Po skonfigurowaniu nazwy wyświetlanej i urządzeń możesz dołączyć do sesji połączenia. Zobaczysz główny ekran połączenia, gdzie znajdują się podstawowe funkcje połączenia.
Elementy głównego ekranu połączenia:
- Galeria multimediów: główny etap, na którym są pokazywani uczestnicy. Jeśli uczestnik ma włączoną kamerę, ich kanał wideo jest wyświetlany tutaj. Każdy uczestnik ma osobny kafelek, który wyświetla wyświetlaną nazwę i strumień wideo (jeśli jest dostępny)
- Nagłówek: To tutaj znajdują się główne elementy sterujące połączeniem, umożliwiające przełączanie ustawień i panelu bocznego uczestników, włączanie i wyłączanie wideo oraz mikrofonu, udostępnianie ekranu i opuszczanie połączenia.
- Panel boczny: Tutaj wyświetlana jest lista uczestników i informacje o ustawieniach po włączeniu za pomocą elementów sterujących w nagłówku. Składnik można odrzucić przy użyciu "X" w prawym górnym rogu. Pasek boczny uczestników zawiera listę uczestników i link umożliwiający zaproszenie większej liczby użytkowników do czatu. Pasek boczny Ustawienia umożliwia skonfigurowanie ustawień mikrofonu i aparatu.
Poniżej znajdziesz więcej informacji o wymaganiach wstępnych i krokach potrzebnych do skonfigurowania przykładu.
Wymagania wstępne
- Konto platformy Azure z aktywną subskrypcją. Aby uzyskać szczegółowe informacje, zobacz Tworzenie bezpłatnego konta
- Node.js (12.18.4 i nowsze)
- Visual Studio Code (stabilna kompilacja)
- Zasób usług Azure Communication Services. Aby uzyskać szczegółowe informacje, zobacz Tworzenie zasobu usług Azure Communication Services. Musisz zapisać parametry połączenia zasobu na potrzeby tego przewodnika Szybki start.
Przed uruchomieniem przykładu po raz pierwszy
Otwórz wystąpienie programu PowerShell, Terminal Windows, wiersza polecenia lub równoważnego i przejdź do katalogu, do którego chcesz sklonować przykład.
git clone https://github.com/Azure-Samples/communication-services-web-calling-hero.gitPobierz
Connection Stringz portalu Azure lub przy użyciu Azure CLI.az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"Aby uzyskać więcej informacji na temat parametrów połączenia, zobacz Tworzenie zasobów usługi Azure Communication Services
Gdy masz już
Connection String, dodaj ciąg połączenia do pliku samples/Server/appsetting.json. Wprowadź parametry połączenia w zmiennej:ResourceConnectionString.Pobierz
Endpoint stringz portalu Azure lub przy użyciu interfejsu wiersza polecenia platformy Azure.az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"Aby uzyskać więcej informacji na temat ciągów punktów końcowych, zobacz Create an Azure Communication Resources (Tworzenie zasobów komunikacji platformy Azure)
Gdy otrzymasz
Endpoint String, dodaj ciąg znaków punktu końcowego do pliku samples/Server/appsetting.json. Wprowadź ciąg znaków punktu końcowego do zmiennejEndpointUrl
Uruchamianie lokalne
Instalowanie zależności
npm run setupUruchamianie aplikacji wywołującej
npm run startSpowoduje to otwarcie serwera klienta na porcie 3000, który obsługuje pliki witryny internetowej, oraz serwer interfejsu API na porcie 8080, który wykonuje funkcje, takie jak wybicie tokenów dla uczestników połączeń.
Rozwiązywanie problemów
Aplikacja wyświetla ekran "Nieobsługiwana przeglądarka", ale jestem w obsługiwanej przeglądarce.
Jeśli aplikacja jest obsługiwana za pośrednictwem nazwy hosta innej niż localhost, musisz obsługiwać ruch za pośrednictwem protokołu HTTPS, a nie http.
Publikowanie na platformie Azure
npm run setupnpm run buildnpm run package- Użyj rozszerzenia platformy Azure i wdróż katalog Calling/dist w usłudze app Service
Czyszczenie zasobów
Jeśli chcesz wyczyścić i usunąć subskrypcję usług Komunikacyjnych, możesz usunąć zasób lub grupę zasobów. Usunięcie grupy zasobów powoduje również usunięcie wszelkich innych skojarzonych z nią zasobów. Dowiedz się więcej o czyszczeniu zasobów.
Następne kroki
Aby uzyskać więcej informacji, zobacz następujące artykuły:
- Zapoznaj się z zestawem SDK do wywołań
- Dowiedz się więcej o tym, jak działa dzwonienie
Materiały uzupełniające
- Przykłady — znajdź więcej przykładów i innych materiałów przykładowych na naszej stronie z przeglądem przykładów.
- Redux — zarządzanie stanem po stronie klienta
- FluentUI — biblioteka interfejsu użytkownika obsługiwana przez firmę Microsoft
- React — biblioteka do tworzenia interfejsów użytkownika
- ASP.NET Core — struktura do tworzenia aplikacji internetowych
Przykład Group Calling Hero dla systemu iOS w usłudze Azure Communication Services pokazuje, jak za pomocą zestawu SDK wywołań usługi Communication Services dla systemu iOS można utworzyć obsługę połączeń grupowych obejmujących głos i wideo. W tym przykładowym przewodniku Szybki start dowiesz się, jak skonfigurować i uruchomić przykład. Przedstawiono omówienie przykładu dla lepszego zrozumienia.
Pobieranie kodu
Znajdź projekt dla tego przykładu w witrynie GitHub.
Omówienie
Przykład jest natywną aplikacją dla systemu iOS, która używa zestawów SDK usług Azure Communication Services dla systemu iOS do tworzenia środowiska wywołującego, które oferuje zarówno połączenie głosowe, jak i wideo. Aplikacja używa składnika po stronie serwera do aprowizowania tokenów dostępu, które są następnie używane do inicjowania zestawu SDK usług Azure Communication Services. Aby skonfigurować ten składnik po stronie serwera, możesz skorzystać z samouczka Zaufana usługa z Azure Functions.
Oto jak wygląda przykład:
Po naciśnięciu przycisku „Rozpocznij nowe połączenie” aplikacja na iOS poprosi o podanie wyświetlanej nazwy, która będzie używana podczas połączenia.
Po naciśnięciu przycisku „Dalej” na ekranie „Rozpocznij połączenie” możesz udostępnić identyfikator grupy połączenia za pośrednictwem arkusza udostępniania w iOS.
Aplikacja umożliwia również dołączenie do istniejącego połączenia usługi Azure Communication Services poprzez podanie identyfikatora istniejącego połączenia lub linku z identyfikatorem Teams.
Po dołączeniu do rozmowy pojawi się monit o przyznanie aplikacji dostępu do kamery i mikrofonu, jeśli aplikacja nie ma jeszcze odpowiednich uprawnień. Należy pamiętać, że podobnie jak wszystkie aplikacje oparte na avFoundation, prawdziwe funkcje audio i wideo są dostępne tylko na rzeczywistym sprzęcie.
Po skonfigurowaniu nazwy wyświetlanej i dołączeniu do rozmowy zobaczysz główny ekran rozmowy, na którym odbywa się jej główna część.
Elementy głównego ekranu połączenia:
- Galeria multimediów: główny etap, na którym są pokazywani uczestnicy. Jeśli uczestnik ma włączoną kamerę, ich kanał wideo jest wyświetlany tutaj. Każdy uczestnik ma osobny kafelek, na którym wyświetlana jest jego nazwa oraz strumień wideo (jeśli jest dostępny). Galeria obsługuje wielu uczestników i jest aktualizowana, gdy uczestnicy są dodawani do połączenia lub z niego usuwani.
- Pasek akcji: tutaj znajdują się główne elementy sterujące połączeniem. Te kontrolki umożliwiają włączenie/wyłączenie wideo i mikrofonu, udostępnienie ekranu i opuszczenie połączenia.
Poniżej znajdziesz więcej informacji o wymaganiach wstępnych i krokach potrzebnych do skonfigurowania przykładu.
Wymagania wstępne
- Konto platformy Azure z aktywną subskrypcją. Aby uzyskać szczegółowe informacje, zobacz Tworzenie bezpłatnego konta.
- Komputer Mac z zainstalowanym środowiskiem Xcode oraz ważnym certyfikatem deweloperskim zainstalowanym w Keychain.
- Zasób usług Azure Communication Services. Aby uzyskać szczegółowe informacje, zobacz Tworzenie zasobu usług Azure Communication Services.
- Funkcja platformy Azure z uruchomionym punktem końcowym uwierzytelniania w celu pobrania tokenów dostępu.
Uruchamianie przykładu lokalnie
Przykład wywołania grupy można uruchomić lokalnie przy użyciu środowiska XCode. Deweloperzy mogą testować aplikację przy użyciu urządzenia fizycznego lub emulatora.
Przed uruchomieniem przykładu po raz pierwszy
- Zainstaluj zależności, uruchamiając polecenie
pod install. - Otwórz
AzureCalling.xcworkspaceplik w programie XCode. - Utwórz plik tekstowy w katalogu głównym o nazwie
AppSettings.xcconfigi ustaw wartość:communicationTokenFetchUrl = <your authentication endpoint, without the https:// component>
Uruchom przykład
Skompiluj i uruchom przykład w środowisku XCode przy użyciu obiektu docelowego AzureCalling w wybranym symulatorze lub urządzeniu.
(Opcjonalnie) Zabezpieczanie punktu końcowego uwierzytelniania
W celach demonstracyjnych ten przykład domyślnie używa publicznie dostępnego punktu końcowego do pobrania tokenu dostępu usług Azure Communication Services. W przypadku scenariuszy produkcyjnych zalecamy korzystanie z własnego, zabezpieczonego punktu końcowego do udostępniania własnych tokenów.
Po dodatkowej konfiguracji ten przykład umożliwia łączenie się z punktem końcowym chronionym przez Microsoft Entra ID (Microsoft Entra ID), dzięki czemu logowanie użytkownika jest wymagane, aby aplikacja mogła pobrać token dostępu usługi Azure Communication Services. Zobacz poniższe kroki:
- Włącz uwierzytelnianie microsoft Entra w aplikacji.
- Przejdź do strony Przegląd swojej zarejestrowanej aplikacji w obszarze Rejestracje aplikacji w Microsoft Entra. Zanotuj element
Application (client) ID, ,Directory (tenant) IDApplication ID URI
-
AppSettings.xcconfigUtwórz plik w katalogu głównym, jeśli jeszcze nie istnieje i dodaj wartości:communicationTokenFetchUrl = <Application ID URI, without the https:// component> aadClientId = <Application (client) ID> aadTenantId = <Directory (tenant) ID>
Czyszczenie zasobów
Jeśli chcesz wyczyścić i usunąć subskrypcję usług Komunikacyjnych, możesz usunąć zasób lub grupę zasobów. Usunięcie grupy zasobów powoduje również usunięcie wszelkich innych skojarzonych z nią zasobów. Dowiedz się więcej o czyszczeniu zasobów.
Następne kroki
Aby uzyskać więcej informacji, zobacz następujące artykuły:
- Zapoznaj się z zestawem SDK do wywołań
- Dowiedz się więcej o tym, jak działa dzwonienie
Materiały uzupełniające
- Azure Communication GitHub — więcej przykładów i informacji na oficjalnej stronie usługi GitHub
- Przykłady — znajdź więcej przykładów i innych materiałów przykładowych na naszej stronie z przeglądem przykładów.
- Funkcje połączeń usługi Azure Communication — aby dowiedzieć się więcej o zestawie SDK wywołań Azure Communication dla systemu iOS —Azure Communication iOS Calling SDK
Przykład Group Calling Hero Sample for Android w usłudze Azure Communication Services pokazuje, jak za pomocą zestawu SDK wywoływania usługi Communication Services dla systemu Android można utworzyć obsługę połączeń grupowych obejmującą połączenia głosowe i wideo. W tym przykładowym przewodniku Szybki start dowiesz się, jak skonfigurować i uruchomić przykład. Przedstawiono omówienie przykładu dla lepszego zrozumienia.
Pobieranie kodu
Znajdź projekt dla tego przykładu w witrynie GitHub.
Omówienie
Ten przykład to natywna aplikacja na system Android, która używa biblioteki klienckiej interfejsu użytkownika systemu Android usługi Azure Communication Services Android UI client library do tworzenia obsługi połączeń obejmującej zarówno połączenia głosowe, jak i wideo. Aplikacja używa składnika po stronie serwera do aprowizowania tokenów dostępu, które są następnie używane do inicjowania zestawu SDK usług Azure Communication Services. Aby skonfigurować ten składnik po stronie serwera, możesz skorzystać z samouczka Zaufana usługa z Azure Functions.
Oto jak wygląda przykład:
Po naciśnięciu przycisku "Rozpocznij nowe wywołanie" aplikacja systemu Android wyświetli monit o wprowadzenie nazwy wyświetlanej do użycia dla wywołania.
Po naciśnięciu przycisku "Dalej" na stronie "Rozpocznij połączenie" możesz udostępnić identyfikator połączenia grupowego.
Aplikacja umożliwia dołączenie do istniejącego połączenia w usłudze Azure Communication Services przez podanie identyfikatora istniejącego połączenia lub linku identyfikatora spotkania w usłudze Microsoft Teams oraz nazwy wyświetlanej.
Po dołączeniu do rozmowy pojawi się monit o przyznanie aplikacji dostępu do kamery i mikrofonu, jeśli aplikacja nie ma jeszcze odpowiednich uprawnień. Zobaczysz główny ekran połączenia, w którym znajduje się podstawowy interfejs obsługi połączenia.
Elementy głównego ekranu połączenia:
- Galeria multimediów: główny etap, na którym są pokazywani uczestnicy. Jeśli uczestnik ma włączoną kamerę, ich kanał wideo jest wyświetlany tutaj. Każdy uczestnik ma osobny kafelek, na którym wyświetlana jest jego nazwa oraz strumień wideo (jeśli jest dostępny). Galeria obsługuje wielu uczestników i jest aktualizowana, gdy uczestnicy są dodawani do połączenia lub z niego usuwani.
- Pasek akcji: tutaj znajdują się główne elementy sterujące połączeniem. Te kontrolki umożliwiają włączenie/wyłączenie wideo i mikrofonu, udostępnienie ekranu i opuszczenie połączenia.
Poniżej znajdziesz więcej informacji o wymaganiach wstępnych i krokach potrzebnych do skonfigurowania przykładu.
Wymagania wstępne
- Konto platformy Azure z aktywną subskrypcją. Aby uzyskać szczegółowe informacje, zobacz Tworzenie bezpłatnego konta.
- Program Android Studio uruchomiony na komputerze
- Zasób usług Azure Communication Services. Aby uzyskać szczegółowe informacje, zobacz Tworzenie zasobu usług Azure Communication Services.
- Funkcja platformy Azure z uruchomionym punktem końcowym uwierzytelniania w celu pobrania tokenów dostępu.
Uruchamianie przykładu lokalnie
Przykład wywołania grupy można uruchamiać lokalnie przy użyciu programu Android Studio. Deweloperzy mogą testować aplikację przy użyciu urządzenia fizycznego lub emulatora.
Przed uruchomieniem przykładu po raz pierwszy
- Otwórz program Android Studio i wybierz pozycję
Open an Existing Project - Otwórz folder
AzureCallingwewnątrz pobranego wydania dla przykładu. - Rozwiń app/assets, aby zaktualizować
appSettings.properties. Ustaw wartość kluczacommunicationTokenFetchUrljako adres URL punktu końcowego uwierzytelniania skonfigurowanego jako wymaganie wstępne.
Uruchom przykład
Skompiluj i uruchom przykład w programie Android Studio.
(Opcjonalnie) Zabezpieczanie punktu końcowego uwierzytelniania
W celach demonstracyjnych ten przykład domyślnie używa publicznie dostępnego punktu końcowego do pobrania tokenu usług Azure Communication Services. W przypadku scenariuszy produkcyjnych zalecamy korzystanie z własnego, zabezpieczonego punktu końcowego do udostępniania własnych tokenów.
Po dodatkowej konfiguracji ten przykład umożliwia połączenie z punktem końcowym chronionym przez Microsoft Entra ID (Microsoft Entra ID), dzięki czemu logowanie użytkownika jest wymagane, aby aplikacja mogła pobrać token usługi Azure Communication Services. Zobacz poniższe kroki:
Włącz uwierzytelnianie microsoft Entra w aplikacji.
Przejdź do strony Przegląd swojej zarejestrowanej aplikacji w obszarze Rejestracje aplikacji w Microsoft Entra. Zanotuj wartości
Package name, ,Signature hashMSAL Configuration.
Edytuj
AzureCalling/app/src/main/res/raw/auth_config_single_account.jsoni ustawisAADAuthEnabled, aby włączyć Microsoft Entra ID.Edytuj
AndroidManifest.xmli ustaw wartośćandroid:pathskrótu sygnatury magazynu kluczy. (Opcjonalnie. Bieżąca wartość używa skrótu z pakietu debug.keystore. Jeśli jest używany inny magazyn kluczy, należy go zaktualizować).<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>Skopiuj konfigurację biblioteki MSAL dla systemu Android z witryny Azure Portal i wklej ją do
AzureCalling/app/src/main/res/raw/auth_config_single_account.json. Uwzględnij "account_mode": "SINGLE"{ "client_id": "", "authorization_user_agent": "DEFAULT", "redirect_uri": "", "account_mode" : "SINGLE", "authorities": [ { "type": "AAD", "audience": { "type": "AzureADMyOrg", "tenant_id": "" } } ] }Edytuj
AzureCalling/app/src/main/res/raw/auth_config_single_account.jsoni ustaw wartość kluczacommunicationTokenFetchUrljako adres URL bezpiecznego punktu końcowego uwierzytelniania.Edytuj
AzureCalling/app/src/main/res/raw/auth_config_single_account.jsoni ustaw wartość kluczaaadScopeszAzure Active DirectoryExpose an APIzakresówUstaw wartość
graphURLwAzureCalling/app/assets/appSettings.propertiesjako punkt końcowy interfejsu interfejs Graph API do pobierania informacji o użytkowniku.Edytuj
AzureCalling/app/src/main/assets/appSettings.propertiesi ustaw wartość kluczatenant, aby włączyć logowanie dyskretne, aby użytkownik nie musiał być ponownie uwierzytelniany i ponownie podczas ponownego uruchamiania aplikacji.
Czyszczenie zasobów
Jeśli chcesz wyczyścić i usunąć subskrypcję usług Komunikacyjnych, możesz usunąć zasób lub grupę zasobów. Usunięcie grupy zasobów powoduje również usunięcie wszelkich innych skojarzonych z nią zasobów. Dowiedz się więcej o czyszczeniu zasobów.
Następne kroki
Aby uzyskać więcej informacji, zobacz następujące artykuły:
- Zapoznaj się z zestawem SDK do wywołań
- Dowiedz się więcej o tym, jak działa dzwonienie
Materiały uzupełniające
- Azure Communication GitHub — więcej przykładów i informacji na oficjalnej stronie usługi GitHub
- Przykłady — znajdź więcej przykładów i innych materiałów przykładowych na naszej stronie z przeglądem przykładów.
- Funkcje wywoływania usługi Azure Communication — aby dowiedzieć się więcej o zestawie SDK wywoływania dla systemu Android — Zestaw SDK wywoływania usługi Azure Communication dla systemu Android
Przykład Group Calling Hero Sample dla systemu Windows w usłudze Azure Communication Services pokazuje, jak za pomocą zestawu SDK wywołań usługi Communication Services dla systemu Windows można utworzyć obsługę połączeń grupowych obejmujących głos i wideo. Z tego przykładu dowiesz się, jak skonfigurować i uruchomić przykład. Przedstawiono omówienie przykładu dla lepszego zrozumienia.
W tym przewodniku Szybki start dowiesz się, jak rozpocząć rozmowę wideo 1:1 przy użyciu zestawu SDK do wywołań usługi Azure Communication Services dla systemu Windows.
Przykładowy kod platformy UWP
Wymagania wstępne
Do wykonania kroków tego samouczka niezbędne jest spełnienie następujących wymagań wstępnych:
Konto platformy Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
Zainstaluj program Visual Studio 2022 z obciążeniem programistycznym Platforma uniwersalna systemu Windows.
Wdrożony zasób usług komunikacyjnych. Utwórz zasób usług komunikacyjnych. Musisz zanotować parametry połączenia na potrzeby tego przewodnika Szybki start.
Token dostępu użytkownika dla usługi Azure Communication Service. Możesz również użyć Azure CLI i uruchomić polecenie, używając swojego ciągu połączenia, aby utworzyć użytkownika i token dostępu.
az communication identity token issue --scope voip --connection-string "yourConnectionString"Aby uzyskać szczegółowe informacje, zobacz Tworzenie tokenów dostępu za pomocą interfejsu wiersza polecenia platformy Azure i zarządzanie nimi.
Konfigurowanie
Tworzenie projektu
W programie Visual Studio utwórz nowy projekt przy użyciu szablonu Pusta aplikacja (Uniwersalna platforma systemu Windows), aby skonfigurować jednostronicową aplikację dla Uniwersalnej platformy systemu Windows (UWP).
Instalowanie pakietu
Kliknij projekt prawym przyciskiem myszy i przejdź do Manage Nuget Packages, aby zainstalować Azure.Communication.Calling.WindowsClientwersję 1.2.0-beta.1 lub nowszą wersję. Upewnij się, że opcja Include Preleased jest zaznaczona.
Żądanie dostępu
Przejdź do Package.appxmanifest i kliknij Capabilities.
Zaznacz Internet (Client & Server), aby uzyskać przychodzący i wychodzący dostęp do Internetu.
Zaznacz Microphone, aby uzyskać dostęp do strumienia audio z mikrofonu.
Zaznacz WebCam, aby uzyskać dostęp do aparatu urządzenia.
Dodaj następujący kod do pliku Package.appxmanifest , klikając prawym przyciskiem myszy i wybierając polecenie Wyświetl kod.
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
Konfigurowanie struktury aplikacji
Musimy skonfigurować podstawowy układ, aby dołączyć naszą logikę. Aby wykonać połączenie wychodzące, potrzebujemy elementu TextBox, aby podać identyfikator użytkownika odbiorcy. Potrzebujemy również przycisku Start Call i przycisku Hang Up.
Musimy również wyświetlić podgląd lokalnego wideo i renderować zdalne wideo innego uczestnika. Potrzebujemy więc dwóch elementów do wyświetlania strumieni wideo.
MainPage.xaml Otwórz projekt i zastąp zawartość następującą implementacją.
<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>
Otwórz do App.xaml.cs (kliknij prawym przyciskiem myszy i wybierz polecenie Wyświetl kod) i dodaj ten wiersz do góry:
using CallingQuickstart;
Otwórz MainPage.xaml.cs (kliknij prawym przyciskiem myszy i wybierz opcję „Wyświetl kod”) i zastąp zawartość następującą implementacją:
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
}
}
}
Model obiektów
Następujące klasy i interfejsy obsługują niektóre główne funkcje zestawu AZURE Communication Services Calling SDK:
| Nazwa/nazwisko | Opis |
|---|---|
CallClient |
CallClient to główny punkt wejścia do biblioteki klienta Calling. |
CallAgent |
Element CallAgent służy do rozpoczynania połączeń i dołączania do nich. |
CommunicationCall |
CommunicationCall służy do zarządzania wykonanymi lub połączonymi połączeniami. |
CallTokenCredential |
Element CallTokenCredential jest używany jako poświadczenie tokenu w celu utworzenia wystąpienia elementu CallAgent. |
CommunicationUserIdentifier |
Element CommunicationUserIdentifier służy do reprezentowania tożsamości użytkownika, która może być jedną z następujących opcji: CommunicationUserIdentifier, PhoneNumberIdentifier lub CallingApplication. |
Uwierzytelnianie użytkownika
Aby zainicjować element CallAgent, potrzebujesz tokenu dostępu użytkownika. Zazwyczaj ten token jest generowany na podstawie usługi z uwierzytelnianiem specyficznym dla aplikacji. Aby uzyskać więcej informacji na temat tokenów dostępu użytkowników, zapoznaj się z przewodnikiem Tokeny dostępu użytkowników.
W przewodniku Szybki start zastąp <AUTHENTICATION_TOKEN> tokenem dostępu użytkownika wygenerowanym dla zasobu Azure Communication Services.
Gdy masz już token, zainicjuj wystąpienie CallAgent, co umożliwi wykonywanie i odbieranie połączeń. Aby uzyskać dostęp do kamer na urządzeniu, musimy również uzyskać instancję Menedżera urządzeń.
Dodaj następujący kod do InitCallAgentAndDeviceManagerAsync funkcji .
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
}
}
Rozpoczynanie połączenia za pomocą wideo
Dodaj implementację do elementu CallButton_Click, aby rozpocząć połączenie wideo. Musimy wyenumerować kamery przy użyciu instancji Menedżera urządzeń i utworzyć LocalOutgoingVideoStream. Musimy ustawić VideoOptions za pomocą LocalVideoStream i przekazać go za pomocą startCallOptions, aby ustawić początkowe opcje dla wywołania. Dołączając LocalOutgoingVideoStream do pliku MediaElement, możemy zobaczyć podgląd lokalnego wideo.
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;
}
Dodaj metody rozpoczynania lub dołączania do różnych typów połączeń (połączenie 1:1 w usłudze Azure Communication Services, połączenie telefoniczne 1:1, połączenie grupowe w usłudze Azure Communication Services, dołączenie do spotkania w aplikacji Teams itp.).
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 } }
};
}
Dodaj kod, aby utworzyć element LocalVideoStream w zależności od wybranej kamery w metodzie CameraList_SelectionChanged .
var selectedCamera = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamera);
var localUri = await cameraStream.StartPreviewAsync();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
LocalVideo.Source = MediaSource.CreateFromUri(localUri);
});
if (call != null)
{
await call?.StartVideoAsync(cameraStream);
}
Akceptowanie połączenia przychodzącego
Dodaj implementację do elementu OnIncomingCallAsync, aby odebrać połączenie przychodzące z wideo, przekaż LocalVideoStream do acceptCallOptions.
var incomingCall = args.IncomingCall;
var acceptCallOptions = new AcceptCallOptions() {
IncomingVideoOptions = new IncomingVideoOptions()
{
IncomingVideoStreamKind = VideoStreamKind.RemoteIncoming
}
};
_ = await incomingCall.AcceptAsync(acceptCallOptions);
Zdalni uczestnicy i zdalne strumienie wideo
Wszyscy uczestnicy zdalni są dostępni w kolekcji RemoteParticipants w wystąpieniu wywołania. Po nawiązaniu połączenia (CallState.Connected) możemy uzyskać dostęp do zdalnych uczestników połączenia i obsługiwać zdalne strumienie wideo.
Uwaga
Gdy użytkownik dołącza do połączenia, może uzyskać dostęp do aktualnych uczestników zdalnych za pośrednictwem kolekcji RemoteParticipants. Zdarzenie RemoteParticipantsUpdated nie zostanie wywołane dla tych istniejących uczestników. To zdarzenie zostanie wywołane tylko wtedy, gdy uczestnik zdalny dołączy do połączenia lub je opuści, podczas gdy użytkownik już uczestniczy w połączeniu.
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;
}
}
Renderowanie zdalnych materiałów wideo
Dla każdego zdalnego strumienia wideo dołącz go do elementu 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();
});
}
}
Aktualizacja stanu wywołania
Musimy wyczyścić renderery wideo po zakończeniu połączenia i obsłużyć przypadek, gdy zdalni uczestnicy początkowo dołączają do połączenia.
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;
}
}
Zakończ połączenie
Zakończ bieżące połączenie po kliknięciu przycisku Hang Up. Dodaj implementację do metody HangupButton_Click, aby zakończyć połączenie za pomocą utworzonego wcześniej obiektu callAgent oraz usunąć programy obsługi zdarzeń aktualizacji uczestników i zmian stanu połączenia.
var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
try
{
await call.HangUpAsync(new HangUpOptions() { ForEveryone = true });
}
catch(Exception ex)
{
}
}
Uruchamianie kodu
Możesz skompilować i uruchomić kod w programie Visual Studio. W przypadku platform rozwiązań obsługujemy ARM64, x64 i x86.
Możesz wykonać połączenie wideo, podając identyfikator użytkownika w polu tekstowym i klikając przycisk Start Call.
Uwaga: wywołanie 8:echo123 zatrzymuje strumień wideo, ponieważ bot echo nie obsługuje przesyłania strumieniowego wideo.
Aby uzyskać więcej informacji na temat identyfikatorów użytkowników (tożsamości), zapoznaj się z przewodnikiem Tokeny dostępu użytkowników.
Przykładowy kod WinUI 3
Wymagania wstępne
Do wykonania kroków tego samouczka niezbędne jest spełnienie następujących wymagań wstępnych:
Konto platformy Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
Zainstaluj programy Visual Studio 2022 i Zestaw SDK do aplikacji systemu Windows w wersji 1.2 (wersja zapoznawcza 2).
Podstawowa wiedza na temat tworzenia aplikacji WinUI 3. Utwórz swój pierwszy projekt WinUI 3 (Zestaw SDK do aplikacji systemu Windows) to dobry zasób na początek.
Wdrożony zasób usług komunikacyjnych. Utwórz zasób usług komunikacyjnych. Musisz zanotować parametry połączenia na potrzeby tego przewodnika Szybki start.
Token dostępu użytkownika dla usługi Azure Communication Service. Możesz również użyć Azure CLI i uruchomić polecenie, używając swojego ciągu połączenia, aby utworzyć użytkownika i token dostępu.
az communication identity token issue --scope voip --connection-string "yourConnectionString"Aby uzyskać szczegółowe informacje, zobacz Tworzenie tokenów dostępu za pomocą interfejsu wiersza polecenia platformy Azure i zarządzanie nimi.
Konfigurowanie
Tworzenie projektu
W programie Visual Studio utwórz nowy projekt przy użyciu szablonu Blank App, Packaged (WinUI 3 in Desktop), aby skonfigurować jednostronicową aplikację WinUI 3.
Instalowanie pakietu
Kliknij projekt prawym przyciskiem myszy i przejdź do Manage Nuget Packages, aby zainstalować Azure.Communication.Calling.WindowsClientwersję 1.0.0 lub nowszą. Upewnij się, że opcja Include Preleased jest zaznaczona.
Żądanie dostępu
Dodaj następujący kod do pliku app.manifest:
<file name="RtmMvrMf.dll">
<activatableClass name="VideoN.VideoSchemeHandler" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>
Konfigurowanie struktury aplikacji
Musimy skonfigurować podstawowy układ, aby dołączyć naszą logikę. Aby wykonać połączenie wychodzące, potrzebujemy elementu TextBox, aby podać identyfikator użytkownika odbiorcy. Potrzebujemy również przycisku Start Call i przycisku Hang Up.
Musimy również wyświetlić podgląd lokalnego wideo i renderować zdalne wideo innego uczestnika. Potrzebujemy więc dwóch elementów do wyświetlania strumieni wideo.
MainWindow.xaml Otwórz projekt i zastąp zawartość następującą implementacją.
<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>
Otwórz do App.xaml.cs (kliknij prawym przyciskiem myszy i wybierz polecenie Wyświetl kod) i dodaj ten wiersz do góry:
using CallingQuickstart;
Otwórz MainWindow.xaml.cs (kliknij prawym przyciskiem myszy i wybierz opcję „Wyświetl kod”) i zastąp zawartość następującą implementacją:
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();
});
}
}
}
Model obiektów
Następujące klasy i interfejsy obsługują niektóre główne funkcje zestawu AZURE Communication Services Calling SDK:
| Nazwa/nazwisko | Opis |
|---|---|
CallClient |
CallClient to główny punkt wejścia do biblioteki klienta Calling. |
CallAgent |
Element CallAgent służy do rozpoczynania połączeń i dołączania do nich. |
CommunicationCall |
CommunicationCall służy do zarządzania wykonanymi lub połączonymi połączeniami. |
CallTokenCredential |
Element CallTokenCredential jest używany jako poświadczenie tokenu w celu utworzenia wystąpienia elementu CallAgent. |
CommunicationUserIdentifier |
Element CommunicationUserIdentifier służy do reprezentowania tożsamości użytkownika, która może być jedną z następujących opcji: CommunicationUserIdentifier, PhoneNumberIdentifier lub CallingApplication. |
Uwierzytelnianie użytkownika
Aby zainicjować element CallAgent, potrzebujesz tokenu dostępu użytkownika. Zazwyczaj ten token jest generowany na podstawie usługi z uwierzytelnianiem specyficznym dla aplikacji. Aby uzyskać więcej informacji na temat tokenów dostępu użytkowników, zapoznaj się z przewodnikiem Tokeny dostępu użytkowników.
W przewodniku Szybki start zastąp <AUTHENTICATION_TOKEN> tokenem dostępu użytkownika wygenerowanym dla zasobu Azure Communication Services.
Gdy masz już token, zainicjuj nim instancję CallAgent, co umożliwi nam wykonywanie i odbieranie połączeń. Aby uzyskać dostęp do kamer na urządzeniu, musimy również uzyskać instancję Menedżera urządzeń.
Dodaj następujący kod do InitCallAgentAndDeviceManagerAsync funkcji .
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;
Rozpoczynanie połączenia za pomocą wideo
Dodaj implementację do elementu CallButton_Click, aby rozpocząć połączenie wideo. Musimy wyenumerować kamery przy użyciu instancji Menedżera urządzeń i utworzyć LocalVideoStream. Musimy ustawić VideoOptions za pomocą LocalVideoStream i przekazać go za pomocą startCallOptions, aby ustawić początkowe opcje dla wywołania. Dołączając LocalVideoStream do pliku MediaPlayerElement, możemy zobaczyć podgląd lokalnego wideo.
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;
Akceptowanie połączenia przychodzącego
Dodaj implementację do elementu Agent_OnIncomingCallAsync, aby odebrać połączenie przychodzące z wideo, przekaż LocalVideoStream do 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);
Zdalni uczestnicy i zdalne strumienie wideo
Wszyscy uczestnicy zdalni są dostępni w kolekcji RemoteParticipants w wystąpieniu wywołania. Po nawiązaniu połączenia możemy uzyskać dostęp do zdalnych uczestników połączenia i obsłużyć zdalne strumienie wideo.
Uwaga
Gdy użytkownik dołącza do połączenia, może uzyskać dostęp do aktualnych uczestników zdalnych za pośrednictwem kolekcji RemoteParticipants. Zdarzenie OnRemoteParticipantsUpdated nie zostanie wywołane dla tych istniejących uczestników. To zdarzenie zostanie wywołane tylko wtedy, gdy uczestnik zdalny dołączy do połączenia lub je opuści, podczas gdy użytkownik już uczestniczy w połączeniu.
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);
}
}
Renderowanie zdalnych materiałów wideo
Dla każdego zdalnego strumienia wideo dołącz go do elementu 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();
});
}
}
Aktualizacja stanu wywołania
Musimy wyczyścić renderery wideo po zakończeniu połączenia i obsłużyć przypadek, gdy zdalni uczestnicy początkowo dołączają do połączenia.
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;
}
}
Zakończ połączenie
Zakończ bieżące połączenie po kliknięciu przycisku Hang Up. Dodaj implementację do metody HangupButton_Click, aby zakończyć połączenie za pomocą utworzonego wcześniej obiektu callAgent oraz usunąć programy obsługi zdarzeń aktualizacji uczestników i zmian stanu połączenia.
this.call.OnRemoteParticipantsUpdated -= Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged -= Call_OnStateChangedAsync;
await this.call.HangUpAsync(new HangUpOptions());
Uruchamianie kodu
Możesz skompilować i uruchomić kod w programie Visual Studio. W przypadku platform rozwiązań obsługujemy ARM64, x64 i x86.
Możesz wykonać połączenie wideo, podając identyfikator użytkownika w polu tekstowym i klikając przycisk Start Call.
Uwaga: wywołanie 8:echo123 zatrzymuje strumień wideo, ponieważ bot echo nie obsługuje przesyłania strumieniowego wideo.
Aby uzyskać więcej informacji na temat identyfikatorów użytkowników (tożsamości), zapoznaj się z przewodnikiem Tokeny dostępu użytkowników.