Megosztás a következőn keresztül:


Ismerkedés a hívó főhős mintával

Az Azure Communication Services csoporthívási főkiszolgálói mintája bemutatja, hogyan használható a Communication Services Calling Web SDK a csoporthívási élmény létrehozásához.

Ebben a rövid útmutatóban megtudhatja, hogyan működik a minta, mielőtt futtatnánk a mintát a helyi gépen, majd üzembe helyeznénk a mintát az Azure-ban saját Azure Communication Services-erőforrásaival.

Kód letöltése

A minta projektjének megkeresése a GitHubon. A minta egy olyan verziója, amely a nyilvános előzetes verzióban jelenleg elérhető funkciókat tartalmazza, például a Teams Interop és a Hívásrögzítés egy külön ágon található.

Üzembe helyezés az Azure-ban

Áttekintés

A minta ügyféloldali és kiszolgálóoldali alkalmazással is rendelkezik. Az ügyféloldali alkalmazás egy React/Redux webalkalmazás, amely a Microsoft Fluent felhasználói felületi keretrendszerét használja. Ez az alkalmazás kéréseket küld egy ASP.NET Core kiszolgálóoldali alkalmazásnak , amely segít az ügyféloldali alkalmazásnak az Azure-hoz való csatlakozásban.

A minta a következőképpen néz ki:

Képernyőkép a mintaalkalmazás kezdőlapjáról.

Amikor lenyomja a "Hívás indítása" gombot, a webalkalmazás lekéri a felhasználó hozzáférési jogkivonatát a kiszolgálóoldali alkalmazásból. Ez a jogkivonat ezután az ügyfélalkalmazás Azure Communication Serviceshez való csatlakoztatására szolgál. A jogkivonat lekérése után a rendszer kérni fogja, hogy adja meg a használni kívánt kamerát és mikrofont. Váltóvezérlőkkel letilthatja/engedélyezheti az eszközöket:

A mintaalkalmazás hívás előtti képernyőjét ábrázoló képernyőkép.

Miután konfigurálta a megjelenítendő nevet és az eszközöket, csatlakozhat a hívási munkamenethez. Látni fogja a fő hívási vásznon, ahol az alapvető hívási élmény él.

Képernyőkép a mintaalkalmazás főképernyőjén.

A fő hívóképernyő összetevői:

  • Médiatár: A fő szakasz, ahol a résztvevők láthatók. Ha egy résztvevőnek engedélyezve van a kamerája, a videó hírcsatornája itt látható. Minden résztvevő rendelkezik egy külön csempével, amely megjeleníti a megjelenítendő nevét és a videóstreamet (ha van ilyen)
  • Fejléc: Itt találhatók az elsődleges hívásvezérlők a beállítások és a résztvevők oldalsávjának váltásához, a videó be- és kikapcsolásához, a képernyő megosztásához és a hívás elhagyásához.
  • Oldalsáv: Itt jelennek meg a résztvevők és a beállítások adatai, amikor a fejléc vezérlőivel váltanak. Az összetevőt a jobb felső sarokban lévő X használatával lehet elvetni. A résztvevők oldalsávja megjeleníti a résztvevők listáját és egy hivatkozást, a amelyen további felhasználókat hívhat meg csevegésre. A beállítások oldalsávja lehetővé teszi a mikrofon- és kamerabeállítások konfigurálását.

Az alábbiakban további információt talál a minta beállításának előfeltételeiről és lépéseiről.

Előfeltételek

A minta első futtatása előtt

  1. Nyisson meg egy PowerShell-példányt, Windows Terminált, parancssort vagy azzal egyenértékű parancsot, és keresse meg azt a könyvtárat, amelybe a mintát klónozni szeretné.

    git clone https://github.com/Azure-Samples/communication-services-web-calling-hero.git
    
  2. Szerezze be az Connection String Azure Portalt vagy az Azure CLI-t.

    az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
    

    A kapcsolati sztring további információkért lásd: Azure Communication Resources létrehozása

  3. Miután megkapta a Connection Stringfájlt, adja hozzá a kapcsolati sztring a mintákhoz/kiszolgálóhoz/appsetting.json fájlhoz. Adja meg a kapcsolati sztring a következő változóban: ResourceConnectionString.

  4. Szerezze be az Endpoint string Azure Portalt vagy az Azure CLI-t.

    az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
    

    További információ a végponti sztringekről: Azure Communication Resources létrehozása

  5. A lekérés Endpoint Stringután adja hozzá a végponti sztringet a mintákhoz/kiszolgálóhoz/appsetting.json fájlhoz. Adja meg a végponti sztringet a változóban EndpointUrl

Helyi futtatás

  1. Függőségek telepítése

    npm run setup
    
  2. A hívó alkalmazás indítása

    npm run start
    

    Ezzel megnyílik egy ügyfélkiszolgáló a 3000-es porton, amely a webhelyfájlokat szolgálja ki, valamint egy api-kiszolgálót a 8080-es porton, amely olyan funkciókat hajt végre, mint a hívás résztvevőinek jogkivonatainak verése.

