録画した映像・音声をクラウドストレージに保存する (クラウド録画)

クラウド録画機能 は、現在 β 版として提供しております。
そのため、商用サービスでの利用をご検討される際には、必ず事前にお問い合わせください。
β 版のクラウド録画機能の利用料金は無料です。正式版は有償での提供を検討しておりますので、あらかじめご了承ください。
正式版を公開せずに β 版の公開を終了する、もしくは、正式版では β 版から機能や仕様が変更される可能性がありますので、あらかじめご了承ください。 クラウド録画機能に関連して現在発生している問題はRICOH Live Streaming クラウド既知の問題を確認してください。

はじめに

この文書では、RICOH Live Streaming を利用して配信した映像・音声を録画してクラウドストレージに保存するクラウド録画機能について紹介します。

クラウド録画機能は RICOH Live Streaming Conference によるブラウザで録画してローカル環境にダウンロードする機能とは異なる機能です。 この機能では、クライアントアプリによって、 RoomInstance に参加している各 Connection の映像・音声を録画を制御し、クラウドストレージに保存できます。

クラウド録画機能は、SFU 型の RoomType でのみ利用可能で、P2P 型の RoomType では利用できません。 RoomInstance に参加している各 Connection の映像・音声を録画し、クライアントアプリによって指定されたコーデックなどの設定に基づいて変換し、クラウドストレージに保存します。 録画の形態には以下の 2 パターンがあり、1 つの RoomInstance に対してそれぞれ独立・同時に実行できます。

  • 各 Connection の映像・音声を個別の録画ファイルとして保存
  • 各 Connection の映像・音声を 1 つの録画ファイルにレイアウトして合成して保存

クラウド録画機能を利用するには、クライアントアプリ側で以下の環境を準備し、これらを RICOH Live Streaming に登録する必要があります。

  • 録画ファイルを保存するための AWS の S3 バケット
  • (オプション) 録画の完了/失敗の通知を受けるための Webhook の API が実装されたアプリケーションサーバー

上記が完了していることを前提として、録画のシーケンスは以下のようになります。

シーケンス

これを実現するために必要な作業について以下に説明します。

録画ファイル保存用の S3 バケットを RICOH Live Streaming に登録する

RICOH Live Streaming のクラウド録画機能では、クライアントアプリ開発者の用意した AWS の S3 バケットに録画ファイルを保存します。 ここでは、以下のステップによって、録画保存用の S3 バケットの設定を RICOH Live Streaming に登録するまでの流れについて説明します。 なお、クライアントアプリ開発者が AWS のアカウントを所持している前提とします。

  • S3 バケットと登録用 URL の作成
  • S3 バケットにアクセス許可するためのアクセスキーの作成
  • RICOH Live Streaming への S3 バケット設定の登録

S3 バケットと登録用 URL の作成

AWS 上で行う手順です。

  1. S3 バケットの作成

    公式のバケットの名前付けルールに従って任意の名前のバケットを作成してください。 RICOH Live Streaming の保存先として利用する S3 バケットについて、リージョンやバケット名の制約はありません。

  2. 登録用 URL の作成

    RICOH Live Streaming に登録する際には、仮想ホスティング形式の URL を利用する必要があります。

    https://<bucket-name>.s3.<region-code>.amazonaws.com/<key-name>

    仮想ホスティング形式の仕様に従って、録画保存用の URL を作成してください。

    • 例: bucket-exampleバケットのrecording以下に録画ファイルを保存する場合の URL
      https://bucket-example.s3.ap-northeast-1.amazonaws.com/recording

S3 バケットにアクセス許可するためのアクセスキーの作成

AWS 上で行う手順です。

RICOH Live Streaming は、上記の S3 バケットにアクセスするのに、IAM ユーザーのアクセスキー ID とシークレットアクセスキーを利用します。 RICOH Live Streaming が録画ファイルを保存するために最低限必要な権限を持った IAM ユーザとアクセスキーの作成について、マネジメントコンソールを利用する方法を例に説明します。

