Azure Communication Services でどこまでできるのか？ 【Ignite2021】

[以前の記事](https://qiita.com/komiyasa/items/bb74b4e4178ceb99199d)でも少し触れましたが、Microsoft Ignite で再度 Updates がありましたがので、Azure Communication Service を少し触ってみようと思います。アップデート情報の整理も兼ねて色々試してみます。
Azure Communication Services の概要はこちら => https://azure.microsoft.com/ja-jp/services/communication-services/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/f685c4b8-0a1c-874d-eb1e-2530324450dd.png)

#Azure Communication Services アップデート概要
3月上旬に Microsoft Ignite が開催されましたが、そこで Azure Communication Service の Updates がありました。Update の情報としてはこんな感じです。
>Azure Communication Services, the first fully managed communication platform offering from a major cloud provider, will become generally available in the next few weeks. Azure Communication Services is also now interoperable with Microsoft Teams in preview, enabling customers to leverage a unified offering for both internal and external communication experiences. Employees benefit from the security, familiarity and capability of Teams, and external users can enjoy a custom communication experience on a web or mobile app outside the organization. This is ideal for many business-to-consumer scenarios, such as healthcare professionals delivering remote care, financial advisors helping consumers with a loan application or support staff helping end users install a new product.
Azure Communication Services provides developers with a set of libraries to help integrate voice, video, text and data communication. This enables scenarios such as browser-to-browser, browser-to-app and app-to-app communication; users interacting with bots or other services; and users and bots interacting over the public switched telephone network. Azure Communication Services was first introduced in preview in September 2020.
In addition, enterprises can now offer conversational artificial intelligence (AI) experiences over a traditional phone line with Azure Bot Service’s new telephony channel, powered by Azure Communication Services. When coupled with powerful AI capabilities from Azure Cognitive Services, enterprises can offer seamless natural language and speech interaction to end users compared with traditional Interactive Voice Response (IVR) offerings.

翻訳するとこんな感じ。
>主要なクラウドプロバイダーが提供する最初のフルマネージド通信プラットフォームであるAzureCommunication Servicesは、数週間以内に一般提供される予定です。 Azure Communication Servicesは、プレビューでMicrosoft Teamsと相互運用できるようになり、顧客は内部と外部の両方の通信エクスペリエンスに統合されたサービスを活用できるようになりました。従業員はチームのセキュリティ、親しみやすさ、機能の恩恵を受け、外部ユーザーは組織外のWebまたはモバイルアプリでカスタムコミュニケーションエクスペリエンスを楽しむことができます。これは、リモートケアを提供する医療専門家、ローン申請で消費者を支援するファイナンシャルアドバイザー、エンドユーザーが新製品をインストールするのを支援するサポートスタッフなど、多くの企業から消費者へのシナリオに最適です。
Azure Communication Servicesは、音声、ビデオ、テキスト、およびデータ通信の統合を支援する一連のライブラリを開発者に提供します。これにより、ブラウザーからブラウザー、ブラウザーからアプリ、アプリからアプリの通信などのシナリオが可能になります。ボットまたは他のサービスと対話するユーザー。公衆交換電話網を介して対話するユーザーとボット。 Azure Communication Servicesは、2020年9月にプレビューで最初に導入されました。
さらに、企業は、Azure CommunicationServicesを搭載したAzureBot Serviceの新しいテレフォニーチャネルを使用して、従来の電話回線を介して会話型人工知能（AI）エクスペリエンスを提供できるようになりました。 Azure Cognitive Servicesの強力なAI機能と組み合わせると、企業は、従来の対話型音声応答（IVR）製品と比較して、エンドユーザーにシームレスな自然言語と音声の対話を提供できます。

つまり、Teams と同じ様な機能を Azure Communication Services という Azure 上のサービスで利用できるようになったということですね！これは非常に便利そう！」
こちらの記事では Ignite での動画が見れますので参考にしてください。
https://docs.microsoft.com/ja-jp/events/ignite-mar-2021/azure/sessions/studio02/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/1d4cb445-ddb2-5170-2230-9435a05c539c.png)

実はプレビュー版時に試した際に、チャットと通話はできることを確認しています。以下その記事ですので参考までに。Azure Communication Service の Key の生成方法など初歩的な内容を記載しています。

【爆速】Azure Communication Services を早速試してみた！
https://qiita.com/komiyasa/items/bb74b4e4178ceb99199d

Azure Communication Services を使ってみた！(Chat編)
https://qiita.com/komiyasa/items/d34fd97d7e32b6f5a230

#サンプルコードを動かしてみる
今回特に試したかったのは、画面共有ができるのかどうかです。実際にサンプルコードを触りながら見ていきたいと思います。
##サンプルコード
サンプルコードは以下の GitHub に Microsoft から公開しています。
(参考)Azure-Samples/communication-services-web-calling-tutorial
https://github.com/Azure-Samples/communication-services-web-calling-tutorial/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/cab2c52f-e70f-1f0b-a9d7-81169e834812.png)
JavaScript ベースのアプリケーションなので Node.Js の環境があれば動きそうですね。実際に試してみましょう。

##接続文字列を変更
ダウンロードしたソースコードの中に、Config.json がありますので、この中の 'ConnectionString' の値を自分が Azure にデプロイした ACS の接続文字列に置き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/9d4c9375-c293-7047-f80c-c047717616a3.png)

