Cisco のビデオ端末で画面レイアウトを変えてみた


この記事は Cisco Systems Japan の有志による Advent Calendar 2022 の 25 日目として投稿しています。
　2022年版(1枚目 & 2枚目): https://qiita.com/advent-calendar/2022/cisco


## はじめに
[Ciscoのコラボレーションエンドポイント](https://www.cisco.com/c/ja_jp/products/collaboration-endpoints/index.html)はビデオ会議の専用端末として広く利用されています。
デフォルトの設定でも十分に生産性高く利用することが可能ですが、環境に合わせることでより良い使い方が可能です。実際に会議室でさらにより便利に使いたい、会議以外のところで使いたい、といったご相談が増えています。
このような需要に応えられる端末自体の幅広い設定、API、多くのIFをもつ機種のサポートが以前からあります。昨今ではそれに加えてマクロが端末自体で動作させることができたり、Webアプリを展開したり、受付端末のような機能を制限したKioskモードを利用できたりと、カスタマイズの幅が増えてきており、ますます活躍の場を広げています。

本記事では改めてAPIやマクロの概要について触れます。また、実際にご要望をいただいた画面レイアウトの変更方法を実現する例を紹介します。

今回のAdvent Calender では他記事でもマクロを使った例をあげています。内容が被っているところも多くありますが、是非両方見て理解を深めてもらえればありがたいです。
　[人を検知して自動的にビデオ通話を開始させてみる - Cisco Desk Pro 編 -](https://qiita.com/kazkaz_o3/items/67878c62c081d78962a9)

## Cisco Devices のAPI
Cisco Deviceを司るRoomOSではAPIを利用することが可能です。利用可能なものを大別すると下記の4つに別れます。
* COMMAND：アクションを実行する
* STATUS：Read Onlyでステータス情報を取得する
* CONFIG：設定を行う
* EVENT：トリガーを元に検知をする

APIは利用するためのインタフェースとしてSSH,　HTTP/HTTPS,　WebSocket,　Serial Console を利用することが可能です。
また、端末のマクロに組み込むこんで実行することもできますし、端末をクラウド管理している場合にはREST APIを利用したり、管理ポータルであるControl Hub 上からAPIを利用することが可能になっています。
SSH等を利用する場合には、実際にDeviceにネットワーク的にアクセス可能な環境から実行する必要があります。REST APIやControl Hub上から実行することで、管理権限のあるユーザが実際にどこにいても利用できるというのは非常に便利です。

実際に簡単な例として挙げてみます。
ciscodevices@cisco.com 向けにAPIを用いて発信を行いる例です。
SSHアクセスし、コマンドを用いる場合
```
xCommand Dial Number: ciscodevices@cisco.com
```

REST APIを利用する場合（BODYのみ表示）
```
POST https://webexapis.com/v1/xapi/command/Dial
{
  "deviceId": "Y2lzY29zcGFya.....S9mb29iYXIv",
  "arguments": {
    "Number": "ciscodevices@cisco.com"
  }
};
```

Control Hub を利用する場合
メニューから選択、値を入れて実行することが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412449/93e83cc0-0e71-3d20-618b-1e29bd62371a.png)


端末のAPIドキュメントは下記に公開されています。
[Cisco Webex Board, Desk, and Room Series API Reference Guide](https://www.cisco.com/c/en/us/support/collaboration-endpoints/spark-room-kit-series/products-command-reference-list.html)
また[roomos.cisco.com](https://roomos.cisco.com/)では、簡単に検索や実際のコマンド等を確認することができます。

Control Hub登録している場合のREST APIについては[developer.webex.com](https://developer.webex.com/)を確認してください。

## Cisco Devices のマクロ
Cisco Devices 上でJavascript を利用してマクロを組むことでDevice上でAPIを実行することが可能です。カスタマイズされたUIとの連携することで、ボタンが押されたことをもとに設定変更を行ったり、部屋内の人数を検知して一定以上だであれば検知したり（参照：[Cisco Webex Device で室内の密を検知してWebex に通知してみた](https://qiita.com/tatakaya/items/7a63f093f628e64c41eb))、いろいろなユースケースで利用可能です。

*ビデオエンドポイント カスタマイズの資料より抜粋
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412449/b4e3520a-0d31-b5f2-aed1-e9807fb772fc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412449/9595bfdf-a215-e702-3246-2e6d0c3372b3.png)

現在マクロは端末ごとにWebInterfaceでログインして設定を行いますが、クラウド上の管理ポータルから管理ができるようになってきました（2022年12月現在ベータ機能として実装）。

ciscodevices@cisco.com 向けにAPIを用いて発信を行いるマクロであればこのようになります。
```
import xapi from 'xapi';
xapi.command('Dial', { Number: 'ciscodevices@cisco.com' });
```
実際のマクロがこれだけですとマクロを有効化した段階で発信してしまいます。実際にお使いいただく上ではトリガーとの紐付けも行っていただく必要があります。例えば、UIのカスタマイズを行いスピードダイアルボタンを作成し、ボタンが押されたことを検知して発信というイメージです。
端末上のメニューとしてUIをカスタマイズするにはUI Editor を利用することができます。[User Interface Extensions](https://roomos.cisco.com/doc/TechDocs/UiExtensions.md)からUI Editor をお試しすることもできます。

実際のマクロ作成にあたっては[マクロ スクリプト作成のチュートリアル](https://www.cisco.com/c/dam/global/ja_jp/td/docs/telepresence/endpoint/ce95/macro-scripting-tutorial.pdf)や前述した[roomos.cisco.com](https://roomos.cisco.com/)でJavascript、サンプルマクロを確認すると便利です。

概要はここまでとして、このあとはレイアウト変更をAPIやMacroで実行する例をご紹介していきます。

## 複数画面構成のレイアウトをAPIで変更してみる

大きめの会議室を利用する場合、複数モニターを用意してインテグレーションを行う場合があります。
複数のモニタを配置して会議を行なっているお客様からは、通常左側のモニターに資料が大きく映るが、今回は右側に写したい、といった要望がくる場合があります。この場合はモニタロールの設定変更にて対応することができます。

Cisco Devices でインテグレーションを行う場合、2,3画面を使う場合に各画面にどういう表示がでるかについては複数の要素が絡んできます。
1. 会議の状況
参加者数や資料共有の有無など。
2. レイアウト
Grid, Overlay, Stack, Focusをローカルで指定して変更。実際に会議室においてあるコントローラで変更可能です。
3. ビデオモニター・モニターロール
ビデオ出力コネクタに接続された画面にどのビデオストリームを表示するかを決定します。端末上の設定で決まります。

モニターロールは多くの端末（Room55D,Room70を除く）でデフォルトAutoであり、Autoの場合は自動で値が割り振りをされます。この値を明示的に変えることでレイアウトを変更することが可能です。
取りうる値は端末によって下記の通り異なります。
Auto/First/Second/PresentationOnly [ RoomKit  RoomBar  CodecPlus  Room55  Room70/Room55D DeskPro  BoardPro ]
Auto/First/Second/Third/PresentationOnly/Recorder [ CodecPro  Room70G2  RoomPanorama/Room70Panorama ]

詳細については[管理者ガイド](https://www.cisco.com/c/ja_jp/support/collaboration-endpoints/spark-room-kit-series/products-maintenance-guides-list.html#~tab-documentation)をご確認ください。

実際にAPIを利用してSSHアクセスしてモニターロールを変更してみます。
モニター１に接続されている端末のMonitor Role をAutoからPresentation Only に変更します。

変更前の値がAutoであることを確認。
```
xConfiguration Video Output Connector[1] MonitorRole
*c xConfiguration Video Output Connector 1 MonitorRole: Auto
** end
OK
```

MonitorRoleをPresentationOnlyに変更。
```
xConfiguration Video Output Connector[1] MonitorRole: PresentationOnly
** end
OK
```

MonitorRoleがPresentationOnlyであることを確認。
```
xConfiguration Video Output Connector[1] MonitorRole
*c xConfiguration Video Output Connector 1 MonitorRole: PresentationOnly
** end
OK
```


変更前画面（１画面構成時）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412449/667adede-8475-4c8d-1fd1-be160ff0f0b6.png)


変更後画像（１画面構成時）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412449/5878d1f3-c98f-15f1-b918-a569ca02c7af.png)

１画面構成であったとしても人物表示がなくなりプレゼンテーションのみ表示に変わったことが確認できます。
なお、１画面構成の場合はデフォルトで利用可能なレイアウト変更で対処が可能なケースがほとんどです。上記例もレイアウトをフォーカスに変えることで実現することは可能です。


## マクロを使ってユーザがレイアウトを変更できるようにしてみる

SSHでAPIを利用する、またはWebGUIで設定する方法の場合、端末に対しての管理者レベルの権限が必要です。
すなわち実際に会議を行なっているユーザからは変更ができないというのがネックになってくる場合があります。
これに対して、実際にユーザが利用するコントローラ上に変更メニューを表示し、それをトリガーにマクロを用いて設定変更を行うことで対応することが可能です。

コントローラー上にメニューを表示するには端末にHTTPSでアクセスし、UI Extensions Editor を使ってメニューを作成します。
Pannel を新規で作成しボタンを作成、必要なパラメーターの設定を行なっていきます。

今回は２画面の構成を想定して作成していきます。
作成したメニューは下記の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412449/49df95b7-db52-e3e0-5844-d6d4246309f7.png)

マクロとの兼ね合わせを踏まえて下記の点に注意の上作成してします。
1. WidgetIdの末尾の数字をモニター番号と紐付け
2. 各ボタンのValueをMonitorRoleの設定値に合わせる

このメニューをサンプルとしてXMLでエクスポートしましたので公開します。
<details><summary>コントローラー上のメニューサンプルXML</summary>

```rb
<Extensions>
  <Version>1.9</Version>
  <Panel>
    <Order>1</Order>
    <PanelId>panel_display_layout</PanelId>
    <Origin>local</Origin>
    <Location>HomeScreen</Location>
    <Icon>Lightbulb</Icon>
    <Name>モニターコントロール</Name>
    <ActivityType>Custom</ActivityType>
    <Page>
      <Name>モニターロール</Name>
      <Row>
        <Name>モニター1</Name>
        <Widget>
          <WidgetId>monitor_role_1</WidgetId>
          <Type>GroupButton</Type>
          <Options>size=4;columns=3</Options>
          <ValueSpace>
            <Value>
              <Key>Auto</Key>
              <Name>自動</Name>
            </Value>
            <Value>
              <Key>First</Key>
              <Name>First</Name>
            </Value>
            <Value>
              <Key>Second</Key>
              <Name>Second</Name>
            </Value>
            <Value>
              <Key>PresentationOnly</Key>
              <Name>資料表示のみ</Name>
            </Value>
          </ValueSpace>
        </Widget>
      </Row>
      <Row>
        <Name>モニター2</Name>
        <Widget>
          <WidgetId>monitor_role_2</WidgetId>
          <Type>GroupButton</Type>
          <Options>size=4;columns=3</Options>
          <ValueSpace>
            <Value>
              <Key>Auto</Key>
              <Name>自動</Name>
            </Value>
            <Value>
              <Key>First</Key>
              <Name>First</Name>
            </Value>
            <Value>
              <Key>Second</Key>
              <Name>Second</Name>
            </Value>
            <Value>
              <Key>PresentationOnly</Key>
              <Name>資料表示のみ</Name>
            </Value>
          </ValueSpace>
        </Widget>
      </Row>
      <Options/>
    </Page>
  </Panel>
</Extensions>
```
</details>

続いてボタンに対応するマクロを作成していきます。
端末上のMacro Editor を使って記載していきます。
今回のマクロでは3つのFunction を作っています。

```
async function listenOn() {
  xapi.event.on('UserInterface Extensions Widget Action', (event) => WidgetAction(event));
}
```
作成したボタンを押すなどのイベントを検知し、イベント種別判断用の関数を呼び出します。

```
async function WidgetAction(event) {
  console.log('WidgetAction', event);
  if (event.Type === 'released') {
    VideoOutputMonitor(event);
  }
}
```
発生したイベントの種別を判断し、released であればモニターロール変更用の関数を呼び出します。

```
async function VideoOutputMonitor(event) {
  console.log('VideoOutputMonitor', `event=`, event);
    let id = event.WidgetId.slice(-1);
    xapi.Config.Video.Output.Connector[id].MonitorRole.set(event.Value)
}
```
実際のモニターロールの変更を行います。
id は実際にボタン様のWidegetIdの最後の１文字を利用しています。作成したボタンのWidgetIDがmonitor_role_1,monitor_role_2ですので、押された場所に応じてidを変更します。
MonitorRole は設定可能な値を作成したボタンのValue（Auto,First,Second,PresentationOnly）としてボタンに設定を行なっているため、それを利用します。

参考としてサンプルコードを全文で記載します。
<details><summary>サンプルコード全文</summary>

```rb
import xapi from 'xapi';

async function VideoOutputMonitor(event) {
  console.log('VideoOutputMonitor', `event=`, event);
    let id = event.WidgetId.slice(-1);
    xapi.Config.Video.Output.Connector[id].MonitorRole.set(event.Value)
}

async function WidgetAction(event) {
  console.log('WidgetAction', event);
  if (event.Type === 'released') {
    VideoOutputMonitor(event);
  }
}

async function listenOn() {
  xapi.event.on('UserInterface Extensions Widget Action', (event) => WidgetAction(event));
}

listenOn();
```
</details>

今回はマクロ利用の実例としてモニターのレイアウトに使えるサンプルをご紹介しました。
２画面ではなく、３画面で実施したい、などありましたらサンプルをもとに作成いただければと思います。

## おわりに
多くの会議でリモートの参加が誰かしらいるという状況が増えつつあるなか会議室に専用端末をおきたいという需要が増えています。
リモートから誰かしらが参加するというのが大多数を占めるというのが調査上からもわかっています。そんななか生産性を保つために、専用端末を使うことで音声、ビデオの品質を担保しようという動きがあるわけです。

なぜ専用端末を使うと良いのか？について書き始めるとそれだけで長くなりそうなので割愛しますが、下記の動画で簡潔に触れていますので、ご興味があれば見てみてください。
[【比較してみた】PCメインのweb会議を続けない方がいい理由！](https://www.youtube.com/watch?v=YrXHXi1KAY8)

また、会議以外での使い方を含めていろんな可能性があると思いますので、APIやマクロも含めて、お客様にあったご利用、ご提案をしてもらえれば嬉しいです。

## 免責事項
本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。