クイックスタート

ソースから SENCA をビルドして 1 台のノードを起動し、ストリームを作成して RTMP で配信し、HLS で再生するまでの手順です。Docker で起動する方法も紹介します。

はじめに

このページの見出し
  1. 必要なもの
  2. ビルドする
  3. コーデックのライブラリ
  4. ノードを起動する
  5. 管理者トークンを取り出す
  6. ストリームを作成する
  7. RTMP で配信する
  8. 再生 URL を取得して再生する
  9. 録画する(任意)
  10. 停止する
  11. Docker で動かす
  12. 次に読むページ
  13. 関連するページ

ソースから SENCA をビルドして 1 台のノードを起動し、OBS や FFmpeg から RTMP で送った映像を HLS で再生するまでを順にたどります。Docker で起動する方法は最後にあります。

先に知っておくとつまずかない点が 2 つあります。ストリームを作ったときに返る stream_key は 1 回しか表示されません。また、ライブの再生には有効期限のある署名付き URL が必要です。

コマンドは Linux x86_64(Ubuntu 26.04)で動作を確かめています。

必要なもの

  • Linux(コーデックを動かす別プロセスの権限を絞るために、Linux の seccomp と Landlock を使います)
  • Rust 1.90 以上(Cargo.toml の rust-version で指定しています)と、C のリンカー
  • 試しに配信・再生するための FFmpeg(任意です。OBS やほかのプレイヤーでもかまいません)
  • ロイヤリティフリーのコーデックのライブラリ(任意です。下の「コーデックのライブラリ」を参照してください)

ビルドする

本体とコーデック用のプログラムをビルドします。

cargo build --release -p senca-node -p senca-codec-worker

target/release/ に senca-node と senca-codec-worker ができます。senca-node は自分と同じディレクトリにある senca-codec-worker を起動するので、2 つは同じ場所に置いておきます。どうしても別の場所に置くなら、--codec-worker-bin でその場所を指定してください。

キャプチャデバイスを使うときは、コマンドに -p senca-capture も加えます。これで senca-capture-worker もできます。

コーデックのライブラリ

AV1・VP8/VP9・Opus のエンコードとデコードには、次の共有ライブラリを使います。senca-codec-worker が実行時に dlopen で読み込みます。

なくてもノードは動き、受け取った映像・音声をそのまま配信・録画するところまではできます。変換・静止画・サムネイルだけが使えず、503 になります。

ライブラリ(soname)用途Ubuntu 26.04 のパッケージ
libdav1d.so.7AV1 のデコードlibdav1d7
libSvtAv1Enc.so.2AV1 のエンコードlibsvtav1enc2
libvpx.so.12VP8・VP9 のエンコードとデコード(libvpx 1.16 の ABI だけに対応)libvpx12
libopus.so.0Opus のエンコードとデコードlibopus0

ライブラリは次の順に探します。

  1. --codec-lib-dir DIR で指定したディレクトリに、その名前のファイルがあれば読み込みます。 --codec-lib-dir を指定しない場合は、環境変数 SENCA_CODEC_LIB_DIR の値を使います。 --codec-lib-dir を指定すると、その値で SENCA_CODEC_LIB_DIR を置き換えて senca-codec-worker に渡します。値は : で区切って複数指定できます。
  2. 見つからなければ、ファイル名だけを指定して dlopen します。この場合は OS の標準の探し方(ld.so.cache や LD_LIBRARY_PATH)に従います。

ディストリビューションのパッケージで入れたなら、--codec-lib-dir は要りません。別の場所に置いたライブラリを使うときだけ指定します。どのコーデックを読み込めたかは、GET /api/v1/capabilities の応答の codecs.transcode でわかります。

H.264/H.265 のソフトウェアコーデックは同梱しておらず、外から読み込むこともしません。H.264/H.265 を変換したい場合は、GPU とメーカーのドライバーを用意してください(コーデックと特許 を参照)。

ノードを起動する

./target/release/senca-node --data-dir ./data \
  --http 127.0.0.1:8080 --rtmp 127.0.0.1:1935 \
  --console-dir ./apps/console

--data-dir は必ず指定してください。省くとカレントディレクトリの out にデータを置きます。

待ち受けるアドレスの既定は HTTP が 0.0.0.0:8080、RTMP が 0.0.0.0:1935 です。この例では 127.0.0.1 を指定して、同じマシンからの接続だけを受け付けています。

API の応答や再生 URL には、外から見たときの URL(公開 URL)が入ります。既定は http://127.0.0.1:8080 と rtmp://127.0.0.1:1935 です。ポート番号や外から見たホスト名がこれと違うなら、--public-http-url と --public-rtmp-url で合わせます(設定 を参照)。

起動すると、標準エラー出力に次のようなログが出ます(サンドボックスに関する行は省いています)。