IAM ユーザー作成については AWS アカウント での IAM ユーザーの作成を参照し、以降の手順に従ってください。

  1. IAM ユーザの作成を開始し、任意の IAM ユーザー名を設定して[次へ]を押します IAM ユーザーの詳細を指定

  2. [ポリシーを直接アタッチする]を選択し、[ポリシーの作成]ボタンからユーザーの権限を設定します 許可を設定

  3. [ポリシーの作成]の画面が開くので、[JSON]を選んで JSON エディタをにポリシー設定を入力して[次へ]を押します アクセス許可を指定

    • この画面で録画ファイルの保存に必要な最小限の権限を持つポリシーを設定します
      • 例として次の JSON を使用できますが、Resource<bucket-name>および<key-name>は置き換えてください
      • Resourceの最後の*は必要です
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AllowS3Upload",
          "Effect": "Allow",
          "Action": ["s3:PutObject", "s3:AbortMultipartUpload"],
          "Resource": ["arn:aws:s3:::<bucket-name>/<key-name>/*"]
        }
      ]
    }
  4. 任意のポリシー名を入力し[ポリシーの作成]を実行します IAM ポリシーを確認して作成

  5. 元の IAM ユーザーの[許可を設定]の画面に戻り、更新ボタンを押したあと、4.で入力したポリシー名を検索し、選択して[次へ]を押します

  6. [IAM ユーザーを確認して作成]画面が表示されるので、[ユーザーの作成]を押してユーザーを作成します

  7. 作成した IAM ユーザーの画面を開き、[セキュリティ認証情報]を選択し、[アクセスキーを作成]を押します アクセスキーを作成

  8. [ユースケース]で[その他]を選択して[次へ]を押します アクセスキーのユースケース

  9. [説明タグを設定]は特に不要なので、そのまま[アクセスキーを作成]を押します

  10. アクセスキーが発行されるので、アクセスキーとシークレットアクセスキーを保存しておきます 発行されたアクセスキー

    • シークレットアクセスキーは画面を閉じると後から確認できません
    • [.csv ファイルをダウンロード]するのをお勧めします

RICOH Live Streaming への S3 バケット設定の登録

上記の手順で、S3 バケットの仮想ホスティング形式の URL と、バケットにアクセスするためのアクセスキーが作成されました。 これらを RICOH Live Streaming に登録して、録画ファイルの保存ができるようにします。

  1. 以下のような JSON ファイルを作成し、任意の名前で保存します

    • ここでは recording_s3_config.json という名前で保存したとします
    {
      "s3_url": "<S3 バケットの仮想ホスティング形式の URL>",
      "access_key_id": "<アクセスキーID>",
      "secret_access_key": "<シークレットアクセスキー>"
    }
  2. 上記の設定を RICOH Live Streaming の録画ストレージ設定 API に登録します

    • 以下はcurlを利用して登録する例です
    • <client_id>/<client_secret> は ClientID/ClientSecret に置き換えてください
    curl \
    -u <client_id>:<client_secret> \
    -X POST \
    "https://api.livestreaming.mw.smart-integration.ricoh.com/v1/clients/<client_id>/recording_storages/aws_s3/register" \
    -d @recording_s3_config.json

(オプション) 録画の成功/失敗の通知を受ける Webhook サーバを開発して RICOH Live Streaming に登録する

録画ファイルの作成は、RoomInstance の終了後、非同期に行われ、長時間かかることがあります。 アプリケーションサーバーで Webhook API を実装して、この URL を Live Streaming に登録することで、録画の完了/失敗時に通知を受け取ることができます。

Webhook URL の登録はオプションで、対応しなくてもクラウド録画機能を使うことができます。 録画の完了のタイミングを正確に知る必要があったり、録画失敗の通知を受け取る必要がある場合は Webhook に対応してください。

Webhook API やそれの登録に関する仕様は アクティビティ API を参照してください。

アプリケーションサーバーでの Webhook API の実装

Webhook API では以下の機能が必要です。

  • RICOH Live Streaming への Webhook URL 設定の登録時に API が呼び出されるので、クライアントアプリの正当性を証明するためのレスポンスを返します
  • 録画の完了/失敗の通知を受け取って、クライアントアプリで必要な処理を行います
    • その中で、受け取った通知が RICOH Live Streaming から正当に送信されていることを検証します