Hibaelhárítás

  • Az alkalmazás egy "Nem támogatott böngésző" képernyőt jelenít meg, de támogatott böngészőben vagyok.

    Ha az alkalmazást a localhosttól eltérő gazdagépnéven kézbesítik, akkor a forgalmat https-en keresztül kell kiszolgálnia, és nem http-en.

Közzététel az Azure platformon

  1. npm run setup
  2. npm run build
  3. npm run package
  4. Használja az Azure-bővítményt, és telepítse a Calling/Dist könyvtárat az app service-ben

Az erőforrások eltávolítása

Ha törölni és eltávolítani szeretne egy Communication Services-előfizetést, törölheti az erőforrást vagy az erőforráscsoportot. Az erőforráscsoport törlése a hozzá társított egyéb erőforrásokat is törli. További információ az erőforrások tisztításáról.

Következő lépések

További információért tekintse át az alábbi cikkeket:

További információ

  • Minták – További mintákat és példákat találhat a minták áttekintési oldalán.
  • Redux – Ügyféloldali állapotkezelés
  • FluentUI – Microsoft-alapú felhasználói felületi kódtár
  • React – Kódtár felhasználói felületek létrehozásához
  • ASP.NET Core – Keretrendszer webalkalmazások létrehozásához

Az iOS-hez készült Azure Communication Services csoporthívási fő minta bemutatja, hogyan használható az iOS-et hívó Kommunikációs szolgáltatások SDK egy hang- és videohívást tartalmazó csoporthívási felület létrehozásához. Ebben a rövid útmutatóban megtudhatja, hogyan állíthatja be és futtathatja a mintát. A rendszer áttekintést nyújt a mintáról a környezethez.

Kód letöltése

A minta projektjének megkeresése a GitHubon.

Áttekintés

A minta egy natív iOS-alkalmazás, amely az Azure Communication Services iOS SDK-jait használja a hang- és videohívást egyaránt tartalmazó hívási felület létrehozásához. Az alkalmazás kiszolgálóoldali összetevőt használ az Azure Communication Services SDK inicializálásához használt hozzáférési jogkivonatok kiépítéséhez. A kiszolgálóoldali összetevő konfigurálásához kövesse a megbízható szolgáltatást az Azure Functions oktatóanyagával.

A minta a következőképpen néz ki:

Képernyőkép a mintaalkalmazás kezdőlapjáról.

Amikor lenyomja az "Új hívás indítása" gombot, az iOS-alkalmazás kéri, hogy adja meg a megjelenítendő nevet a híváshoz.

A mintaalkalmazás hívás előtti képernyőjét ábrázoló képernyőkép.

Miután a "Hívás indítása" képernyőn a "Tovább" gombra koppintott, lehetősége van megosztani a hívás csoportazonosítóját az iOS megosztási lapján.

Képernyőkép a mintaalkalmazás megosztási csoportazonosító képernyőjét ábrázoló képernyőről.

Az alkalmazás lehetővé teszi egy meglévő Azure Communication Services-híváshoz való csatlakozást a meglévő hívás azonosítójának vagy teams-azonosító hivatkozásának megadásával.

Képernyőkép a mintaalkalmazás csatlakozáshívási képernyőjéről.

A híváshoz való csatlakozás után a rendszer kérni fogja, hogy adjon engedélyt az alkalmazásnak a kamerához és a mikrofonhoz való hozzáféréshez, ha még nincs engedélyezve. Ne feledje, hogy az AVFoundation-alapú alkalmazásokhoz hasonlóan a valódi hang- és videofunkciók csak valós hardveren érhetők el.

Miután konfigurálta a megjelenítendő nevet, és csatlakozott a híváshoz, látni fogja a fő hívási vásznon, ahol az alapvető hívási élmény él.

Képernyőkép a mintaalkalmazás főképernyőjén.

A fő hívóképernyő összetevői:

  • Médiatár: A fő szakasz, ahol a résztvevők láthatók. Ha egy résztvevőnek engedélyezve van a kamerája, a videó hírcsatornája itt látható. Minden résztvevő rendelkezik egy külön csempével, amely megjeleníti a megjelenítendő nevét és a videóstreamet (ha van ilyen). A katalógus több résztvevőt támogat, és akkor frissül, ha a résztvevőket hozzáadják vagy eltávolítják a hívásból.
  • Műveletsáv: Itt találhatók az elsődleges hívásvezérlők. Ezek a vezérlők lehetővé teszik a videó és a mikrofon be- és kikapcsolását, a képernyő megosztását és a hívás elhagyását.

Az alábbiakban további információkat talál a minta beállításának előfeltételeiről és lépéseiről.

Előfeltételek

  • Egy Azure-fiók, aktív előfizetéssel. További részletekért lásd : Fiók létrehozása ingyenesen.
  • Egy Xcode-ot futtató Mac gép, valamint egy érvényes fejlesztői tanúsítvány, amely telepítve van a kulcskarikába.
  • Egy Azure Communication Services-erőforrás. További részletekért lásd : Azure Communication Services-erőforrás létrehozása.
  • A hitelesítési végpontot futtató Azure-függvény hozzáférési jogkivonatok lekéréséhez.