created the first admin token in ./data/control/bootstrap-admin-token (mode 0600)
2026-11-03T01:10:04.936Z senca-node 0.0.0 started (node f1be5f27675d35f8dd72b88676be8754)
2026-11-03T01:10:04.936Z http listening on 127.0.0.1:8080
2026-11-03T01:10:04.936Z rtmp listening on 127.0.0.1:1935
2026-11-03T01:10:04.942Z grid: registered (cpu 7200 m, mem 20422 MB, gpus 0, capture 0)
2026-11-03T01:10:04.942Z grid: became the scheduler (leader)

次の 2 つが ok と ready を返せば、ノードは動いています。

curl -s http://127.0.0.1:8080/healthz   # ok
curl -s http://127.0.0.1:8080/readyz    # ready

管理者トークンを取り出す

API を呼ぶにはトークンが要ります。既定のパスワードというものはなく、初回の起動時に作られる管理者トークンを使います。トークンは data_dir/control/bootstrap-admin-token(パーミッション 0600)に書き込まれ、権限は tenant:admin と node:admin、テナントは default、有効期限はありません。

これをシェルの変数に読み込んでおきます。

TOKEN=$(cat ./data/control/bootstrap-admin-token)

何でもできるトークンなので、試し終えたら用途ごとに権限を絞ったトークンを作り、このファイルは安全な場所へ移すか削除してください(セキュリティ を参照)。

ストリームを作成する

ストリームは配信 1 本の単位です。配信を受け付ける前に、まずこれを作ります。

curl -s -X POST http://127.0.0.1:8080/api/v1/streams \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"name":"demo"}'

応答(201、一部を抜粋):

{
  "id": "60dd5cca4fa2785a5d8eefc3b1f5d1bc",
  "name": "demo",
  "generation": 1,
  "desired_state": "running",
  "observed_state": "waiting_input",
  "hls": {"container": "ts", "segment_ms": 2000, "window": 6},
  "ingest": {
    "rtmp_url": "rtmp://127.0.0.1:1935/live",
    "stream_key": "sk_zgo54TfcU8PEPmrJDH34OHnjYR5Ot6nv__hlyLSf4pk",
    "whip_url": "http://127.0.0.1:8080/whip/60dd5cca4fa2785a5d8eefc3b1f5d1bc"
  }
}

stream_key が返されるのは、この応答と、キーを再発行したとき(POST /api/v1/streams/{id}/keys)だけです。 サーバーにはハッシュ値しか残らないので、ここで控えてください。

ID とキーはこのあと何度も使うので、変数に入れておきます。

SID=60dd5cca4fa2785a5d8eefc3b1f5d1bc
KEY=sk_zgo54TfcU8PEPmrJDH34OHnjYR5Ot6nv__hlyLSf4pk

RTMP で配信する

FFmpeg で試験用の映像と音声を送る

ffmpeg -re -f lavfi -i testsrc2=size=1280x720:rate=30 \
  -f lavfi -i sine=frequency=440:sample_rate=48000 \
  -c:v libx264 -preset veryfast -tune zerolatency -g 60 -pix_fmt yuv420p \
  -c:a aac -b:a 128k \
  -f flv "rtmp://127.0.0.1:1935/live/$KEY"

配信先の URL は、rtmp_url の後ろに stream_key をつなげたものです。RTMP の app 名は live で、live で始まる名前でもかまいません。

キーフレームの間隔は、HLS のセグメントの長さ(既定 2 秒)以下にします。上の例は 30 fps で -g 60 なので、ちょうど 2 秒ごとです。

OBS から配信する

[設定]→[配信]を次のようにします。

  • サービス: カスタム
  • サーバー: rtmp://127.0.0.1:1935/live
  • ストリームキー: sk_...(作成時に返された stream_key)

あわせて[出力]で、キーフレームの間隔を 2 秒以下にしておきます。

配信が届いたことを確かめる

配信が届くと、GET /api/v1/streams/{id} の応答の observed_state が live に変わり、live の項目に受け取ったトラックの情報が入ります。

curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8080/api/v1/streams/$SID

再生 URL を取得して再生する

ライブの再生には署名付きの URL を使います。発行するトークンには subscribe の権限が必要です。

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8080/api/v1/streams/$SID/playback-url
{
  "expires_at": "2026-11-03T01:16:01Z",
  "playback": {
    "hls": "http://127.0.0.1:8080/s/1793668561/nWqDQOWkMTMY3Z2GoC94Rw/live/60dd5cca4fa2785a5d8eefc3b1f5d1bc/index.m3u8",
    "rtmp": "rtmp://127.0.0.1:1935/play/60dd5cca4fa2785a5d8eefc3b1f5d1bc?exp=1793668561&sig=nWqDQOWkMTMY3Z2GoC94Rw",
    "whep": "http://127.0.0.1:8080/whep/60dd5cca4fa2785a5d8eefc3b1f5d1bc?exp=1793668561&sig=nWqDQOWkMTMY3Z2GoC94Rw"
  }
}

