Egress
Egress は、誰かがそのパスを読んでいる間、ブロードキャストを開発者のストレージに録り、配信サービスへ送ります。プレフィックスの下のすべてのブロードキャストの合成は一つのページで作り、参加者のタブでも Egress 自身でも動くので、誰のタブも開いていなくても録れます。
パス
| パス(読み手のルートから) | 読まれている間 |
|---|---|
.egress/{source}/{dest} |
ブロードキャスト {source} を {dest} へ送る |
.egress/{prefix}/.composite/{dest} |
{prefix} の下のブロードキャストを合成し、合成を {dest} へ送る |
{dest} は最後の段で、record か、プロジェクトの環境変数 EXPORT_{NAME}_URL の {name} です(EXPORT_YOUTUBE_URL なら youtube)。.egress/{source}/… を読むと {source} がプロジェクトの外へ送られるので、{source} と同じように許してください。
// Recording and streaming through Egress: while .egress/{source}/{dest} is read, Egress records
// {source} (dest record) or sends it to the destination a project variable names (EXPORT_{DEST}_URL).
import { type Connection, json } from 'tablebox.io';
export async function egress(connection: Connection, source: string, dest: string, show: (status: unknown) => void) {
const output = await connection.read(`.egress/${source}/${dest}`);
const status = new json.Snapshot.Consumer({ track: output.track('status.json').subscribe() });
void (async () => { for await (const now of status) show(now); })();
// Closing the read stops it 20 s later, unless someone else still reads it.
return () => output.close();
}読まれている間
Egress は、パスが最初に読まれてから、最後の読み手が去って 20 秒後まで働き、パスの読み手全員で一つの録画か一つの送り出しを共有します。読み出しを持ち続けるバックエンドがあれば、誰もいなくても録れます。人が来たときにパスを読むアプリなら、自動で録れます。
出力のトラックは一つで、status.json は {"state", "code"?, "message"?, "file"?} の JSON スナップショットのトラックです。
state |
意味 |
|---|---|
waiting |
元がまだ出ていない、またはそのカタログにまだレンディションがない |
active |
送っている、または録っている。record では file が録画のキー |
retrying |
送り先かストレージが失敗した。Egress は 30 秒まで延ばしながらやり直す |
failed |
Egress が始められない: code は missing-variable(message が変数の名前)、bad-request(元のコーデックが送り先に合わない、または送り先が内部のアドレス)、failed のどれか |
配信
EXPORT_{NAME}_URL には、ストリームキー付きの rtmp://、rtmps://、srt:// の URL を書きます。一つの元は、カタログに映像と音声のレンディションが載ったとき、または最初の一つが載ってから 5 秒後に、出されたとおり再エンコードせずに送ります。配信サービスは H.264 と AAC を受け、合成、Ingress で受けた OBS のストリーム、そのコーデックで出すブラウザー(出す・読む)はそれを持ちます。
録画
record は、Persistence のストレージの変数で、MP4 のファイルを開発者のストレージの {STORAGE_PREFIX}{project path of source}/{UTC start as YYYYMMDDTHHMMSSZ}.mp4 に書きます。元が現れるたびに別のファイルになり、元が終わるか egress が止まると完成します。どのプレーヤーでも開けます。
合成
合成は、{prefix} の下の、. の段のあるパスを除き、名前が .hang で終わるすべての hang のブロードキャストの映像を、パスの順に 1280x720、30 fps のグリッドに並べ、音声をすべて混ぜた、H.264 と AAC(48 kHz、ステレオ)の一つのブロードキャストです。出てきたり消えたりするブロードキャストは、グリッドに加わったり抜けたりします。
.egress/{prefix}/.composite/{dest} を読むと、Egress が合成のページを自分で開きます。同じページは参加者のタブでも https://{egress host}/composite#relay={url}&token={token}&prefix={prefix}&path={path}(Egress のホストはリファレンス)で動きます。その参加者の端末で {prefix} を合成し、publish が {path} を覆うそのトークンで、合成を {path} に出します。それから .egress/{path}/{dest} を読めば送られます。
失敗
- 変数がない: 設定されるまで状態は
failedで、文がその名前を示します。設定すれば、読み直さなくても始まります。 - 送り先がストリームを拒むか切る、またはストレージが失敗する: パスが読まれている間
retrying。 - 元が去る:
waiting。録画のファイルは完成します。 - 元のコーデックが送り先に合わない(たとえば SRT への VP9 の映像、AAC しか受けないサービスへの Opus の音声): 状態は
failed、コードはbad-request。サービスが拒む場合はretrying。 EXPORT_{NAME}_URLのホスト、またはrecordのSTORAGE_ENDPOINTのホストが、インターネットではなくネットワークの中のアドレスであるか、そこに名前が引ける(Persistence と同じ): 状態はfailed、コードはbad-request、messageが変数の名前。変数が変わるまで続きます。- 合成のページが落ちる: Egress が開き直す間
retrying。 - インスタンスが止まる: 読み出しは終わり、読み直すと引き継いだインスタンスに届きます。読み直したパスで、送り出しをやり直すか新しいファイルを始めます。止まったときに書いていたファイルは失われることがあります。