Minta helyi futtatása

A csoporthívási minta helyileg futtatható az XCode használatával. A fejlesztők használhatják a fizikai eszközüket vagy egy emulátort az alkalmazás teszteléséhez.

A minta első futtatása előtt

  1. Telepítse a függőségeket a futtatással pod install.
  2. Megnyitás AzureCalling.xcworkspace az XCode-ban.
  3. Hozzon létre egy szövegfájlt a gyökérkönyvtárban, hívja meg AppSettings.xcconfig és állítsa be az értéket:
    communicationTokenFetchUrl = <your authentication endpoint, without the https:// component>
    

Minta futtatása

Hozza létre és futtassa a mintát az XCode-ban az AzureCalling-cél használatával a választott szimulátoron vagy eszközön.

(Nem kötelező) Hitelesítési végpont biztonságossá tétele

Bemutató célokra ez a minta alapértelmezés szerint egy nyilvánosan elérhető végpontot használ egy Azure Communication Services hozzáférési jogkivonat lekéréséhez. Éles helyzetekben javasoljuk, hogy saját biztonságos végpontot használjon saját jogkivonatok kiépítéséhez.

További konfigurációval ez a minta támogatja a Microsoft Entra ID (Microsoft Entra ID) által védett végponthoz való csatlakozást, hogy az alkalmazáshoz felhasználói bejelentkezés szükséges az Azure Communication Services hozzáférési jogkivonatának lekéréséhez. Lásd az alábbi lépéseket:

  1. Engedélyezze a Microsoft Entra-hitelesítést az alkalmazásban.
  2. Nyissa meg a regisztrált alkalmazás áttekintési oldalát a Microsoft Entra alkalmazásregisztrációk területén. Jegyezze fel a Application (client) ID, Directory (tenant) IDApplication ID URI

Microsoft Entra-konfiguráció az Azure Portalon.

  1. Hozzon létre egy AppSettings.xcconfig fájlt a gyökérben, ha még nincs jelen, és adja hozzá az értékeket:
    communicationTokenFetchUrl = <Application ID URI, without the https:// component>
    aadClientId = <Application (client) ID>
    aadTenantId = <Directory (tenant) ID>
    

Az erőforrások eltávolítása

Ha törölni és eltávolítani szeretne egy Communication Services-előfizetést, törölheti az erőforrást vagy az erőforráscsoportot. Az erőforráscsoport törlése a hozzá társított egyéb erőforrásokat is törli. További információ az erőforrások tisztításáról.

Következő lépések

További információért tekintse át az alábbi cikkeket:

További információ

Az Androidhoz készült Azure Communication Services csoporthívási fő minta bemutatja, hogyan használható az Android SDK-t hívó kommunikációs szolgáltatások egy hang- és videohívást tartalmazó csoporthívási felület létrehozásához. Ebben a rövid útmutatóban megtudhatja, hogyan állíthatja be és futtathatja a mintát. A rendszer áttekintést nyújt a mintáról a környezethez.

Kód letöltése

A minta projektjének megkeresése a GitHubon.

Áttekintés

A minta egy natív Android-alkalmazás, amely az Azure Communication Services Android felhasználói felületének ügyféloldali kódtárát használja a hang- és videohívást egyaránt tartalmazó hívófelület létrehozásához. Az alkalmazás kiszolgálóoldali összetevőt használ az Azure Communication Services SDK inicializálásához használt hozzáférési jogkivonatok kiépítéséhez. A kiszolgálóoldali összetevő konfigurálásához kövesse a megbízható szolgáltatást az Azure Functions oktatóanyagával.

A minta a következőképpen néz ki:

Képernyőkép a mintaalkalmazás kezdőlapjáról.

Amikor lenyomja az "Új hívás indítása" gombot, az Android-alkalmazás kéri, hogy adja meg a megjelenítendő nevet a híváshoz.

A mintaalkalmazás hívás előtti képernyőjét ábrázoló képernyőkép.

Miután a "Hívás indítása" lapon a "Tovább" gombra kattintott, lehetősége van megosztani a "Csoporthívás azonosítóját".

Képernyőkép a mintaalkalmazás megosztási csoport hívásazonosítójának képernyőéről.

Az alkalmazás lehetővé teszi egy meglévő Azure Communication Services-híváshoz való csatlakozást a meglévő hívás azonosítójának vagy a Teams-értekezletazonosító hivatkozásának megadásával és a megjelenítendő név megadásával.

Képernyőkép a mintaalkalmazás csatlakozáshívási képernyőjéről.

A híváshoz való csatlakozás után a rendszer kérni fogja, hogy adjon engedélyt az alkalmazásnak a kamerához és a mikrofonhoz való hozzáféréshez, ha még nincs engedélyezve. Megjelenik a fő hívásvásznon, ahol az alapvető hívási élmény él.

Képernyőkép a mintaalkalmazás főképernyőjén.

