合成のルール

このドキュメントでは SkyWay LiveStreaming API で SkyWay の映像や音声を合成する設定のルールについて説明します。

JSON 形式の設定によって映像と音声の合成の制御が可能です。 指定可能なパラメーターの詳細は、APIリファレンスを参照してください。

合成処理の概要

合成の設定は Channel 中の Publication を選択し、どのようなレイアウトで表示するかを設定します。 LiveStreaming Service は合成の設定に従って Publication を合成した映像を配信サービスに配信します。

合成の設定は大きく3つに分かれています。

  • mode
    • 現在は CUSTOM モードのみ利用可能です
  • videoConfig
    • 映像の合成に関する設定を行います
  • audioConfig
    • 音声の合成に関する設定を行います

映像合成の設定

videoConfig では映像の合成について、以下の設定が可能です。

  • 必須
    • canvasWidth
      • 出力映像の横幅のピクセル数
    • canvasHeight
      • 出力映像の縦幅のピクセル数
    • elements
      • 合成対象となる映像を設定します。指定方法は後述します。
  • オプション
    • backgroundImage
      • 出力映像の背景画像
        • png 形式の画像を base64化した文字列を入力する
        • 背景画像は常に要素より奥に描画されます

音声合成の設定

videoConfig では音声の合成について、以下の設定が可能です。

  • 必須
    • elements
      • 合成対象となる音声を設定します。指定方法は後述します。

要素の設定

要素とは、合成における個々の映像または音声の要素を指します。たとえば、会議中の参加者のカメラ映像や画面共有、個別の音声がそれに該当します。

映像の要素の設定

videoConfig 内の elements プロパティで、各映像の要素について以下の設定が可能です。

  • 必須
    • publisher
      • 合成対象となる Publication を選択します。選択方法は後述します。
    • width
      • 要素の横幅のピクセル数
    • height
      • 要素の縦幅のピクセル数
    • x
      • 要素の X 座標
        • 左側が原点
    • y
      • 要素の Y 座標
        • 上側が原点
  • オプション
    • zIndex
      • 要素の重なりの順の指定
        • 0以上255以下の値を指定できます
        • 0が最も奥です
          • 背景画像は要素の zIndex の値にかかわらず常にエレメントより奥に描画されます
        • デフォルトで0が割り当てられます

映像の要素は49個まで設定できます。

次のように x を30,y を60と設定した場合はこのような出力となります。

{ "mode": "CUSTOM", "videoConfig": { "canvasWidth": 720, "canvasHeight": 720, "elements": [ { "publisher": { "id": "*" }, "height": 300, "width": 300, "x": 30, "y": 60 } ] }, "audioConfig": { "elements": [] } }

座標指定例

音声の要素の設定

audioConfig 内の elements プロパティで、各音声の要素について以下の設定が可能です。

  • 必須
    • publisher
      • 合成対象となる Publication を選択します。選択方法は後述します。

音声の要素は4個まで設定できます。

要素のPublicationの選択

各要素では、publisher プロパティを使用して合成対象となる Publication の選択をする必要があります。選択の手順は以下のような流れになります。

  1. publisher の選択

    この時点で選択した Publisher のすべての Publication が候補になります。

  2. query による絞り込み

    1で選択した候補から最終的に1つの Publisher を選択します。

  3. publisher の publication を選択

    2で選択した Publisher が publish している Publication を候補として Publication を選択します。この時点で複数の候補が存在する可能性があります。

  4. 対象の Publication の決定

    3で選択した候補から最終的に1つの Publication を選択します。

publisherの選択

以下の識別子から Publisher(Publication を Publish した Member)を選択できます。

(※core ライブラリを利用している場合は SFU-Bot ではなく元の Publication を Publish している Person が対象です。)

  • id
  • name
  • metadata

いずれの識別子も選択されていない場合は channel 中のすべての Member が候補となります

queryによる候補の絞り込み

publisher の選択の結果、複数の Publisher の候補が存在する場合、query プロパティによって1つに絞り込みます。

query では以下の設定が可能です。

  • sortBy
    • Publisher の候補をリアルタイムに、どのような順序で並べるかを指定できます
      • AUDIO_LEVEL
        • 各 Publisher の Publish している AudioPublication のうち、最も音量が大きい AudionPublication の音量が大きい順
      • TIMELINE
        • Publisher が Room に Join した時刻順
  • index
    • ソートされた Publisher の候補の配列から最終的な Publisher を選択するための添字
    • -1を指定すると候補の配列の最後の Publisher が選択される

query を指定しない場合はデフォルトで sortBy が TIMELINE、index が0に設定されます。

Channel 中の AUDIO_LEVEL 上位2 publisher の publication を選択して描画する設定と結果は次のようになります。

{ "mode": "CUSTOM", "videoConfig": { "canvasWidth": 1920, "canvasHeight": 1080, "elements": [ { "publisher": { "id": "*", "query": { "sortBy": "AUDIO_LEVEL", "index": 0 } }, "x": 0, "y": 0, "width": 960, "height": 1080 }, { "publisher": { "id": "*", "query": { "sortBy": "AUDIO_LEVEL", "index": 1 } }, "x": 960, "y": 0, "width": 960, "height": 1080 } ] }, "audioConfig": { "elements": [ { "publisher": { "id": "*", "query": { "sortBy": "AUDIO_LEVEL", "index": 0 } } }, { "publisher": { "id": "*", "query": { "sortBy": "AUDIO_LEVEL", "index": 1 } } } ] } }

