RICOH Live Streaming アプリケーション開発者ガイド

本文書はRICOH Live Streamingサービスを用いたアプリケーションの開発者向けにサービスの使い方を解説する文書です

利用フロー

  1. 実際に動作確認する場合、Client ID/Secretが必要です
  2. RICOH Live Streamingサービスと認証連携できるアプリケーションサーバを開発しデプロイしてください

クラウド環境について

  • 弊社から提供する環境には「本番環境」と「Dev環境」の2つがあります
  • Client SDKのconnect APIに与えるオプションにて接続先の切り替えが可能です
    • 接続先を指定しない場合は「本番環境」に接続します

本番環境

  • 本番環境は下記目的のために提供を行います
    • アプリケーション開発者が正式リリース済みのAPIを利用して開発を行えるようにする
    • アプリケーション開発者が展示会等へのアプリケーションの出展、エンドユーザー候補などへのデモを行う
    • アプリケーション開発者がエンドユーザーにサービスの提供を行う

本番環境の利用について

  • 稼働時間: 24時間365日明示的には停止しません
  • メンテナンスを最大で月1回実施します
    • 実施日時についてはその都度事前にご連絡します

本番環境のエンドポイント

  • Signaling Room API: wss://signaling.livestreaming.mw.smart-integration.ricoh.com/v1/room
    • 接続先を特に指定せずに接続を行った場合、デフォルトで上記エンドポイントに接続されますので明示的に設定する必要はありません

本番環境のサービス稼働状況ページ

Dev環境

  • Dev環境は下記目的のために提供をおこないます
    • 本番環境にリリース済のバージョンに対して非互換の仕様変更となるリリースが予定される場合、アプリケーション開発者が事前に新しい仕様でアプリケーションの開発と評価を行えるようにする
    • 大規模な新規機能追加が予定される場合、アプリケーション開発者が本番環境リリース前にアプリケーションの開発と評価を行えるようにする
    • Dev環境で提供されるサービスの仕様は、本番環境リリースまでの間に「取りやめ」や「仕様変更」などされる可能性がありますのであらかじめご了承ください
  • 上記目的に合致する先行リリース機能等が無い期間については、Dev環境はクローズし本番環境のみの提供となりますのであらかじめご了承ください

Dev環境の利用について

  • 稼働時間: 24時間365日明示的には停止しません
  • ただし以下の時間帯は保守やアップデートなどの為の定期メンテナンス枠となります
    • 毎週火曜日 14:00-18:00
    • (特に対応が必要な項目が無い場合、メンテナンスを予告なくスキップする事があります)
    • デモ利用などの理由で上記時間帯も稼働を希望する場合は、事前にリコーの窓口にお問い合わせください

Dev環境のエンドポイント

  • Signaling Room API: wss://signaling-dev.livestreaming.mw.smart-integration.ricoh.com/v1/room

Dev環境のサービス稼働状況ページ

接続先設定例

ClientSDK for Web

  const connectOption = {
    localLSTracks: lsTracks,
    // signalingURLにDev環境のエンドポイントを設定
    signalingURL: "wss://signaling-dev.livestreaming.mw.smart-integration.ricoh.com/v1/room", 
  };
  client.connect("CLIENT_ID", access_token, connectOption);

ClientSDK for Android

  val option = Option.Builder()
          .localTracks(localTracks)
          .signalingURL("wss://signaling-dev.livestreaming.mw.smart-integration.ricoh.com/v1/room")
          .build()

  mClient!!.connect(
          "CLIENT_ID",
          accessToken,
          option)

ClientSDK for Windows(プロトタイプ)

  var option = new Option()
      .SetLocalTracks(localTracks)
      .SetSignalingURL("wss://signaling-dev.livestreaming.mw.smart-integration.ricoh.com/v1/room");

  client.Connect("CLIENT_ID", accessToken, option);

解説

コネクションがルームに入室するまでのフロー

コネクションがルームに入室するまでのフロー

コネクションがP2P会議を開始するフロー

コネクションがP2P会議を開始するフロー

アクセストークンの生成

サンプル

JavaScript (Node.js)

const jwt = require("jsonwebtoken");
const moment = require("moment");

CLIENT_SECRET = "sample_client_secret";

function generateToken() {
  const nbf = moment().unix();
  const exp = moment().add(30, "seconds").unix();
  const connection_id = "conn1";
  const room_id = "room1";
  const room_spec = { type: "sfu" };

  return new Promise((res, rej) => {
    jwt.sign(
      { nbf, exp, connection_id, room_id, room_spec },
      CLIENT_SECRET,
      { algorithm: "HS256" },
      (err, token) => (err ? rej(err) : res(token))
    );
  });
}

Elixir

# {:jose, "~> 1.10"} を依存に追加しているものとする
client_secret = "sample_client_secret"
jwk = %{"kty" => "oct", "k" => :jose_base64url.encode(client_secret)}
jws = %{"alg" => "HS256"}

jwt = %{
  "nbf" => DateTime.utc_now() |> DateTime.to_unix(),
  "exp" => (DateTime.utc_now() |> DateTime.to_unix()) + 30,
  "room_id" => "room1",
  "connection_id" => "conn1",
  "room_spec" => %{ "type" => "p2p" }
  "tags" => [%{"name" => "user_id", "value" => 1, "use_notification" => true}]
}

{_alg, token} = JOSE.JWT.sign(jwk, jws, jwt) |> JOSE.JWS.compact()

Java


import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;

import javax.crypto.SecretKey;

import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

class AccessToken {
  public String getAccessToken(
    String connectionId,
    String clientSecret,
    String roomId,
    String type,
    Integer maxConnections,
    Integer bitrateReservationMbps)
    {
      JwtBuilder builder = Jwts.builder();
      byte[] secretByteArray = clientSecret.getBytes(StandardCharsets.US_ASCII);
      SecretKey key = Keys.hmacShaKeyFor(secretByteArray);
      Calendar now = Calendar.getInstance();
      Date nbf = now.getTime();
      now.add(Calendar.MINUTE, 30);
      Date exp = now.getTime();

      Map<String, Object> mediaControl = new HashMap<String, Object>() {
        {
          put("bitrate_reservation_mbps", bitrateReservationMbps);
        }
      };
      Map<String, Object> spec = new HashMap<String, Object>() {
        {
          put("type", type);
          put("max_connections", maxConnections);
          put("media_control", mediaControl);
        }
      };

      return builder
        .claim("connection_id", connectionId)
        .claim("room_id", roomId)
        .claim("room_spec", spec)
        .setNotBefore(nbf)
        .setExpiration(exp)
        .signWith(key, SignatureAlgorithm.HS256)
        .compact();
    }
  }
}