A fő hívóképernyő összetevői:

  • Médiatár: A fő szakasz, ahol a résztvevők láthatók. Ha egy résztvevőnek engedélyezve van a kamerája, a videó hírcsatornája itt látható. Minden résztvevő rendelkezik egy külön csempével, amely megjeleníti a megjelenítendő nevét és a videóstreamet (ha van ilyen). A katalógus több résztvevőt támogat, és akkor frissül, ha a résztvevőket hozzáadják vagy eltávolítják a hívásból.
  • Műveletsáv: Itt találhatók az elsődleges hívásvezérlők. Ezek a vezérlők lehetővé teszik a videó és a mikrofon be- és kikapcsolását, a képernyő megosztását és a hívás elhagyását.

Az alábbiakban további információkat talál a minta beállításának előfeltételeiről és lépéseiről.

Előfeltételek

Minta helyi futtatása

A csoporthívási minta helyileg futtatható az Android Studióval. A fejlesztők használhatják a fizikai eszközüket vagy egy emulátort az alkalmazás teszteléséhez.

A minta első futtatása előtt

  1. Nyissa meg az Android Studiót, és válassza a Open an Existing Project
  2. Nyissa meg a mappát a AzureCalling minta letöltött kiadásában.
  3. Bontsa ki az alkalmazást/objektumokat a frissítéshez appSettings.properties. Állítsa be a kulcs communicationTokenFetchUrl értékét az előfeltételként beállított hitelesítési végpont URL-címének.

Minta futtatása

Hozza létre és futtassa a mintát az Android Studióban.

(Nem kötelező) Hitelesítési végpont biztonságossá tétele

Bemutató célokra ez a minta alapértelmezés szerint egy nyilvánosan elérhető végpontot használ egy Azure Communication Services-jogkivonat lekéréséhez. Éles helyzetekben javasoljuk, hogy saját biztonságos végpontot használjon saját jogkivonatok kiépítéséhez.

További konfiguráció esetén ez a minta támogatja a Microsoft Entra ID (Microsoft Entra ID) által védett végponthoz való csatlakozást, hogy az alkalmazás felhasználói bejelentkezést igényeljen egy Azure Communication Services-jogkivonat lekéréséhez. Lásd az alábbi lépéseket:

  1. Engedélyezze a Microsoft Entra-hitelesítést az alkalmazásban.

  2. Nyissa meg a regisztrált alkalmazás áttekintési oldalát a Microsoft Entra alkalmazásregisztrációk területén. Jegyezze fel a Package name, Signature hash. MSAL Configutaion

Microsoft Entra-konfiguráció az Azure Portalon.

  1. Szerkessze AzureCalling/app/src/main/res/raw/auth_config_single_account.json és engedélyezze isAADAuthEnabled a Microsoft Entra-azonosítót.

  2. Szerkessze AndroidManifest.xml és állítsa be android:path a kulcstár-aláírás kivonatát. (Nem kötelező. Az aktuális érték a csomagolt debug.keystore kivonatát használja. Ha más kulcstárat használ, ezt frissíteni kell.)

    <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>
    
  3. Másolja az MSAL Android-konfigurációt az Azure Portalról, és illessze be a fájlba AzureCalling/app/src/main/res/raw/auth_config_single_account.json. "account_mode": "SINGLE"

       {
          "client_id": "",
          "authorization_user_agent": "DEFAULT",
          "redirect_uri": "",
          "account_mode" : "SINGLE",
          "authorities": [
             {
                "type": "AAD",
                "audience": {
                "type": "AzureADMyOrg",
                "tenant_id": ""
                }
             }
          ]
       }
    
  4. Szerkessze AzureCalling/app/src/main/res/raw/auth_config_single_account.json és állítsa be a kulcs communicationTokenFetchUrl értékét úgy, hogy a biztonságos hitelesítési végpont URL-címe legyen.

  5. A kulcs aadScopes értékének szerkesztése AzureCalling/app/src/main/res/raw/auth_config_single_account.json és beállítása hatókörökből Azure Active Directory Expose an API

  6. A felhasználói adatok beolvasásához graphURL állítsa be AzureCalling/app/assets/appSettings.properties a Be értéket Graph API-végpontként.

  7. Szerkessze AzureCalling/app/src/main/assets/appSettings.properties és állítsa be a kulcs tenant értékét a csendes bejelentkezés engedélyezéséhez, hogy a felhasználót ne kelljen újra és újra hitelesíteni az alkalmazás újraindítása közben.

Az erőforrások eltávolítása

Ha törölni és eltávolítani szeretne egy Communication Services-előfizetést, törölheti az erőforrást vagy az erőforráscsoportot. Az erőforráscsoport törlése a hozzá társított egyéb erőforrásokat is törli. További információ az erőforrások tisztításáról.

Következő lépések

További információért tekintse át az alábbi cikkeket:

További információ

