本文へスキップ
Esc

Web SDK

このページの内容

@rerinku/player は Rerinku View SDK の Web 向けの部分です。純粋な TypeScript で書かれ、どのフロントエンドフレームワークにも依存せず、Apache-2.0 のオープンソースです。

  • OnboardClient:Rerinku View オープン API のクライアントです。デバイス、ストリーム、サムネイル、稼働状態、WebRTC のシグナリングを扱います。
  • RerinkuPlayer:用意された <video> 上で、デバイスのライブ映像(WebRTC)や録画(HLS)を再生し、切断されると自動で再接続します。UI は一切持たず、状態は DOM イベントで通知されるので、HTMLMediaElement と同じように使えます。
  • @rerinku/player/engine:低レベルのエンジンです。シグナリングとライフサイクルを自分で管理したい場合に使います。

インストール

npm install @rerinku/player

ES モジュールと型定義で約 10 KB(gzip)です。hls.js は、録画を再生するときにだけ必要に応じて読み込まれます。バンドラーを使わないページでは、IIFE 版を直接読み込めます。IIFE 版はグローバルオブジェクト Rerinku を作ります。

<script src="https://unpkg.com/@rerinku/player/dist/rerinku-player.iife.js"></script>

クイックスタート

import { OnboardClient, RerinkuPlayer } from "@rerinku/player";

// 1. Rerinku View に接続する。閲覧トークンは読み取り専用なので、公開の Web ページに書いてよい。
const client = new OnboardClient({
  baseUrl: "https://n1234.nodes.rerinku.com",
  token: "<閲覧トークン>",
});

// 2. <video> の上にプレーヤーを作る。要素はミュートの自動再生に設定される。
const video = document.querySelector("video")!;
const player = new RerinkuPlayer(video, { client });
player.addEventListener("statuschange", (e) => console.log(e.detail.state));

// 3. デバイスを 1 台選んで再生を始める。最初のフレームが出ると load() が完了し、切断されるとプレーヤーが自動で再接続する。
const devices = await client.listDevices();
await player.load({ kind: "live", device: devices[0] });

// 不要になったら
player.destroy();

バンドラーを使わない場合も書き方はまったく同じで、クラスをグローバルオブジェクトから取り出すだけです。

<video muted playsinline autoplay></video>
<script src="https://unpkg.com/@rerinku/player/dist/rerinku-player.iife.js"></script>
<script>
  const { OnboardClient, RerinkuPlayer } = Rerinku;
  const client = new OnboardClient({ baseUrl: "https://n1234.nodes.rerinku.com", token: "<閲覧トークン>" });
  const player = new RerinkuPlayer(document.querySelector("video"), { client });
  client.listDevices().then((devices) => player.load({ kind: "live", device: devices[0] }));
</script>

SDK リポジトリの examples/quickstart/ には、完全な Web ページ版(index.html。カメラの切り替えと状態表示付きで、そのまま開くだけで動きます)と TypeScript 版(main.ts)があります。

認証

どのサイトの Web ページからでもクロスオリジンで Rerinku View を呼び出せますが、ほかのサイトからのリクエストにはトークンが必要です。

  • 公開の Web ページ(公式サイトのデモ、店舗のサイネージ、自分のサイト):Rerinku View の 設定 → 開発者 で読み取り専用の閲覧トークンを作成し、token で渡します。login() は呼ばないでください。このトークンでできるのは、デバイスの一覧(機密性のあるフィールドは除去済み)、サムネイルの取得、稼働状態の読み取り、ライブ映像の取得だけです。
  • サーバー側のプログラムとネイティブアプリ:client.login(password) を呼び、モバイルアプリと同じように紐付けを行います。Rerinku View にアクセスパスワードが設定されていなければ、パスワードは不要です。
  • ほかのサイトの Web ページが login() でフル権限のトークンを取得できるのは、Rerinku View にアクセスパスワードが設定されている場合だけです。

トークンはメモリ上にだけ保持されます。保存するかどうかは利用する側で決めてください。コンストラクターに token で渡し、tokenchange イベントを監視します。このイベントは、ログイン時、ログアウト時、そしてサーバーがトークンの取り消しを確認したときに発生します。

const client = new OnboardClient({ baseUrl: "http://192.168.1.10:8080", token: saved });
client.addEventListener("tokenchange", (e) => save(e.detail)); // 取り消されると e.detail は null
if (!client.token) {
  await client.login("", { name: "店舗ダッシュボード", installId: "dash-0001" }); // アクセスパスワードを設定しているならパスワードを指定
}

同じ installId で再びログインしても、トークンが新しくなるだけで、許可が 1 件増えることはありません。すべてのトークンは 設定 → 開発者 → 許可済みのアプリ に一覧され、いつでも取り消せます。

OnboardClient

new OnboardClient({ baseUrl, token, fetch })

オプション 説明
baseUrl Rerinku View のアドレス。例:https://n1234.nodes.rerinku.com。空文字列はページと同じオリジンを表します
token 以前のログインで得たトークン、または閲覧トークン
fetch カスタムの fetch(テストやサーバーサイドレンダリングで使用)

