配信と録画
SENCA のほうから外へ接続する機能を扱います。ネットワークカメラや別の配信サーバーから映像を取りに行くのが入力(pull)、SENCA のストリームを YouTube のような配信先へ送るのが出力(push)です。出力には、Cloudflare Stream・Amazon IVS・AWS Elemental MediaLive に SENCA がインジェストエンドポイントを作ってそこへ送る、PaaS 連携という形もあります。
配信者のほうから SENCA へ送ってくる RTMP・SRT・WHIP は、ここではなく 取り込みと再生 で説明しています。
始める前に 2 つ知っておいてください。パスワードやストリームキーは URL に書かず、シークレットに保存して credential_ref: "secret:{name}" で渡します。また、社内のカメラのようにプライベートアドレスにある相手には、管理者が --egress-allow で許可するまで接続できません。
例で使う API・TOKEN・H は、取り込みと再生 と同じです。
API
入力・出力・シークレットを操作する API です。
| 操作 | リクエスト | 権限 |
|---|---|---|
| 入力を追加 | POST /streams/{id}/inputs | stream:write |
| 入力の一覧 | GET /streams/{id}/inputs?limit&cursor | stream:read |
| 入力の取得・変更・削除 | GET・PATCH・DELETE /inputs/{id} | stream:read・stream:write |
| 出力を追加 | POST /streams/{id}/outputs | stream:write |
| 出力の一覧 | GET /streams/{id}/outputs?limit&cursor | stream:read |
| 出力の取得・変更・削除 | GET・PATCH・DELETE /outputs/{id} | stream:read・stream:write |
| シークレット | POST・GET /secrets、DELETE /secrets/{id} | tenant:admin |
入力・出力を作るときの本文:
| フィールド | 入力 | 出力 | 意味 |
|---|---|---|---|
protocol | 必須 | 必須 | 種類です。入力は rtmp_pull・rtsp_pull・srt_pull・hls_pull・device、出力は rtmp_push・srt_push・paas です |
url | 必須 | paas 以外は必須 | 接続先です。使えるスキームは protocol で決まります(下の表を参照)。2048 文字までで、空白と制御文字は使えません。user:pass@ を含めると 400 を返します |
credential_ref | 任意 | 任意(paas では必須) | secret:{name} の形で、認証情報を渡します。認証情報は URL に書かず、ここで渡してください(シークレット を参照) |
enabled | 既定は true | 既定は true | false にすると、動かさずに止めておきます |
options | 任意 | 任意 | 種類ごとの追加の設定です。値は文字列で、16 個まで、キーは 64 文字・値は 256 文字までです |
provider | paas では必須 | 連携先のサービスです。cloudflare_stream・aws_ivs・aws_medialive のどれかです | |
placement | 任意 | 任意 | どのノードで動かすかの指定です(配置先 を参照) |
| protocol | url のスキーム |
|---|---|
rtmp_pull・rtmp_push | rtmp・rtmps |
rtsp_pull | rtsp・rtsps(rtsps は TLS で接続します) |
srt_pull・srt_push | srt |
hls_pull | http・https |
device | device:{デバイス ID}(取り込みと再生 の「キャプチャデバイスから取り込む」を参照) |
1 つのストリームに付けられる入力は 4 個、出力は 16 個までで、超えると 403 QUOTA_EXCEEDED になります。
PATCH(If-Match が必須)で変えられるのは url・credential_ref(null で外せます)・enabled・options・placement で、protocol と provider は変えられません。変更すると世代番号が上がり、動いている接続は再接続されます。
応答には status(状態と再接続 を参照)と、placement・placement_status(配置先 を参照)が入ります。出力ではさらに provider と provider_resource も返ります。
入力(pull)
入力は、ストリームから見ると 1 人の配信者です。1 つのストリームの配信者は同時に 1 つだけなので、push の配信者がつながっている間は入力は接続できず、再接続を繰り返します。逆に入力がつながっている間は、push の配信者が入れません。入力が切れたときも、ふつうの配信者と同じく再接続の猶予時間があります(取り込みと再生 を参照)。
rtmp_pull
RTMP のサーバーから取り込みます。
curl -s -X POST "$API/streams/$SID/inputs" "${H[@]}" -d '{"protocol":"rtmp_pull","url":"rtmp://origin.example.com/live/program1"}'
url は rtmp[s]://host[:port]/{app}/{stream name} の形で、ポートを省くと rtmp は 1935、rtmps は 443 です。stream name は、credential_ref のシークレットがあればその値、なければ URL の最後の部分を使い、どちらもなければエラーです。
再生はライブとして要求します(play の start に -2 を指定)。受信が 20 秒止まったら、接続を切って再接続します。
rtsp_pull
ネットワークカメラ(IP カメラ)から取り込むときに使います。カメラのログイン情報をシークレットに保存してから、入力を追加する例です。
curl -s -X POST "$API/secrets" "${H[@]}" -d '{"name":"cam-login","value":"viewer:s3cret"}'
curl -s -X POST "$API/streams/$SID/inputs" "${H[@]}" -d '{"protocol":"rtsp_pull","url":"rtsp://192.0.2.10:554/stream1","credential_ref":"secret:cam-login"}'
転送方式は TCP interleaved(RTSP の TCP 接続の中でメディアも送る方式)だけです。NAT やファイアウォールを越えやすいのが利点です。ポートの既定は 554 です。
認証情報は user:password の形でシークレットに入れます。Basic 認証はパスワードを平文で送ってしまうので、options.allow_basic: "true" を指定したときしか使いません。
rtsps:// では TLS で接続し、サーバー証明書を OS の認証局の証明書で検証します。認証局の証明書のファイルは、環境変数 SSL_CERT_FILE で指定することもできます。
自己署名の証明書を使うカメラなら、options.tls_spki_sha256 に証明書の公開鍵(SPKI)の SHA-256 を base64 か 16 進で書き、相手を固定します(, 区切りで複数可)。固定した場合は認証局・有効期限・ホスト名を検証しない代わりに、値が一致しなければ TLS の接続は失敗し、暗号化なしに切り替えることもしません。値の書き方が正しくなければ 400 です。
# カメラの証明書から固定する値を作る
openssl x509 -in cam.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
curl -s -X POST "$API/streams/$SID/inputs" "${H[@]}" \
-d '{"protocol":"rtsp_pull","url":"rtsps://192.0.2.10:322/stream1","credential_ref":"secret:cam-login","options":{"tls_spki_sha256":"<上の値>"}}'
社内のカメラのようにプライベートアドレスにある相手へは、--egress-allow で許可しないと接続できません(外向きの接続の制限 を参照)。
srt_pull
SRT で送り出している相手に、SENCA から接続して取り込みます。
curl -s -X POST "$API/streams/$SID/inputs" "${H[@]}" -d '{"protocol":"srt_pull","url":"srt://contrib.example.com:9000?streamid=feed1&latency=200000","credential_ref":"secret:srt-feed-pass"}'
SENCA が caller(接続しに行く側)になり、MPEG-TS を受け取ります。url のクエリで読むのは streamid と latency だけです。latency の単位はマイクロ秒で、ffmpeg の URL と同じく 200000 が 200 ms です(既定も 200 ms)。パスフレーズ(10〜79 文字)は URL に書かず、credential_ref で渡してください。
hls_pull
HLS で配信されている映像を取り込みます。CDN に載っている配信を中継し直すときなどに使えます。
curl -s -X POST "$API/streams/$SID/inputs" "${H[@]}" -d '{"protocol":"hls_pull","url":"https://cdn.example.com/live/master.m3u8"}'
multivariant playlist(複数の画質をまとめたプレイリスト)を渡すと、帯域(BANDWIDTH)がいちばん大きい画質を選びます。セグメントは TS と fMP4 に対応し、実際の時間と同じ速さでストリームに流します。
ライブのプレイリストは、最初は最後の 3 セグメントから読み、その後は TARGETDURATION の半分(0.5〜5 秒)ごとに読み直します。#EXT-X-ENDLIST のあるプレイリスト(VOD)は最後まで読んだら終わり、状態が ended になります。繰り返し再生はしません。
なお、取り込み元がセグメントをためている分の遅延は、SENCA の側ではなくせません。
device
キャプチャデバイスからの入力です。取り込みと再生 の「キャプチャデバイスから取り込む」を参照してください。
出力(push)
出力は、ストリームの配信が始まるまで waiting_input で待ち、始まったら配信先へ接続します。配信が終われば接続を閉じ、また次の配信を待ちます。
rtmp_push
RTMP で配信先へ送ります。配信先のストリームキーをシークレットに保存してから、出力を追加する例です。
curl -s -X POST "$API/secrets" "${H[@]}" -d '{"name":"yt-key","value":"xxxx-xxxx-xxxx-xxxx"}'
curl -s -X POST "$API/streams/$SID/outputs" "${H[@]}" -d '{"protocol":"rtmp_push","url":"rtmps://live.example.com:443/app","credential_ref":"secret:yt-key"}'
url は rtmp[s]://host[:port]/{app}[/{stream key}] の形です。stream key は credential_ref があればその値、なければ URL の最後の部分を使います。ただし URL に書いたキーは API の応答(url)にそのまま出てしまうので、credential_ref を使ってください。
送る形式は FLV(Enhanced RTMP を含む)です。どのコーデックを受け付けるかは配信先しだいです。接続と publish の開始は 15 秒、1 回ごとの書き込みは 10 秒でタイムアウトします。
srt_push
SRT で配信先へ送ります。
curl -s -X POST "$API/streams/$SID/outputs" "${H[@]}" -d '{"protocol":"srt_push","url":"srt://receiver.example.com:9000?streamid=senca&latency=300000","credential_ref":"secret:srt-out-pass"}'
SENCA が caller として接続し、MPEG-TS を 1316 バイトずつ送ります。streamid と latency(マイクロ秒)の扱いも、パスフレーズを credential_ref で渡すのも srt_pull と同じです。AV1・VP8・VP9 は TS に入らないので送れません。
外部の WHIP サーバーへ送る機能(
whip_push)には対応していません。protocol: "whip_push"を指定すると 400 を返します。
PaaS 連携
protocol: "paas" を指定すると、クラウドのメディアサービスに SENCA がインジェストエンドポイント(映像の受け付け先)を作り、そこへ SENCA 自身が RTMP(S) か SRT で送ります。クラウドの管理画面でインジェストエンドポイントを手で作っておく必要はありません。
Cloudflare Stream の認証情報をシークレットに保存してから、出力を追加する例です。
curl -s -X POST "$API/secrets" "${H[@]}" -d '{"name":"cf","value":"0123456789abcdef0123456789abcdef:CF_API_TOKEN"}'
curl -s -X POST "$API/streams/$SID/outputs" "${H[@]}" -d '{"protocol":"paas","provider":"cloudflare_stream","credential_ref":"secret:cf","options":{"recording":"automatic"}}'
出力が有効になると、状態が provisioning になり、外部のリソース(Live Input・Channel・Input)が作られます。リソースには senca:owner={出力の ID} のタグ(Cloudflare では meta)が付きます。作成の途中経過とリソースの ID は、次のリクエストを送る前に出力の provider_resource に保存していくので、途中でノードが止まってもリソースが二重にできることはありません。同じ owner のリソースが見つかれば、それを引き継ぎます。
インジェストエンドポイントの stream key やパスフレーズは SENCA には保存せず、送り始めるたびに外部の API から取り直します。送り方は rtmp_push・srt_push と同じで、options.ingest で rtmps か srt を選べます。指定しなければ、連携先が返す最初のインジェストエンドポイントを使います。
出力を削除すると、外部のリソースも削除します。 SENCA のタグが付いていないリソースには触れません。外部のリソースの削除に失敗しても出力の定義は消え、失敗したことはログに残ります。
外部の API への接続にも 外向きの接続の制限 がかかります。
連携先ごとの設定:
provider | 作成するもの | credential_ref の値 | options |
|---|---|---|---|
cloudflare_stream | Cloudflare Stream の Live Input | account_id:api_token | recording: off(既定)・automatic。customer_subdomain: customer-xxxx.cloudflarestream.com。endpoint: API の接続先を差し替えます(テスト環境につなぐときなど) |
aws_ivs | Amazon IVS の Channel | access_key_id:secret_access_key[:session_token] | region(必須)。channel_type: STANDARD(既定)・BASIC・ADVANCED_SD・ADVANCED_HD。latency_mode: LOW(既定)・NORMAL。recording_configuration_arn。endpoint |
aws_medialive | AWS Elemental MediaLive の Input と Input Security Group | access_key_id:secret_access_key[:session_token] | region(必須)。input_type: RTMP_PUSH(既定)・SRT_LISTENER。allow_cidr(ノードの送信元の CIDR。, 区切りで 10 個まで)か input_security_group(既存の ID。SENCA は作りも消しもしません)のどちらかが必須です。pipelines: 1(既定)・2。rtmp_app(既定は senca)。srt_passphrase_secret_arn。srt_min_latency_ms(120〜15000、既定は 2000)。endpoint |
Cloudflare Stream へは、RTMPS(既定)か SRT で送ります。
Amazon IVS の送り先は rtmps://{ingestEndpoint}:443/app/ で、Channel が SRT に対応していれば SRT も選べます。配信中の Channel は IVS の側が削除を断る(ConflictException)ので、その場合はログを見て手作業で削除してください。
MediaLive では、SENCA が作るのは送り先の Input と、それを守る Security Group だけです。Channel(エンコードの設定や出力先)はご自身で作り、この Input をつないでください。Channel につながったままの Input は削除できません。provider_resource は input=<id>;sg=<id> の形になります。
状態と再接続
入力・出力の status:
| フィールド | 意味 |
|---|---|
state | 今の状態です。starting(開始中)、provisioning(PaaS 連携で外部のリソースを作成中)、waiting_input(出力が配信の開始を待っている)、connecting(接続中)、active(動作中)、backoff(再接続を待っている)、error(失敗した)、ended(VOD の hls_pull を最後まで読み込んだ)のどれかです |
last_error | 直近の失敗の理由です(秘密の情報は含みません) |
connects | 接続に成功した回数です |
since | 今の state になった時刻です |
bytes | 送受信したバイト数です |
status に値が入るのは、その入力・出力を動かしているノードに問い合わせたときだけです。ほかのノードに聞いたときや、動いていないときは null です。
失敗すると状態は error になり、すぐ backoff に移って、待ってから再接続します。待ち時間は 1 秒から失敗のたびに倍になり、最大 60 秒です。実際にはその値の半分から全部までの間でランダムに決まります。配信元が配信を終えたときのように正常に終わった場合は、0.5〜1 秒待つだけで次の接続に移ります。
--egress-allow を指定せずに 127.0.0.1 の RTSP カメラを指定すると、次のようになります。
{"state": "backoff", "last_error": "127.0.0.1 は許されていない宛先です(--egress-allow で許可が必要)", "connects": 0, "bytes": 0,
"since": "2026-11-03T01:19:43.679Z"}
シークレット
シークレットは、パスワードやキーを暗号化して保存しておく場所です。入力・出力などからは secret:{name} の形で参照します。
curl -s -X POST "$API/secrets" "${H[@]}" -d '{"name":"cam-login","value":"viewer:s3cret"}'
{"id":"33bb760ab08f2f11af9fcd12af258649","name":"cam-login","ref":"secret:cam-login","created_at":"2026-11-03T01:19:07.291Z"}
保存した値は API から読み出せません。 一覧に出るのは id・name・ref・created_at だけです。値を変えたいときは、削除して作り直してください。ただし入力・出力・ストリームの字幕から参照されている間は削除できません(409)。
name の決まりはストリームの名前と同じ(1〜64 文字の英数字と -_.)で、テナントの中で重複すると 409 です。value は 1〜8192 バイト、1 つのテナントに 500 個まで保存できます。存在しないシークレットを参照すると、入力・出力の作成や変更は 400 になります。
値は AES-256-GCM で暗号化して保存します。鍵は、1 台ならノードの鍵 {data-dir}/control/secret-key、クラスターならクラスター共通の鍵です(セキュリティ を参照)。
値に何を入れるかは、使う場所で決まっています。
| 使う場所 | 値の形 |
|---|---|
rtmp_pull | stream name |
rtmp_push | stream key |
rtsp_pull | user:password |
srt_pull・srt_push | パスフレーズ(10〜79 文字) |
paas | PaaS 連携 の表を参照 |
| 字幕(字幕と翻訳) | API キー |
名前が srt-passphrase のもの | SENCA が SRT で待ち受けるときのパスフレーズ(取り込みと再生 を参照) |
外向きの接続の制限
SENCA から外へ向かう接続(egress)は、宛先を制限しています。外から指定された URL を使って内部のサーバーへ接続させる攻撃(SSRF)を防ぐためです。
pull の入力、push の出力、PaaS 連携の API、字幕の API の接続先は、名前解決をしたあとの IP アドレスで検査します。DNS でプライベートアドレスを指すように細工しても、すり抜けられません。既定で拒否する宛先は次のとおりです。
- ループバック(127.0.0.0/8、::1)、未指定アドレス(0.0.0.0 や ::)、マルチキャスト、ブロードキャスト、0.0.0.0/8
- リンクローカル(169.254.0.0/16 と fe80::/10。クラウドのメタデータの 169.254.169.254 も含みます)
- プライベートアドレス(10/8、172.16/12、192.168/16、100.64/10、fc00::/7)。これらを IPv6 の形で書いたアドレス(IPv4 射影 IPv6 アドレス)も同じく拒否します
社内のカメラや配信先へ接続したいときは、管理者が --egress-allow CIDR で範囲を許可します。何回でも重ねて指定できます。
senca-node ... --egress-allow 192.0.2.0/24 --egress-allow 10.20.0.0/16
許可されていない宛先でも、入力・出力の作成自体は通ります。失敗するのは接続するときで、理由は last_error に出ます(状態と再接続 の例を参照)。作成が 201 で返ったのに映像が来ないときは、まずここを見てください。
配置先
enabled が true の入力・出力は、グリッドのワークロード(input:{id}・output:{id})になり、グリッドが割り当てたノードだけがそれを動かします。
出力は、そのストリームの配信を受けているノードに優先して割り当てます。ノード間の中継を 1 段省けるからです。キャプチャの入力は、そのデバイスを持つノードに割り当てます。H.264/H.265 でエンコードするキャプチャは、GPU のエンコードのセッションを 1 つ確保します。
placement で指定できるのは次のものです。
- 手動での割り当て(
node・device) - ラベルによる条件
- 同じノードに置かないものの指定(アンチアフィニティ)
- 優先度
- 割り当ての方針(散らす
spread、詰めるbinpack) - 割り当て先が止まったときの扱い(
pin_policy)
degrade はパイプライン専用で、入力・出力に指定すると 400 です。
割り当ての結果は placement_status に出ます。state は running・pending・unschedulable・not_scheduled のどれかで、ほかに node・node_name・reason などが入ります。
1 台で動かしている場合も仕組みは同じで、割り当て先がそのノードしかないだけです。詳しくは クラスターとグリッド を参照してください。
関連するページ
この文書の原文は、リポジトリの docs/guide/ja/06-inputs-outputs.md にあります。内容は現在の版(v0.0.1)に合わせています。