A WindowsHoz készült Azure Communication Services csoporthívási fő minta bemutatja, hogyan használható a Kommunikációs szolgáltatások hívása Windows SDK-val egy hang- és videohívást tartalmazó csoporthívási felület létrehozásához. Ebben a mintában megtudhatja, hogyan állíthatja be és futtathatja a mintát. A rendszer áttekintést nyújt a mintáról a környezethez.

Ebben a rövid útmutatóban megtudhatja, hogyan indíthat 1:1-ás videohívást a Windowshoz készült Azure Communication Services Calling SDK használatával.

UWP-mintakód

Előfeltételek

Az oktatóanyag teljesítéséhez a következő előfeltételekre lesz szüksége:

  • Egy Azure-fiók, aktív előfizetéssel. Fiók ingyenes létrehozása.

  • Telepítse a Visual Studio 2022-t Univerzális Windows-platform fejlesztési számítási feladattal.

  • Üzembe helyezett Communication Services-erőforrás. Hozzon létre egy Communication Services-erőforrást. Ehhez a rövid útmutatóhoz rögzítenie kell a kapcsolati sztring.

  • Felhasználói hozzáférési jogkivonat az Azure Communication Service-hez. Az Azure CLI-t is használhatja, és futtathatja a parancsot a kapcsolati sztring egy felhasználó és egy hozzáférési jogkivonat létrehozásához.

    az communication identity token issue --scope voip --connection-string "yourConnectionString"
    

    További részletekért lásd: Hozzáférési jogkivonatok létrehozása és kezelése az Azure CLI használatával.

Beállítás

A projekt létrehozása

A Visual Studióban hozzon létre egy új projektet az Üres alkalmazás (Univerzális Windows) sablonnal egy egyoldalas Univerzális Windows-platform (UWP) alkalmazás beállításához.

Képernyőkép az Új UWP-projekt ablakról a Visual Studióban.

Telepítse a(z) csomagot

Kattintson a jobb gombbal a projektre, és nyissa meg az Manage Nuget Packages 1.2.0-beta.1 vagy a superior verzió telepítését Azure.Communication.Calling.WindowsClient . Győződjön meg arról, hogy az Előzetes belefoglalás jelölőnégyzet be van jelölve.

Hozzáférés kérése

Ugrás, Package.appxmanifest majd kattintson a gombra Capabilities. Ellenőrizze Internet (Client & Server) , hogy szeretne-e bejövő és kimenő hozzáférést szerezni az internethez. Ellenőrizze Microphone , hogy elérhető-e a mikrofon hangcsatornája. Ellenőrizze WebCam az eszköz kamerájának elérését.

Adja hozzá a következő kódot a Package.appxmanifest jobb gombbal a Kód megtekintése parancsra kattintva.

<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>

Az alkalmazás-keretrendszer beállítása

Egy alapszintű elrendezést kell konfigurálnunk a logikánk csatolásához. Kimenő hívás indításához meg kell TextBox adnia a hívó felhasználóazonosítóját. Egy gombra és egy Start Call gombra Hang Up is szükségünk van. A helyi videó előnézetét is meg kell tekintenünk, és el kell készítenünk a másik résztvevő távoli videóját. Tehát két elemre van szükségünk a videóstreamek megjelenítéséhez.

Nyissa meg a MainPage.xaml projektet, és cserélje le a tartalmat a következő megvalósításra.

<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>

Nyissa meg a következőt App.xaml.cs (kattintson a jobb gombbal, és válassza a Kód megtekintése lehetőséget), és adja hozzá ezt a sort a tetejére:

using CallingQuickstart;

Nyissa meg a MainPage.xaml.cs (jobb gombbal kattintva és válassza a Kód megtekintése) lehetőséget, és cserélje le a tartalmat a következő implementációra:

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
        }
    }
}

Objektummodell

A következő osztályok és felületek kezelik az Azure Communication Services Calling SDK néhány fő funkcióját:

Név Leírás
CallClient Ez CallClient a hívási ügyfélkódtár fő belépési pontja.
CallAgent Ez CallAgent a hívások indítására és csatlakoztatására szolgál.
CommunicationCall A CommunicationCall rendszer az elhelyezett vagy csatlakoztatott hívások kezelésére szolgál.
CallTokenCredential A CallTokenCredential rendszer a jogkivonat hitelesítő adataiként használja a példányosításhoz.CallAgent
CommunicationUserIdentifier A CommunicationUserIdentifier felhasználó identitásának ábrázolására szolgál, amely a következő lehetőségek egyike lehet: CommunicationUserIdentifiervagy PhoneNumberIdentifier CallingApplication.

Az ügyfél hitelesítése

A CallAgentfelhasználói hozzáférési jogkivonat inicializálásához felhasználói hozzáférési jogkivonatra van szükség. Ez a jogkivonat általában egy olyan szolgáltatásból jön létre, amely az alkalmazásra jellemző hitelesítéssel rendelkezik. A felhasználói hozzáférési jogkivonatokról további információt a Felhasználói hozzáférési jogkivonatok útmutatójában talál.

A rövid útmutatóban cserélje le <AUTHENTICATION_TOKEN> az Azure Communication Service-erőforráshoz létrehozott felhasználói hozzáférési jogkivonatot.