本文を省くと、URL の有効期間は 300 秒です。1 時間使いたければ {"ttl_secs": 3600} のように送ります。指定できるのは 1 秒から --max-playback-ttl(既定 86400 秒)までです。期限切れの URL や署名が合わない URL には 403 が返ります。なお whep の URL は、--webrtc-udp を指定したノードでしか使えません(取り込みと再生 を参照)。

受け取った hls の URL で再生してみます。

ffplay "http://127.0.0.1:8080/s/.../index.m3u8"
# または
ffprobe -v error -show_entries stream=codec_name,width,height -of compact "http://127.0.0.1:8080/s/.../index.m3u8"

ブラウザーなら hls.js などの HLS プレイヤーで再生できます。署名付き URL の応答には Access-Control-Allow-Origin: * が付くので、別のオリジンのページからでも読めます。

管理画面は http://127.0.0.1:8080/console/ で開き、API トークンでログインします。ただし管理画面のプレイヤーは fMP4 の HLS か WHEP しか再生できず、既定の TS 形式のストリームは映りません。形式は hls.container で切り替えられます(取り込みと再生 を参照)。

録画する(任意)

録画を始めて、一覧に出てくることを確かめます。

curl -s -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{}' \
  http://127.0.0.1:8080/api/v1/streams/$SID/recordings          # 202 が返り、state は recording
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8080/api/v1/recordings

録画の停止、VOD での再生、MP4 へのエクスポートについては、録画 を参照してください。

停止する

Ctrl-C(SIGINT)か SIGTERM で止まります。録画中のものがあれば finalized として閉じてから終了します。SIGKILL や停電で強制的に止まったときは、書き込み途中だった録画を次の起動時に interrupted として閉じます(運用 を参照)。

Docker で動かす

リポジトリの Dockerfile と compose.yaml で、1 台のノードを立ち上げられます。

docker compose up -d --build
docker compose exec senca cat /var/lib/senca/control/bootstrap-admin-token

1 行目でイメージをビルドして起動し、2 行目で管理者トークンを表示します。接続先は次のとおりです。

  • 管理 API・HLS・管理画面: http://localhost:8080(管理画面は /console/)
  • RTMP: rtmp://localhost:1935/live、SRT: localhost:9000/udp
  • 公開 URL は、compose の変数 SENCA_PUBLIC_HTTP(既定は http://localhost:8080)と SENCA_PUBLIC_RTMP(既定は rtmp://localhost:1935)で変えられます。 例: SENCA_PUBLIC_HTTP=https://media.example.com docker compose up -d

イメージの中身:

項目内容
ベースイメージUbuntu 26.04(libvpx 1.16、つまり libvpx.so.12 が入っているため)
実行ファイル/opt/senca/bin/senca-node・senca-codec-worker・senca-capture-worker
コーデックのライブラリlibdav1d7・libvpx12・libopus0・libsvtav1enc2。GPU 用に libva2・libva-drm2・libvpl2 も入っています。--codec-lib-dir /usr/lib/x86_64-linux-gnu を指定しています
実行ユーザーsenca(uid 10001)。compose では、ルートファイルシステムを読み取り専用にし、/tmp を tmpfs にし、no-new-privileges を指定しています
データボリューム /var/lib/senca(--data-dir)
管理画面・配信ページ/opt/senca/console(/console/ で開く)・/opt/senca/sender(/sender/ で開く)
ヘルスチェックsenca-node --healthcheck http://127.0.0.1:8080/readyz(10 秒ごと)
公開するポート8080/tcp・1935/tcp・9000/udp・8443/udp

--data-dir・--console-dir・--sender-dir・--codec-lib-dir はイメージの ENTRYPOINT で固定してあり、待ち受けるアドレスは CMD(compose では command)で渡します。command を書き換えるときは、--http なども含めて全部書き直してください。

WebRTC(WHIP・WHEP・ルーム)は、既定で UDP の 8443 番(--webrtc-udp 0.0.0.0:8443)を使います。ブラウザーなどの相手に知らせる IP アドレス(ICE の候補)は compose の変数 SENCA_PUBLIC_IP で指定します。既定の 127.0.0.1 のままだと、同じマシンのブラウザーからしかつながりません。たとえば SENCA_PUBLIC_IP=203.0.113.10 docker compose up -d のように起動します。docker run で起動する場合は、引数に --webrtc-public-ip <ホストの IP> を加えてください。これがないとコンテナーの中のアドレスを相手に伝えてしまい、ホストの外からはつながりません。

compose.yaml は、手元の作業中のファイルからイメージをビルドします。配布するイメージは、git archive HEAD | docker build -t senca/node:local - のようにコミット済みのソースから作ってください。

GPU をコンテナーに渡す例は compose.yaml のコメントにあります。NVIDIA の GPU なら NVIDIA Container Toolkit を、Intel・AMD の GPU なら /dev/dri を使います。イメージの中のライブラリの置き場所は x86_64 のパス(/usr/lib/x86_64-linux-gnu)で固定です。

次に読むページ

関連するページ

この文書の原文は、リポジトリの docs/guide/ja/02-quickstart.md にあります。内容は現在の版(v0.0.1)に合わせています。