音量ソート表示例


publicationの選択

audioPublication または videoPublication プロパティでは以下の識別子から Publisher の Publication を選択できます。

  • id
  • metadata

選択できる Publication は config の種類と同じものに限られます。(audioConfig なら contentType が Audio のもの、videoConfig なら contentType が Video のもの)

publication プロパティを設定しない場合は最初に Publish された Publication が選択されます。

publication プロパティを設定した上で Publication の候補が複数ある場合は、より早く Publish された Publication が選択されます。

識別子の指定方法

id, name, metadata といった識別子は以下の方法で指定できます。

  • id
    • 対象のリソースに設定されている文字列(完全一致)、*(ワイルドカード)
  • name
    • 対象のリソースに設定されている文字列(完全一致)、* を含む文字列(部分一致)、 *(ワイルドカード)
  • metadata
    • 対象のリソースに設定されている文字列(完全一致)、* を含む文字列(部分一致)、 *(ワイルドカード)

name や metadata では、audience-* のような書き方をすることで部分一致で判定できます。

また name や metadata に * を指定した場合はその要素を持たない場合も含みます。

metadata を指定する場合は channel 中の member と publication の metadata に以下のフォーマットのデータを JSON 文字列の形式で格納してください。SKYWAY_SYSTEM.liveStreaming.label の内容と metadata に指定した識別子の内容でマッチングを行うことができます。

{ "SKYWAY_SYSTEM": { "liveStreaming": { "label": "" } } }

識別子で指定可能な文字種は、Channel、Member の name として使用可能な文字種、およびワイルドカードのみとなります。

Channel、Memberのnameとして使用可能な文字種

設定の例

ここでは以下の3種類の合成例を説明します。

  • side by side(横並びの映像)
  • picture in picture(プレゼン用等の表示)
  • Grid(全映像の表示)

side by side

以下のスクリーンショットのような合成を行うための設定について説明します。

Side by Sideレイアウト

{ "mode": "CUSTOM", "videoConfig": { "canvasWidth": 1920, "canvasHeight": 1080, "elements": [ { "publisher": { "id": "*", "query": { "sortBy": "TIMELINE", "index": 0 } }, "x": 0, "y": 0, "width": 960, "height": 1080 }, { "publisher": { "id": "*", "query": { "sortBy": "TIMELINE", "index": 1 } }, "x": 960, "y": 0, "width": 960, "height": 1080 } ] }, "audioConfig": { "elements": [ { "publisher": { "id": "*", "query": { "sortBy": "AUDIO_LEVEL", "index": 0 } } }, { "publisher": { "id": "*", "query": { "sortBy": "AUDIO_LEVEL", "index": 1 } } } ] } }

この例では、話者の音量が大きい上位2名の映像を画面の左と右に表示し、それらの音声を合成して出力しています。

picture in picture

以下のスクリーンショットのような合成を行うための設定について説明します。

PiPレイアウト

{ "mode": "CUSTOM", "videoConfig": { "canvasWidth": 1280, "canvasHeight": 720, "elements": [ { "publisher": { "id": "*", "query": { "sortBy": "TIMELINE", "index": 0 } }, "x": 0, "y": 0, "width": 1280, "height": 720, "zIndex": 0 }, { "publisher": { "id": "*", "query": { "sortBy": "TIMELINE", "index": 1 } }, "x": 960, "y": 540, "width": 320, "height": 180, "zIndex": 1 } ] }, "audioConfig": { "elements": [ { "publisher": { "id": "*", "query": { "sortBy": "AUDIO_LEVEL", "index": 0 } } }, { "publisher": { "id": "*", "query": { "sortBy": "AUDIO_LEVEL", "index": 1 } } } ] } }

この例では screen-share という label を metadata に持った映像を全画面に表示し、 camera という label を metadata に持った映像を小窓に表示しています。またそれらと同じ label を metadata に持った音声を合成して出力しています。

Grid

以下のスクリーンショットのような合成を行うための設定を JavaScript のプログラムで作成する例について説明します。

Gridレイアウト

const canvasWidth = 1280; const canvasHeight = 720; // elementsの数を指定する const numElements = 9; // 列数: 要素数の平方根の切り上げ const columns = Math.ceil(Math.sqrt(numElements)); // 行数: 要素数 ÷ 列数の切り上げ const rows = Math.ceil(numElements / columns); // Canvas サイズから計算する1セルあたりの幅・高さ const cellWidth = Math.floor(canvasWidth / columns); const cellHeight = Math.floor(canvasHeight / rows); const videoElements = [...new Array(numElements).keys()].map((i) => { const row = Math.floor(i / columns); const col = i % columns; return { publisher: { id: "*", query: { sortBy: "TIMELINE", index: i, }, }, x: col * cellWidth, y: row * cellHeight, width: cellWidth, height: cellHeight, }; }); // 音声は最大4つまで合成できるので音量上位4つを設定する const audioElements = [...new Array(4).keys()].map((i) => ({ publisher: { id: "*", query: { sortBy: "AUDIO_LEVEL", index: i, }, }, })); const composite = { mode: "CUSTOM", videoConfig: { canvasWidth, canvasHeight, elements: videoElements, }, audioConfig: { elements: audioElements, }, };

この例では指定した element の数に合わせてレスポンシブに映像を Grid 状に合成します。