Miután rendelkezik jogkivonattal, inicializáljon vele egy példányt CallAgent , amely lehetővé teszi számunkra a hívások indítását és fogadását. Az eszköz kameráinak eléréséhez Eszközkezelő példányt is le kell szereznünk.

Adja hozzá a következő kódot a InitCallAgentAndDeviceManagerAsync függvényhez.

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
    }
}

Hívás indítása videóval

Adja hozzá az implementációt a CallButton_Click hívás indításához videóval. Számba kell venni a kamerákat az eszközkezelő példányával, és létre kell hoznunk LocalOutgoingVideoStream. A hívás kezdeti beállításainak beállításához meg kell adnunk VideoOptions a következőt LocalVideoStream , és át kell adnunk startCallOptions . A helyi videó előnézetét a csatolással LocalOutgoingVideoStream MediaElementtekintheti meg.

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;
}

Adja hozzá a különböző típusú hívás indításához vagy csatlakozásához használt metódusokat (1:1 Azure Communication Services-hívás, 1:1 telefonhívás, Azure Communication Services-csoporthívás, Teams-értekezletbe való bekapcsolódás stb.).

private async Task<CommunicationCall> StartAcsCallAsync(string acsCallee)
{
    var options = await GetStartCallOptionsAsynnc();
    var call = await this.callAgent.StartCallAsync( new [] { new UserCallIdentifier(acsCallee) }, options);
    return call;
}

private async Task<CommunicationCall> StartPhoneCallAsync(string acsCallee, string alternateCallerId)
{
    var options = await GetStartCallOptionsAsynnc();
    options.AlternateCallerId = new PhoneNumberCallIdentifier(alternateCallerId);

    var call = await this.callAgent.StartCallAsync( new [] { new PhoneNumberCallIdentifier(acsCallee) }, options);
    return call;
}

private async Task<CommunicationCall> JoinGroupCallByIdAsync(Guid groupId)
{
    var joinCallOptions = await GetJoinCallOptionsAsync();

    var groupCallLocator = new GroupCallLocator(groupId);
    var call = await this.callAgent.JoinAsync(groupCallLocator, joinCallOptions);
    return call;
}

private async Task<CommunicationCall> JoinTeamsMeetingByLinkAsync(Uri teamsCallLink)
{
    var joinCallOptions = await GetJoinCallOptionsAsync();

    var teamsMeetingLinkLocator = new TeamsMeetingLinkLocator(teamsCallLink.AbsoluteUri);
    var call = await callAgent.JoinAsync(teamsMeetingLinkLocator, joinCallOptions);
    return call;
}

private async Task<StartCallOptions> GetStartCallOptionsAsynnc()
{
    return new StartCallOptions() {
        OutgoingAudioOptions = new OutgoingAudioOptions() { IsOutgoingAudioMuted = true, OutgoingAudioStream = micStream  },
        OutgoingVideoOptions = new OutgoingVideoOptions() { OutgoingVideoStreams = new OutgoingVideoStream[] { cameraStream } }
    };
}

private async Task<JoinCallOptions> GetJoinCallOptionsAsync()
{
    return new JoinCallOptions() {
        OutgoingAudioOptions = new OutgoingAudioOptions() { IsOutgoingAudioMuted = true },
        OutgoingVideoOptions = new OutgoingVideoOptions() { OutgoingVideoStreams = new OutgoingVideoStream[] { cameraStream } }
    };
}

Adja hozzá a kódot a LocalVideoStream létrehozásához a módszer kiválasztott kamerájától CameraList_SelectionChanged függően.

var selectedCamerea = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamerea);

 var localUri = await cameraStream.StartPreviewAsync();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
    LocalVideo.Source = MediaSource.CreateFromUri(localUri);
});

if (call != null)
{
    await call?.StartVideoAsync(cameraStream);
}

Bejövő hívás elfogadása

Adja hozzá az implementációt a OnIncomingCallAsync bejövő hívás videóval való fogadásához, majd adja át a LocalVideoStream következőnek acceptCallOptions: .

var incomingCall = args.IncomingCall;

var acceptCallOptions = new AcceptCallOptions() { 
    IncomingVideoOptions = new IncomingVideoOptions()
    {
        IncomingVideoStreamKind = VideoStreamKind.RemoteIncoming
    } 
};

_ = await incomingCall.AcceptAsync(acceptCallOptions);

Távoli résztvevő és távoli videóstreamek

A híváspéldányok gyűjteményén RemoteParticipants keresztül minden távoli résztvevő elérhető. Miután a hívás csatlakozik (CallState.Connected), hozzáférhetünk a hívás távoli résztvevőihez, és kezelhetjük a távoli videóstreameket.

Feljegyzés

Amikor egy felhasználó csatlakozik egy híváshoz, a gyűjteményen keresztül elérheti az RemoteParticipants aktuális távoli résztvevőket. Az RemoteParticipantsUpdated esemény nem aktiválódik a meglévő résztvevők számára. Ez az esemény csak akkor aktiválódik, ha egy távoli résztvevő csatlakozik vagy elhagyja a hívást, amíg a felhasználó már szerepel a hívásban.


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;
    }

}