##npm run
接続文字列を置き換えることができたら、以下のように npm でデプロイすると `localhost:5000` でブラウザが自動的に立ち上がってきます。

```
npm install
npm run build
npm run start
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/ceb192ef-9408-7b83-ca40-fe120f99190d.png)

このサンプルコードのアプリケーションでは、最初に User の Initialize して User ID を取得、そのあとでその User ID ベースで会議に入るという流れになっています。Initialize すると以下のように User ID が割り振られ、会議を開始する際の Group ID、Teams Meeting に入る際のフォームが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/08249a6c-9635-dfdc-9eb8-239e03435bf5.png)
ここでローカルの Teams アプリから会議を立ち上げ、そのミーティングリンクを ACS のアプリに入れミーティングに招待してみみます。
参加させるといわゆる Teams 会議に外部からの参加者が来ているように Windows がでてきました！Teams のまんまですね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/e3763d85-92d7-d6fb-ec1a-5801dcc0426e.png)
サンプルでは実際に音声通話もビデオ通話もできそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/e4e2e10b-044e-c49e-e6ba-2db54b60484a.png)
画面共有もできますね！これはプレビューリリースの際にはそこまで注視していなかったのですが、画面共有が Azure Communication Service でできるとなると色々活用できるシナリオはありそうです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/f413e100-1522-7053-52ba-e1952346c32d.png)

##Azure Communication Services の SDK
サンプルコードになりますが、画面共有する際のコードはこんな感じ。SDK として Screan Shearing が準備されているのでそれを活用すればよいだけの話みたいですね。これは楽ちん！

```videoshare.js
/************************************************/
/*     Local Video and Local Screen-sharing     */
/************************************************/
// To start a video, you have to enumerate cameras using the getCameras()
// method on the deviceManager object. Then create a new instance of
// LocalVideoStream passing the desired camera into the startVideo() method as
// an argument
const cameraDevice = this.callClient.getDeviceManager().getCameras()[0];
const localVideoStream = new LocalVideoStream(cameraDevice);
await call.startVideo(localVideoStream);

// To stop local video, pass the localVideoStream instance available in the
// localVideoStreams collection
await this.currentCall.stopVideo(localVideoStream);

// You can use DeviceManager and Renderer to begin rendering streams from your local camera.
// This stream won't be sent to other participants; it's a local preview feed. This is an asynchronous action.
const renderer = new Renderer(localVideoStream);
const view = await renderer.createView();
document.getElementById('someDiv').appendChild(view.target);

// You can switch to a different camera device while video is being sent by invoking
// switchSource() on a localVideoStream instance
const cameraDevice1 = this.callClient.getDeviceManager().getCameras()[1];
localVideoStream.switchSource(cameraDeivce1);

