Wprowadzenie do przykładu elementu hero wywołującego
Przykład wywołania elementu Hero w usługach Azure Communication Services pokazuje, jak można użyć usług komunikacyjnych wywołujących internetowy zestaw SDK do utworzenia środowiska wywoływania grup.
W tym przykładowym przewodniku Szybki start dowiesz się, jak działa przykład przed uruchomieniem przykładu na maszynie lokalnej, a następnie wdrożymy przykład na platformie Azure przy użyciu własnych zasobów usług Azure Communication Services.
Pobieranie kodu
Znajdź projekt dla tego przykładu w witrynie GitHub. Wersja przykładu, która zawiera funkcje obecnie 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 wywołania. Zobaczysz główną kanwę wywołań, na której znajduje się podstawowe środowisko wywołujące.
Składniki głównego ekranu wywołującego:
- 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 pojedynczy kafelek, który pokazuje nazwę wyświetlaną i strumień wideo (jeśli istnieje)
- Nagłówek: w tym miejscu znajdują się podstawowe kontrolki wywołań, aby przełączać ustawienia i pasek boczny uczestnika, włączać i mieszać wideo i włączać/wyłączać, ekran udostępniania i opuszczać połączenie.
- Pasek boczny: jest to miejsce, w którym uczestnicy i informacje o ustawieniach są wyświetlane po przełączeniu za pomocą kontrolek 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 na temat wymagań wstępnych i kroków konfigurowania 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 zarejestrować zasób parametry połączenia 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.git
Pobierz z
Connection String
witryny Azure Portal 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 parametry połączenia, zobacz Create an Azure Communication Resources (Tworzenie zasobów komunikacji platformy Azure)
Po pobraniu
Connection String
pliku dodaj parametry połączenia do pliku samples/Server/appsetting.json. Wprowadź parametry połączenia w zmiennej:ResourceConnectionString
.Pobierz z
Endpoint string
witryny Azure Portal 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)
Po pobraniu pliku dodaj ciąg punktu końcowego
Endpoint String
do pliku samples/Server/appsetting.json . Wprowadzanie ciągu punktu końcowego w zmiennejEndpointUrl
Uruchamianie lokalne
Instalowanie zależności
npm run setup
Uruchamianie aplikacji wywołującej
npm run start
Spowoduje 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 setup
npm run build
npm 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 używaniem zestawu SDK wywołującego
- Dowiedz się więcej o tym, jak działa wywołanie
Materiały uzupełniające
- Przykłady — znajdź więcej przykładów i przykładów na naszej stronie przeglądu 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 wywołania hero w usługach Azure Communication Services dla systemu iOS pokazuje, w jaki sposób można użyć usług komunikacyjnych wywołujących zestaw SDK systemu iOS do tworzenia środowiska wywoływania grup obejmującego głos i wideo. W tym przykładowym przewodniku Szybki start dowiesz się, jak skonfigurować i uruchomić przykład. Omówienie przykładu jest dostępne dla kontekstu.
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 Trusted Service with Azure Functions (Zaufana usługa w usłudze Azure Functions ).
Oto jak wygląda przykład:
Po naciśnięciu przycisku "Uruchom nowe wywołanie" aplikacja systemu iOS wyświetli monit o wprowadzenie nazwy wyświetlanej do użycia dla wywołania.
Po naciśnięciu przycisku "Dalej" na ekranie "Rozpocznij połączenie" możesz udostępnić identyfikator grupy wywołania za pośrednictwem arkusza udziału systemu iOS.
Aplikacja umożliwia również dołączenie istniejącego wywołania usług Azure Communication Services przez określenie identyfikatora istniejącego wywołania lub linku identyfikatora zespołu.
Po dołączeniu do połączenia zostanie wyświetlony monit o udzielenie aplikacji uprawnień dostępu do aparatu i mikrofonu, jeśli jeszcze nie został autoryzowany. 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 wywołania zobaczysz główną kanwę wywołania, na której znajduje się podstawowe środowisko wywołania.
Składniki głównego ekranu wywołującego:
- 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 pojedynczy kafelek, który pokazuje swoją nazwę wyświetlaną i strumień wideo (jeśli istnieje). Galeria obsługuje wielu uczestników i jest aktualizowana po dodaniu lub usunięciu uczestników do połączenia.
- Pasek akcji: jest to miejsce, w którym znajdują się kontrolki wywołania podstawowego. Te kontrolki umożliwiają włączenie/wyłączenie wideo i mikrofonu, udostępnienie ekranu i opuszczenie połączenia.
Poniżej znajdziesz więcej informacji na temat wymagań wstępnych i kroków konfigurowania przykładu.
Wymagania wstępne
- Konto platformy Azure z aktywną subskrypcją. Aby uzyskać szczegółowe informacje, zobacz Tworzenie bezpłatnego konta.
- Komputer Mac z uruchomionym programem Xcode wraz z prawidłowym certyfikatem dewelopera zainstalowanym w pęku kluczy.
- 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.xcworkspace
plik w programie XCode. - Utwórz plik tekstowy w katalogu głównym o nazwie
AppSettings.xcconfig
i 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 użycie własnego zabezpieczonego punktu końcowego do aprowizowania własnych tokenów.
W przypadku dodatkowej konfiguracji ten przykład obsługuje nawiązywanie połączenia z chronionym punktem końcowym microsoft Entra ID (Microsoft Entra ID ), dzięki czemu logowanie użytkownika jest wymagane do pobrania tokenu dostępu usług Azure Communication Services. Zobacz poniższe kroki:
- Włącz uwierzytelnianie microsoft Entra w aplikacji.
- Przejdź do strony przeglądu zarejestrowanej aplikacji w obszarze Rejestracje aplikacji Firmy Microsoft. Zanotuj element
Application (client) ID
, ,Directory (tenant) ID
Application ID URI
AppSettings.xcconfig
Utwó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 używaniem zestawu SDK wywołującego
- Dowiedz się więcej o tym, jak działa wywołanie
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 przykładów na naszej stronie przeglądu przykładów.
- Funkcje połączeń komunikacyjnych platformy Azure — aby dowiedzieć się więcej na temat wywoływania zestawu SDK dla systemu iOS — Azure Communication iOS Calling SDK
Przykład wywołania hero w usługach Azure Communication Services dla systemu Android pokazuje, w jaki sposób można użyć usług komunikacyjnych wywołujących system Android SDK do tworzenia środowiska wywoływania grup obejmującego głos i wideo. W tym przykładowym przewodniku Szybki start dowiesz się, jak skonfigurować i uruchomić przykład. Omówienie przykładu jest dostępne dla kontekstu.
Pobieranie kodu
Znajdź projekt dla tego przykładu w witrynie GitHub.
Omówienie
Przykład jest natywną aplikacją systemu Android, która używa biblioteki klienta interfejsu użytkownika systemu Android usług Azure Communication Services 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 Trusted Service with Azure Functions (Zaufana usługa w usłudze 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 istniejącego wywołania usług Azure Communication Services przez określenie identyfikatora istniejącego połączenia lub identyfikatora spotkania zespołów i nazwy wyświetlanej.
Po dołączeniu do połączenia zostanie wyświetlony monit o udzielenie aplikacji uprawnień dostępu do aparatu i mikrofonu, jeśli jeszcze nie został autoryzowany. Zobaczysz główną kanwę wywołań, na której znajduje się podstawowe środowisko wywołujące.
Składniki głównego ekranu wywołującego:
- 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 pojedynczy kafelek, który pokazuje swoją nazwę wyświetlaną i strumień wideo (jeśli istnieje). Galeria obsługuje wielu uczestników i jest aktualizowana po dodaniu lub usunięciu uczestników do połączenia.
- Pasek akcji: jest to miejsce, w którym znajdują się kontrolki wywołania podstawowego. Te kontrolki umożliwiają włączenie/wyłączenie wideo i mikrofonu, udostępnienie ekranu i opuszczenie połączenia.
Poniżej znajdziesz więcej informacji na temat wymagań wstępnych i kroków konfigurowania 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
AzureCalling
Otwórz folder w wersji pobranej dla przykładu.- Rozwiń węzeł app/assets, aby zaktualizować
appSettings.properties
plik . Ustaw wartość kluczacommunicationTokenFetchUrl
jako 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 użycie własnego zabezpieczonego punktu końcowego do aprowizowania własnych tokenów.
W przypadku dodatkowej konfiguracji ten przykład obsługuje nawiązywanie połączenia z chronionym punktem końcowym microsoft Entra ID (Microsoft Entra ID ), dzięki czemu logowanie użytkownika jest wymagane do pobrania tokenu usług Azure Communication Services przez aplikację. Zobacz poniższe kroki:
Włącz uwierzytelnianie microsoft Entra w aplikacji.
Przejdź do strony przeglądu zarejestrowanej aplikacji w obszarze Rejestracje aplikacji Firmy Microsoft. Zanotuj wartości
Package name
, ,Signature hash
MSAL Configuration
.
Edytuj
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
i ustaw,isAADAuthEnabled
aby włączyć identyfikator Entra firmy Microsoft.Edytuj
AndroidManifest.xml
i ustaw wartośćandroid:path
skró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.json
i ustaw wartość kluczacommunicationTokenFetchUrl
jako adres URL bezpiecznego punktu końcowego uwierzytelniania.Edytuj
AzureCalling/app/src/main/res/raw/auth_config_single_account.json
i ustaw wartość kluczaaadScopes
zAzure Active Directory
Expose an API
zakresówUstaw wartość dla
graphURL
elementu wAzureCalling/app/assets/appSettings.properties
polu Punkt końcowy interfejsu API programu Graph, aby pobrać informacje o użytkowniku.Edytuj
AzureCalling/app/src/main/assets/appSettings.properties
i 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 używaniem zestawu SDK wywołującego
- Dowiedz się więcej o tym, jak działa wywołanie
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 przykładów na naszej stronie przeglądu przykładów.
- Funkcje wywoływania komunikacji platformy Azure — aby dowiedzieć się więcej na temat wywoływania zestawu Sdk systemu Android — Zestaw SDK wywoływania systemu Android w komunikacji platformy Azure
Przykład wywołania hero w usługach Azure Communication Services dla systemu Windows pokazuje, jak można użyć usług komunikacyjnych wywołujących windows SDK do tworzenia środowiska wywoływania grup obejmującego głos i wideo. Z tego przykładu dowiesz się, jak skonfigurować i uruchomić przykład. Omówienie przykładu jest dostępne dla kontekstu.
Z tego przewodnika Szybki start dowiesz się, jak uruchomić połączenie wideo 1:1 przy użyciu zestawu SDK wywołującego 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 pakietem roboczym programowania platforma uniwersalna systemu Windows.
Wdrożony zasób usług komunikacyjnych. Utwórz zasób usług komunikacyjnych. Musisz zarejestrować 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ć interfejsu wiersza polecenia platformy Azure i uruchomić polecenie za pomocą parametry 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 (uniwersalny system Windows), aby skonfigurować jednostronicową aplikację platforma uniwersalna systemu Windows (UWP).
Instalowanie pakietu
Kliknij prawym przyciskiem myszy projekt i przejdź do Manage Nuget Packages
witryny , aby zainstalować Azure.Communication.Calling.WindowsClient
wersję 1.2.0-beta.1 lub nowszą. Upewnij się, że zaznaczono opcję Uwzględnij wersję Preleased.
Żądanie dostępu
Przejdź do Package.appxmanifest
strony i kliknij pozycję Capabilities
.
Sprawdź Internet (Client & Server)
, czy uzyskać dostęp przychodzący i wychodzący do Internetu.
Sprawdź Microphone
, czy uzyskać dostęp do kanału audio mikrofonu.
Sprawdź WebCam
, czy chcesz 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 umieścić wywołanie wychodzące, musimy TextBox
podać identyfikator użytkownika wywoływanego. Potrzebujemy Start Call
również przycisku i Hang Up
przycisku.
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 (kliknij prawym przyciskiem MainPage.xaml.cs
myszy i wybierz pozycję 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 |
Jest CallClient to główny punkt wejścia do biblioteki wywołującej klienta. |
CallAgent |
Element służy do uruchamiania CallAgent i dołączania wywołań. |
CommunicationCall |
Służy CommunicationCall do zarządzania umieszczonymi lub sprzężonym wywołaniami. |
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 tym przewodniku Szybki start zastąp <AUTHENTICATION_TOKEN>
ciąg tokenem dostępu użytkownika wygenerowanym dla zasobu usługi Azure Communication Service.
Po utworzeniu tokenu zainicjuj CallAgent
wystąpienie, co umożliwi nam wykonywanie i odbieranie wywołań. Aby uzyskać dostęp do kamer na urządzeniu, musimy również uzyskać Menedżer urządzeń wystąpienie.
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 CallButton_Click
elementu , aby rozpocząć wywołanie za pomocą wideo. Musimy wyliczyć aparaty za pomocą wystąpienia menedżera urządzeń i skonstruować LocalOutgoingVideoStream
element . Musimy ustawić VideoOptions
element i LocalVideoStream
przekazać go za startCallOptions
pomocą , 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 uruchamiania lub dołączania do różnych typów połączeń (połączenie z usługami Azure Communication Services 1:1, połączenie telefoniczne 1:1, połączenie grupy usług Azure Communication Services, dołączanie do spotkania w usłudze 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 OnIncomingCallAsync
elementu , aby odpowiedzieć na połączenie przychodzące za pomocą wideo, przekaż element do acceptCallOptions
.LocalVideoStream
var incomingCall = args.IncomingCall;
var acceptCallOptions = new AcceptCallOptions() {
IncomingVideoOptions = new IncomingVideoOptions()
{
IncomingVideoStreamKind = VideoStreamKind.RemoteIncoming
}
};
_ = await incomingCall.AcceptAsync(acceptCallOptions);
Zdalny uczestnik i zdalne strumienie wideo
Wszyscy uczestnicy zdalni są dostępni za pośrednictwem kolekcji w wystąpieniu RemoteParticipants
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 wywołania, może uzyskać dostęp do bieżących uczestników zdalnych za pośrednictwem kolekcji RemoteParticipants
. Wydarzenie RemoteParticipantsUpdated
nie zostanie wyzwolne dla tych istniejących uczestników. To zdarzenie zostanie wyzwolone tylko wtedy, gdy uczestnik zdalny dołączy lub opuści połączenie, gdy użytkownik jest już w wywołaniu.
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 filmów wideo
Dla każdego zdalnego strumienia wideo dołącz go do .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ć programy renderujących wideo po rozłączeniu wywołania i obsłużyć przypadek, gdy uczestnicy zdalni początkowo dołączą do wywołania.
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;
}
}
Kończ połączenie
Zakończ bieżące wywołanie po kliknięciu Hang Up
przycisku. Dodaj implementację do HangupButton_Click, aby zakończyć wywołanie utworzonego przez nas agenta callAgent i usunąć aktualizację uczestnika i wywołać programy obsługi zdarzeń stanu.
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
platformy , x64
i x86
.
Możesz wykonać wychodzące połączenie wideo, podając identyfikator użytkownika w polu tekstowym i klikając Start Call
przycisk.
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 Windows App SDK w wersji 1.2 (wersja zapoznawcza 2).
Podstawowa wiedza na temat tworzenia aplikacji WinUI 3. Utwórz swój pierwszy projekt WinUI 3 (Windows App SDK) to dobry zasób na początek.
Wdrożony zasób usług komunikacyjnych. Utwórz zasób usług komunikacyjnych. Musisz zarejestrować 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ć interfejsu wiersza polecenia platformy Azure i uruchomić polecenie za pomocą parametry 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 prawym przyciskiem myszy projekt i przejdź do Manage Nuget Packages
witryny , aby zainstalować Azure.Communication.Calling.WindowsClient
wersję 1.0.0 lub wyższą. Upewnij się, że zaznaczono opcję Uwzględnij wersję Preleased.
Żą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 umieścić wywołanie wychodzące, musimy TextBox
podać identyfikator użytkownika wywoływanego. Potrzebujemy Start Call
również przycisku i Hang Up
przycisku.
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 (kliknij prawym przyciskiem MainWindow.xaml.cs
myszy i wybierz pozycję 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 |
Jest CallClient to główny punkt wejścia do biblioteki wywołującej klienta. |
CallAgent |
Element służy do uruchamiania CallAgent i dołączania wywołań. |
CommunicationCall |
Służy CommunicationCall do zarządzania umieszczonymi lub sprzężonym wywołaniami. |
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 tym przewodniku Szybki start zastąp <AUTHENTICATION_TOKEN>
ciąg tokenem dostępu użytkownika wygenerowanym dla zasobu usługi Azure Communication Service.
Po zainicjowaniu CallAgent
wystąpienia tokenu, co umożliwi nam wykonywanie i odbieranie wywołań. Aby uzyskać dostęp do kamer na urządzeniu, musimy również uzyskać Menedżer urządzeń wystąpienie.
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 CallButton_Click
elementu , aby rozpocząć wywołanie za pomocą wideo. Musimy wyliczyć aparaty za pomocą wystąpienia menedżera urządzeń i skonstruować LocalVideoStream
element . Musimy ustawić VideoOptions
element i LocalVideoStream
przekazać go za startCallOptions
pomocą , 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 Agent_OnIncomingCallAsync
elementu , aby odpowiedzieć na połączenie przychodzące za pomocą wideo, przekaż element do acceptCallOptions
.LocalVideoStream
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);
Zdalny uczestnik i zdalne strumienie wideo
Wszyscy uczestnicy zdalni są dostępni za pośrednictwem kolekcji w wystąpieniu RemoteParticipants
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 wywołania, może uzyskać dostęp do bieżących uczestników zdalnych za pośrednictwem kolekcji RemoteParticipants
. Wydarzenie OnRemoteParticipantsUpdated
nie zostanie wyzwolne dla tych istniejących uczestników. To zdarzenie zostanie wyzwolone tylko wtedy, gdy uczestnik zdalny dołączy lub opuści połączenie, gdy użytkownik jest już w wywołaniu.
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 filmów wideo
Dla każdego zdalnego strumienia wideo dołącz go do .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ć programy renderujących wideo po rozłączeniu wywołania i obsłużyć przypadek, gdy uczestnicy zdalni początkowo dołączą do wywołania.
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;
}
}
Kończ połączenie
Zakończ bieżące wywołanie po kliknięciu Hang Up
przycisku. Dodaj implementację do HangupButton_Click, aby zakończyć wywołanie utworzonego przez nas agenta callAgent i usunąć aktualizację uczestnika i wywołać programy obsługi zdarzeń stanu.
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
platformy , x64
i x86
.
Możesz wykonać wychodzące połączenie wideo, podając identyfikator użytkownika w polu tekstowym i klikając Start Call
przycisk.
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.