Távoli videók renderelése

Minden távoli videóstreamhez csatolja a 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();
        });
    }
}

Állapotfrissítés hívása

A hívás megszakadása után meg kell tisztítani a videoleképezőket, és kezelni kell az esetet, amikor a távoli résztvevők először csatlakoznak a híváshoz.

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;
    }
}

Hívás befejezése

A gomb kattintásával fejezd be az Hang Up aktuális hívást. Adja hozzá az implementációt a HangupButton_Click egy hívás befejezéséhez a létrehozott callAgenttel, és bontsa le a résztvevők frissítését és az állapot eseménykezelőinek hívását.

var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
    try
    {
        await call.HangUpAsync(new HangUpOptions() { ForEveryone = true });
    }
    catch(Exception ex) 
    {
    }
}

A kód futtatása

A kódot a Visual Studióban hozhatja létre és futtathatja. A megoldásplatformok esetében támogatjuk ARM64a x86. x64

Kimenő videohívást úgy kezdeményezhet, hogy megad egy felhasználói azonosítót a szövegmezőben, és rákattint a Start Call gombra.

Megjegyzés: A hívás 8:echo123 leállítja a videostreamet, mert az Echo robot nem támogatja a videostreamelést.

A felhasználói azonosítókkal (identitással) kapcsolatos további információkért tekintse meg a felhasználói hozzáférési jogkivonatok útmutatóját .

WinUI 3 mintakód

Előfeltételek

Az oktatóanyag teljesítéséhez a következő előfeltételekre lesz szüksége:

Beállítás

A projekt létrehozása

A Visual Studióban hozzon létre egy új projektet a Blank App, Packaged (WinUI 3 in Desktop) sablonnal egy egyoldalas WinUI 3-alkalmazás beállításához.

Képernyőkép az Új WinUI-projekt ablakról a Visual Studióban.

Telepítse a(z) csomagot

Kattintson a jobb gombbal a projektre, és nyissa meg az Manage Nuget Packages 1.0.0-s vagy újabb verzió telepítését Azure.Communication.Calling.WindowsClient . Győződjön meg arról, hogy az Előzetes belefoglalás jelölőnégyzet be van jelölve.

Hozzáférés kérése

A Visual Studióban az internethez és a mikrofonhoz való hozzáférés kérését bemutató képernyőkép.

Adja hozzá a következő kódot a következőhöz app.manifest:

<file name="RtmMvrMf.dll">
    <activatableClass name="VideoN.VideoSchemeHandler" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>

Az alkalmazás-keretrendszer beállítása

Egy alapszintű elrendezést kell konfigurálnunk a logikánk csatolásához. Kimenő hívás indításához meg kell TextBox adnia a hívó felhasználóazonosítóját. Egy gombra és egy Start Call gombra Hang Up is szükségünk van. A helyi videó előnézetét is meg kell tekintenünk, és el kell készítenünk a másik résztvevő távoli videóját. Tehát két elemre van szükségünk a videóstreamek megjelenítéséhez.

Nyissa meg a MainWindow.xaml projektet, és cserélje le a tartalmat a következő megvalósításra.

<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>

Nyissa meg a következőt App.xaml.cs (kattintson a jobb gombbal, és válassza a Kód megtekintése lehetőséget), és adja hozzá ezt a sort a tetejére:

using CallingQuickstart;

Nyissa meg a MainWindow.xaml.cs (jobb gombbal kattintva és válassza a Kód megtekintése) lehetőséget, és cserélje le a tartalmat a következő implementációra:

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();
            });
        }
    }
}

Objektummodell

A következő osztályok és felületek kezelik az Azure Communication Services Calling SDK néhány fő funkcióját:

Név Leírás
CallClient Ez CallClient a hívási ügyfélkódtár fő belépési pontja.
CallAgent Ez CallAgent a hívások indítására és csatlakoztatására szolgál.
CommunicationCall A CommunicationCall rendszer az elhelyezett vagy csatlakoztatott hívások kezelésére szolgál.
CallTokenCredential A CallTokenCredential rendszer a jogkivonat hitelesítő adataiként használja a példányosításhoz.CallAgent
CommunicationUserIdentifier A CommunicationUserIdentifier felhasználó identitásának ábrázolására szolgál, amely a következő lehetőségek egyike lehet: CommunicationUserIdentifiervagy PhoneNumberIdentifier CallingApplication.

Az ügyfél hitelesítése

A CallAgentfelhasználói hozzáférési jogkivonat inicializálásához felhasználói hozzáférési jogkivonatra van szükség. Ez a jogkivonat általában egy olyan szolgáltatásból jön létre, amely az alkalmazásra jellemző hitelesítéssel rendelkezik. A felhasználói hozzáférési jogkivonatokról további információt a Felhasználói hozzáférési jogkivonatok útmutatójában talál.

A rövid útmutatóban cserélje le <AUTHENTICATION_TOKEN> az Azure Communication Service-erőforráshoz létrehozott felhasználói hozzáférési jogkivonatot.