以下は、node.js と typescript を利用した Webhook API の実装例です。 POST /webhook に対してリクエストを受け取ります。 サーバーのライブラリとして fastify を利用しています。 録画の完了/失敗通知メッセージの型は ActivityRecordingCompleted および ActivityRecordingFailed で、 API 仕様に説明があります。

import crypto from 'crypto';
import fastify from 'fastify';
import rawBody from 'fastify-raw-body';

// Webhook サーバを起動する
async function startWebhookServer(params: {
  port: number;
  clientSecret: string;
}) {
  const { port, clientSecret } = params;

  const server = fastify();
  await server.register(rawBody);

  // POST /webhook でリクエストを受ける
  server.post('/webhook', async (req, reply) => {
    console.log('webhook api is called');

    const msg = req.body as any;

    // RICOH Live Streaming への Webhook URL 設定の登録時に API が呼び出されるので
    // 正当なクライアントアプリであることを検証するためのレスポンスを返す
    if (msg.type === 'webhook.verification') {
      console.log('verification event:', msg);

      // チャレンジシグネチャの返却
      return {
        challenge_signature: createSignature(clientSecret, msg.challenge),
      };
    }

    // 以降は通常の Webhook 通知時の処理

    // RICOH Live Streaming からの正当な通知であることを検証
    const sig = req.headers['x-ricoh-ls-signature'];
    if (sig !== createSignature(clientSecret, req.rawBody as string)) {
      console.error('invalid signature');
      reply.status(400);
      return 'invalid signature';
    }

    switch (msg.type) {
      case 'recording.completed':
        handleRecordingCompleted(msg);
        break;
      case 'recording.failed':
        handleRecordingFailed(msg);
        break;
      default:
        // それ以外のイベント
        break;
    }
    return 'ok';
  });

  await server.listen({ port });
}

function handleRecordingCompleted(msg: any) {
  // 録画完了時の処理を実行
  // メッセージの型は ActivityRecordingCompleted
}

function handleRecordingFailed(msg: any) {
  // 録画失敗時の処理を実行
  // メッセージの型は ActivityRecordingFailed
}

// 正当性検証のためのシグネチャを作成する
function createSignature(key: string, data: string) {
  const hmac = crypto.createHmac('sha256', key);
  hmac.update(data);
  return `sha256=${hmac.digest('hex')}`;
}

async function main() {
  console.log('start webhook server');
  await startWebhookServer({
    port: 8000,
    clientSecret: 'CLIENT_SECRET',
  });
}

main();

なお、RICOH Live Streaming に登録する Webhook URL は、https:// から開始している必要があります。 すなわち、信頼された認証局によって発行された証明書を利用して TLS を終端するロードバランサーをアプリケーションサーバーの前段に配置するなどの構成が必要です。

RICOH Live Streaming への Webhook URL 設定の登録

作成した Webhook API の URL を RICOH Live Streaming に登録します。

  1. 以下のような JSON ファイルを作成し、任意の名前で保存します

    • ここでは webhook_config.json という名前で保存したとします
    {
      "webhook_url": "https://<アプリケーションサーバーのホスト名>/webhook"
    }
    • webhook_url のパスに /webhook をつけているのは、上記のサンプルコードで /webhook のパスでリクエストを受けるようにしているからです。
      • ここは実際のアプリケーションサーバーの設計に従って変更してください。
  2. 上記の設定を RICOH Live Streaming のアクティビティ Webhook 設定登録 API に登録します

    • 以下はcurlを利用して登録する例です
    • <client_id>/<client_secret> は ClientID/ClientSecret に置き換えてください
    curl \
    -u <client_id>:<client_secret> \
    -X POST \
    "https://api.livestreaming.mw.smart-integration.ricoh.com/v1/clients/<client_id>/activity/webhook/register" \
    -d @webhook_config.json

録画を有効にして RoomInstance を作成する

これまでに説明した準備ができている状態で、Access Token に録画の設定をすると、RoomInstance を録画できます。 Access Token の仕様の詳細については Access Token 外部仕様 を参照してください。

Connection ごとの単一拠点録画の設定と、合成録画の設定をそれぞれ独立に行うことができます。

以下では、Access Token の JWT Claims の録画設定について説明します。 クラウド録画機能以外の JWT Claims の設定に関する説明はここでは省略します。