// Handle 'localVideoStreamsUpdated' event
this.currentCall.on('localVideoStreamsUpdated', e => {
    e.added.forEach(addedLocalVideoStream => { this.handleAddedLocalVideoStream(addedLocalVideoStream) });
    e.removed.forEach(removedLocalVideoStream => { this.handleRemovedLocalVideoStream(removedLocalVideoStream) });
});

// To start sharing your screen
await this.currentCall.startScreenSharing();

// To stop sharing your screen
await this.currentCall.stopScreenSharing();

// Handle 'isScreenSharingOnChanged' event
this.currentCall.on('isScreenSharingOnChanged', this.handleIsScreenSharingOnChanged());




/**************************************************************************************/
/*     Handling Video streams and Screen-sharing streams from remote participants     */
/**************************************************************************************/

// Handle remote participant video and screen-sharing streams
addedParticipant.videoStreams.forEach(stream => handleRemoteStream(stream))

// Handle remote participant 'videoStreamsUpdated' event. This is for videos and screen-shrings streams.
addedParticipant.on('videoStreamsUpdated', videoStreams => {
    videoStreams.added.forEach(addedStream => {
        handleRemoteStream(addedStream)
    });

    videoStreams.removed.forEach(removedStream => {
        handleRemoveStream(removedStream);
    });
});

// Render remote streams on UI. Do this logic in a UI component.
// Please refer to /src/MakeCall/StreamMedia.js of this app for an example of how to render streams on the UI:
const handleRemoteStream = (stream) => {
    let componentContainer = document.getElementById(this.componentId);
    componentContainer.hidden = true;

    let renderer = new Renderer(this.stream);
    let view;
    let videoContainer;

    const renderStream = async () => {
        if(!view) {
            view = await renderer.createView();
        }
        videoContainer = document.getElementById(this.videoContainerId);
        if(!videoContainer?.hasChildNodes()) { videoContainer.appendChild(view.target); }
    }

    this.stream.on('isAvailableChanged', async () => {
        if (this.stream.isAvailable) {
            componentContainer.hidden = false;
            await renderStream();
        } else {
            componentContainer.hidden = true;

        }
    });

    if (this.stream.isAvailable) {
        componentContainer.hidden = false;
        await renderStream();
    }
}

<div id={this.componentId}>
    <div id={this.videoContainerId}></div>
</div>
```

#価格はどんなもん？
価格感ですが、Microsoft の公式 docs によると参考価格はこんな感じでした。画面共有とビデオ通話は価格帯が一緒で、だいたい60分通話をして70円くらいですかね。
>Alice が、仕事仲間の Bob と Charlie とグループ通話を行いました。 Alice と Bob は JS クライアント ライブラリを使用し、Charlie は iOS クライアント ライブラリを使用しました。
この通話は合計 60 分間続きました。
Alice と Bob は通話全体に参加しました。 Alice は、自分のビデオを 5 分間オンにし、自分の画面を 23 分間共有しました。 Bob は、通話全体 (60 分間) にわたってビデオを表示し、自分の画面を 12 分間共有しました。
Charlie は 43 分後に通話を終了しました。 Charlie は、参加している間中 (43 分間)、オーディオとビデオを使用しました。
コストの計算
2 人の参加者 x 60 分 x 参加者あたり $0.004/分 = $0.48 [ビデオとオーディオの両方が同じ料金で課金されます]
1 人の参加者 x 43 分 x 参加者あたり $0.004/分 = $0.172 [ビデオとオーディオの両方が同じ料金で課金されます]
グループ通話の総コスト: $0.48 + $0.172 = $0.652

https://docs.microsoft.com/ja-jp/azure/communication-services/concepts/pricing

正確な価格については以下の公式ページを参考にしてください。
https://azure.microsoft.com/ja-jp/pricing/details/communication-services/

Bot や Cognitive Service と連携することでより活用の幅が広がりそうなサービスなので引き続き Watch していきたいと思います！