Miután rendelkezik egy jogkivonattal, inicializálhat vele egy CallAgent példányt, amely lehetővé teszi számunkra a hívások indítását és fogadását. Az eszköz kameráinak eléréséhez Eszközkezelő példányt is le kell szereznünk.

Adja hozzá a következő kódot a InitCallAgentAndDeviceManagerAsync függvényhez.

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;

Hívás indítása videóval

Adja hozzá az implementációt a CallButton_Click hívás indításához videóval. Számba kell venni a kamerákat az eszközkezelő példányával, és létre kell hoznunk LocalVideoStream. A hívás kezdeti beállításainak beállításához meg kell adnunk VideoOptions a következőt LocalVideoStream , és át kell adnunk startCallOptions . A helyi videó előnézetét a csatolással LocalVideoStream MediaPlayerElementtekintheti meg.

var startCallOptions = new StartCallOptions();

if (this.deviceManager.Cameras?.Count > 0)
{
    var videoDeviceInfo = this.deviceManager.Cameras?.FirstOrDefault();
    if (videoDeviceInfo != null)
    {
        var selectedCamerea = CameraList.SelectedItem as VideoDeviceDetails;
        cameraStream = new LocalOutgoingVideoStream(selectedCamerea);

        var localUri = await cameraStream.StartPreviewAsync();
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            LocalVideo.Source = MediaSource.CreateFromUri(localUri);
        });

        startCallOptions.VideoOptions = new OutgoingVideoOptions(new[] { cameraStream });
    }
}

var callees = new ICommunicationIdentifier[1]
{
    new CommunicationUserIdentifier(CalleeTextBox.Text.Trim())
};

this.call = await this.callAgent.StartCallAsync(callees, startCallOptions);
this.call.OnRemoteParticipantsUpdated += Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged += Call_OnStateChangedAsync;

Bejövő hívás elfogadása

Adja hozzá az implementációt a Agent_OnIncomingCallAsync bejövő hívás videóval való fogadásához, majd adja át a LocalVideoStream következőnek acceptCallOptions: .

var acceptCallOptions = new AcceptCallOptions();

if (this.deviceManager.Cameras?.Count > 0)
{
    var videoDeviceInfo = this.deviceManager.Cameras?.FirstOrDefault();
    if (videoDeviceInfo != null)
    {
        var selectedCamerea = CameraList.SelectedItem as VideoDeviceDetails;
        cameraStream = new LocalOutgoingVideoStream(selectedCamerea);

        var localUri = await cameraStream.StartPreviewAsync();
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            LocalVideo.Source = MediaSource.CreateFromUri(localUri);
        });

        acceptCallOptions.VideoOptions = new OutgoingVideoOptions(new[] { localVideoStream });
    }
}

call = await incomingCall.AcceptAsync(acceptCallOptions);

Távoli résztvevő és távoli videóstreamek

A híváspéldányok gyűjteményén RemoteParticipants keresztül minden távoli résztvevő elérhető. A hívás csatlakoztatása után hozzáférhetünk a hívás távoli résztvevőihez, és kezelhetjük a távoli videóstreameket.

Feljegyzés

Amikor egy felhasználó csatlakozik egy híváshoz, a gyűjteményen keresztül elérheti az RemoteParticipants aktuális távoli résztvevőket. Az OnRemoteParticipantsUpdated esemény nem aktiválódik a meglévő résztvevők számára. Ez az esemény csak akkor aktiválódik, ha egy távoli résztvevő csatlakozik vagy elhagyja a hívást, amíg a felhasználó már szerepel a hívásban.

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);
    }
}

Távoli videók renderelése

Minden távoli videóstreamhez csatolja a 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();
        });
    }
}

Állapotfrissítés hívása

A hívás megszakadása után meg kell tisztítani a videoleképezőket, és kezelni kell az esetet, amikor a távoli résztvevők először csatlakoznak a híváshoz.

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;
    }
}

Hívás befejezése

A gomb kattintásával fejezd be az Hang Up aktuális hívást. Adja hozzá az implementációt a HangupButton_Click egy hívás befejezéséhez a létrehozott callAgenttel, és bontsa le a résztvevők frissítését és az állapot eseménykezelőinek hívását.

this.call.OnRemoteParticipantsUpdated -= Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged -= Call_OnStateChangedAsync;
await this.call.HangUpAsync(new HangUpOptions());

A kód futtatása

A kódot a Visual Studióban hozhatja létre és futtathatja. A megoldásplatformok esetében támogatjuk ARM64a x86. x64

Kimenő videohívást úgy kezdeményezhet, hogy megad egy felhasználói azonosítót a szövegmezőben, és rákattint a Start Call gombra.

Megjegyzés: A hívás 8:echo123 leállítja a videostreamet, mert az Echo robot nem támogatja a videostreamelést.

A felhasználói azonosítókkal (identitással) kapcsolatos további információkért tekintse meg a felhasználói hozzáférési jogkivonatok útmutatóját .