共通で必要な Access Token の設定

録画するのに最低限必要な JWT Claims の設定は以下です。

  • room_spec

    • type: sfu または sfu_large が必要で、P2P 型の Room では録画できません
    • recording_on_start: RoomInstance の開始とともに録画を開始する設定で、現状はこれを true にすることによってのみ録画できます
    • storage: 録画ファイルの保存先の設定で、現状は aws_s3 にする必要があります
  • {
      "room_spec": {
        "type": "sfu", // または "sfu_large"
        "recording": {
          "recording_on_start": true,
          "storage": "aws_s3"
        }
      }
    }

各 Connection ごとの単一拠点録画の設定

各 Connection ごとの単一拠点録画の JWT Claims の設定は以下です。

  • connection_spec

    • recording
      • store: その Connection の録画ファイルを保存するかどうかの設定で、デフォルトは true です
      • format: 録画ファイルのフォーマットで、現状は mp4 のみサポートしており、デフォルトは mp4 です
      • video:
        • codec: ビデオコーデックの設定で、h264vp9 から選択でき、デフォルトは h264 です
      • audio:
        • codec: オーディオコーデックの設定で、aacopus から選択でき、デフォルトは aac です
  • {
      "connection_spec": {
        "recording": {
          "store": true,
          "format": "mp4",
          "video": {
            "codec": "h264"
          },
          "audio": {
            "codec": "aac"
          }
        }
      }
    }

合成録画の設定

合成録画の JWT Claims の設定は以下です。

  • room_spec

    • recording
      • composition_recording
        • enabled: 合成録画を有効にするかどうかで、デフォルトは false です
        • format: 録画ファイルのフォーマットで、現状は mp4 のみサポートしており、デフォルトは mp4 です
        • video:
          • resolution: 合成録画の解像度を指定、詳細は Access Token 外部仕様 を参照してください
          • max_bitrate_kbps: 合成録画のビットレートの最大値を指定、詳細は Access Token 外部仕様 を参照してください
        • audio:
          • codec: オーディオコーデックの設定で、aacopus から選択でき、デフォルトは aac です
  • connection_spec

    • recording
      • composition
        • use_video: 合成録画にその Connection の映像を含めるかどうかの設定で、デフォルトは true です
        • use_audio: 合成録画にその Connection の音声を含めるかどうかの設定で、デフォルトは true です
  • 制約として、全ての Connection の connection_spec.recording.composition.use_videofalse の場合、合成録画は失敗します

  • {
      "room_spec": {
        "type": "sfu",
        "recording": {
          "recording_on_start": true,
          "storage": "aws_s3",
          "composition_recording": {
            "enabled": true,
            "format": "mp4",
            "video": {
              "resolution": "auto",
              "max_bitrate_kbps": "auto"
            },
            "audio": {
              "codec": "aac"
            }
          }
        }
      },
      "connection_spec": {
        "recording": {
          "composition": {
            "use_video": true,
            "use_audio": true
          }
        }
      }
    }

録画ファイルの出力

正しい Access Token が設定されて RoomInstance が実行されると、RoomInstance の終了後に、登録された AWS S3 バケットに録画ファイルが出力されます。 ただし、録画ファイルの作成は、RoomInstance の終了後、非同期に行われ、長時間かかることがあります。

出力されるファイルパスの仕様は、録画 API 仕様のディレクトリ構成仕様を参照してください。 出力されるファイルは、各 Connection ごとの単一拠点録画ファイルと合成録画ファイル、および、それらの録画ファイルの情報が記載されたメタデータファイル (JSON) です。

また、録画 API 仕様に記載の通り、保存先の S3 オブジェクトのキー名に room_id が含まれます。 room_id の仕様は IDString なので、S3 のオブジェクトキー名に使用しないほうが良い文字の一部を利用でき、指定された room_id を含むキー名に対して録画ファイルが保存されます。 その場合、AWS のドキュメントに記載されているように、S3 オブジェクトの取り扱いにはクライアントアプリ側で特殊な処理が必要になる可能性があります。 クライアントアプリでの特殊な処理を避けたい場合は、これらの文字を含めずに room_id を作成してください。

この情報は役に立ちましたか?