すべてのメソッドは Promise を返し、最後の引数でキャンセル用の { signal }(AbortSignal)を受け取ります。リクエストが失敗すると OnboardAPIError(status と code 付き。例:invalid_token)を、シグナリングが失敗すると SignalingError を投げます。

メソッド 説明
getInfo() サーバーの ID、名前、API バージョン。トークンは不要
login(password, { name, installId, appVersion }) アクセスパスワードと引き換えにトークンを取得
logout() 現在のトークンを取り消す
listDevices() デバイスの一覧 OnboardDevice[]
listStreams(deviceId) デバイスのストリーム(メインストリーム、サブストリーム、チャンネル)
getThumbnail(deviceId) サムネイル JPEG の Blob。<img> ではトークンを付けられないので、URL.createObjectURL で表示します
getRuntime(deviceId) デバイスの現在の稼働状態(tempC、cpuPct など)。プラットフォームは同じデバイスについて 2 秒以内は結果を使い回すので、それより速くポーリングしないでください
getIceServers() ライブ映像用の STUN/TURN。認証情報には期限があるので、長期間キャッシュしないでください
sendOffer(deviceId, sdp, { streamId }) WebRTC のシグナリング:offer を送り、answer を返します

プロパティ:baseUrl、token(代入可)。イベント:tokenchange(detail は新しいトークンまたは null)。

RerinkuPlayer

new RerinkuPlayer(video, { client, manageVideo })

オプション 説明
client OnboardClient、または sendOffer と getIceServers を実装した任意のオブジェクト。ライブ映像の再生には必須です
manageVideo 既定は true:要素をミュート、インライン、自動再生に設定します(ブラウザーはミュートの自動再生しか許可しないため)。false を渡すと、要素には一切手を加えません
メンバー 説明
load(source) { kind: "live", device, streamId? } または { kind: "hls", url } を再生します。null を渡すと停止します
unload() 再生を止めて接続を解放します
retry() すぐに再接続します:デバイスのオフライン待ちの間や、再試行可能なエラーのあとに使います
destroy() すべてのリソースを解放します
status 現在の状態 PlayerStatus
source 直近の load() に渡したソース

load() は、最初のフレームが画面に表示されると完了(resolve)します。プレーヤーがエラーで止まった場合は PlayerError で reject し、新しい load()、unload()、destroy() によって中断された場合は、名前が AbortError の DOMException で reject します。ライブのソースでオフラインのデバイスを待っている間は Promise が未完了のままなので、その間は statuschange を見てください。

イベント detail
statuschange 新しい PlayerStatus
stats ライブ接続の統計 LiveConnectionStats(約 2 秒ごと)。終了時は null
error PlayerError(code、detail、retryable)

streamId で、デバイスの特定のストリームを選べます。たとえば解像度の低いサブストリームです。指定しなければ、デバイスの既定のストリームを再生します。プレーヤーは再接続のたびに、その前に TURN の認証情報を取得し直します。

再生状態

state 意味
idle ソースがない
connecting 接続を確立中。何を待っているかは code で分かります
playing 映像が表示されている
offline 自動で再接続中。reason は device(サーバーがデバイスのオフラインを確認)か network です。ほかに retryInMs、attempt があります
error 対応が必要。retryable は retry() で回復できるかどうかを表します

message は英語の予備の文言です。多言語に対応する場合は、code に応じて独自の文言を選んでください。

code 意味
connecting、waiting_frame、waiting_keyframe 接続を確立中、映像を待っている
stalled 映像が出たあとでストリームが止まり、最後のフレームで静止している
relay_switch 直接接続の品質が悪いため、クラウドのリレーに切り替え中
no_signaling client が指定されていない
signaling_rejected サーバーがこのセッションを拒否した。detail はサーバーのエラーコード
codec_unsupported ブラウザーがこのコーデックに対応していない。detail はコーデック名
h265_unsupported ブラウザーに WebRTC の H.265 デコード機能がない(Safari にはあり、Chrome ではハードウェアデコードが必要)
hls_failed、hls_media_failed、hls_unsupported、hls_player_load_failed 録画の再生に失敗した

ブラウザーと制限

  • ライブ映像には、WebRTC に対応したモダンブラウザーが必要です。H.264 はどのブラウザーでも再生できます。H.265 はブラウザーの WebRTC デコード機能しだいです。SDK は接続を確立する前に確認し、対応していなければすぐに h265_unsupported を返すので、無駄にストリームを取得することはありません。
  • 映像は既定でミュートのまま自動再生されます。音声が必要な場合は、ユーザーの操作のあとでミュートを解除してください。
  • 録画(HLS)のアドレスは、自分のバックエンドで用意し、認証も処理する必要があります。ブラウザーの HLS リクエストには Authorization リクエストヘッダーを付けられないためです。

低レベルのエンジン

@rerinku/player/engine は createWebRTCEngine(video, source, callbacks, options) と createHLSEngine(video, source, callbacks) をエクスポートします。1 つのエンジンが 1 回のセッションに対応し、シグナリングは options.offer で注入し、状態はコールバックで返されます。RerinkuPlayer はこれらの上に作られています。使う必要があるのは、シグナリングとライフサイクルを自分で管理したい場合だけです。