前回のICPC 2023 Asia Yokohama Regional スタッフ参加記録 に書ききれなかったことを追記していきます。今回はスクリーンキャストについてです。
まとめ
中継に選手のスクリーン動画を出すことに2019年から挑戦しています。しかし、2023年度も中継で活用できるまでには至っていません。これまでの変遷と、課題について列挙します。
背景
ICPC 横浜大会では大会の中継を行なっています。 大会の様子を流したり、問題の解説をしたり、先生や過去の参加者に話をしてもらったりしています。しかしプログラミングコンテストの大会の中継として、本当にほしい絵は大会に実際に参加している選手の動きです。というわけで、ICPC プログラミングコンテストのシステム班としての作業の一環として、選手のコンピュータのスクリーンキャスト、すなわちコンピュータ画面の動画を取得し、中継素材として提供するという作業をしています。
当面の理想系は ICPC 世界大会の中継動画です。動画の途中に何度も、スコアボード、選手のコンピュータスクリーン、選手の顔、それから最近の選手の回答提出一覧が出ているのがわかります。
構成の変遷
ICPC でのコンテストネットワークの構成は、前にも示した通り、選手コンピュータと審判サーバへの出口からなります。
この選手のコンピュータの画面を動画として取り込み、視聴者に届けるのが今回の目標です。画面を動画として取り込むソフトウェアとして我々は ffmpeg を選手コンピュータ上で動かしています。ここまではどの構成でも同じです。そこから動画を中継や視聴者に提供する方法と経路にかなりの変遷があります。
2019 版
全自動で選手のスクリーンキャスト動画を合成し、YouTube Live に届けるサーバを立てました。ランダムなチームの動画を 30 秒ずつ作って合成しました。中継との連携は行わず、動画は中継の副チャンネルで流されました。
中継と連携しなかった理由は、そもそもどこまでできるか、当日ちゃんと動くかとか何も定かでなかったからです。また、コンテスト本番以外にそれと同規模のテストをする環境もありませんでした。VM4,5台や実機2台を用いた動作確認を事前にしたのち、本番で選手コンピュータ60台のスクリーンキャストを処理していました。
![](architecture-2019.png#center)
動画中継サーバが選手コンピュータの選定、録画リクエスト、合成、YouTube Live へのアップロードのすべてを行います。
- 動画中継サーバから選手コンピュータに ssh で接続し、ffmpeg を起動してスクリーンキャストを自分に送るようにする。
- 接続するコンピュータは30秒ごとに切り替える。
- 集まった動画4つを OBS でまとめて YouTube Live に流す。
利点
動画中継サーバの設定だけでコンテンツができる。
難点
中継と連携ができない。自由な操作はできず、ただランダムな4チームの動画が 30 秒ごとに流れる。
この後2年、コロナでオンサイトコンテストがなくなり、ICPCアジア地区予選横浜コンテストはオンラインで行われました。オンラインの場合は選手コンピュータが我々の管理下にはないので、スクリーンキャストを統一的に提供するのは不可能でした。
2022 版
中継班との連携を模索したもの。本番直前に問題が発覚しお蔵入りしました。
今回は中継版との連携のため、インフラは選手のスクリーンキャスト動画を全て中継班に渡すところまでにしました。動画を処理して視聴者に渡すところは中継班が担当します。ここで問題になるのは動画を渡す経路でした。中継班のコンピュータはコンテストネットワークの外にあり、コンテストネットワーク内の選手コンピュータや動画中継サーバにはアクセスできません。そのため、中継動画をインターネット経由でアクセスできるようにしました。
![](architecture-2022.png#center)
ポイントは動画アクセスポイントで、ここで選手のスクリーンキャストが以下の経路で提供されます。
- 選手コンピュータすべてで ffmpeg を起動し、動画中継サーバにスクリーンキャストを送る。
- 動画中継サーバは受け取った動画を HLS 形式で保存し、HTTP で提供できるようにする。
- クラウド上に立てた動画アクセスポイントと動画中継サーバを VPN で接続し、上記の HLS をインターネット経由で読めるようにする。
一方で中継班は、スクリーンキャスト動画の合成のために、世界大会でも使っている中継用ソフトウェアである live-v3 の導入を提案してきました。これを使えば、スコアボードやチーム名をスクリーンキャストに組み合わせるのも容易ですし、特定のチームのスクリーンキャストを呼び出すこともできます。しかし、このソフトウェアとの接続でいくつかの問題がありました。特に二番目の問題が深刻で、これが原因で中継でスクリーンキャストの採用ができませんでした。
- live-v3 が動画形式として mp4 と WebRTC Grabber しかサポートしていない。特に HLS がない。
- 対策として HLS → mp4 変換サーバを書き、上記の動画アクセスポイントに載せました。アクセスに応じて HLS の最新30秒を mp4 に変換して返すサーバです。内部的には ffmpeg を叩いて合成しているだけです。
- live-v3 が「スコアボードの情報」として要求する情報に機密性の高い情報が含まれている。
- これに気づいたのが現地でした。中継チームは 選手のOB/OGメンバでしたが、セキュリティ上の理由で彼らに審判サーバの管理者権限は渡せなかったので、採用できませんでした。これについては2023年度のところでもう少し解説します。
2023 版
インフラ的には 2022 年と同じで、 live-v3 対応のために審判サーバとの連携を工夫しました。
2022年度版に存在した問題は解決し、中継は動作したものの、いくつか難点がありあまり活用されませんでした。
解きたい課題
問題
live-v3 は審判サーバのデータを必要とします。しかし live-v3 が要求する情報には公開スコアボードに含まれる以上の情報が入っていて、その中には審判団とコンテスト運営チームの一部以外に共有できない機密情報もありました。 具体的には、live-v3 は審判サーバの /event-feed という API から提供されるデータを必要とします。 /event-feed はコンテストで起きたことのリストを時系列順に出したものです。 問題として、ここには中継班に提供するには危険なほど重要な秘密情報が入っています。例えばコンテスト中は選手から審判団へ問題に関する質問を送ることができますが、その問い合わせ内容が全て入っています。
解法
/event-feed を安全に中継班に公開するために、審判サーバの /event-feed から機密情報、非公開情報を全て落とすサーバを書きました。審判サーバの /event-feed を読んで、チーム名と公開順位以外のすべてを落として提供すようにしています。
結論が簡単になってしまったのでかんたんに見えますが、この解決策にたどり着くまでに週末を数ヶ月分消費しました。具体的には live-v3 の Kotlin ソースコード解析や、馴染みのないコンテスト API の調査が必要でした。
残された問題点
以上で課題は解決したのですが、以下の問題が新たに見つかり、その結果スクリーンキャストはあまり活用されませんでした。
- HLS → mp4 変換サーバのため、動画は30秒ごとにしか取れない。
- 何らかの原因によって動画が10分遅れた。常に10分前の動画が見られる状態になっていた。
前者が致命的で、このため中継でゆっくり映像を解説できません。 また、後者はテストのときは見つかりませんでした。
次年度へ向けて
中継班が連続的に動画を見れるようにするためには、以下どちらかの解決策を取る必要があります。
- live-v3 の出力 HTML に手を入れて HLS をサポート。hls.js を追加すればいいと思っています。
- WebRTC Grabber なるものを使う。お手製ソフトを選手マシンにあまり入れたくないですが、コード自体は大した量がないので理解して進めます。
hlsの遅延や、WebRTC Grabber が世界大会で使われていることを考えると、後者を選択するのが良さそうです。前者に比べて変更する量がかなり多く、特にインフラの書き換えが必要になりますが。
余談 テストについて
2019年度のところで少し言及しましたが、スクリーンキャストインフラのテストには工夫がいります。コンピュータ実機60台を用いて事前にテストをするのは我々の予算と機材では難しいですし、一方である程度の負荷試験や接続試験はしないと何も保証ができません。今年度のスクリーンキャストの構成では、以下の構成のテストを行いました。
- 選手コンピュータ–動画中継サーバの構成のテスト。選手コンピュータからスクリーンキャストをし、動画中継サーバでそれを受け取って HLS 形式で保存。
- 動画中継サーバ–動画アクセスポイントの構成のテスト。動画中継サーバ上で ffmpeg を動かしてリアルタイムで HLS を生成し、動画アクセスポイントとつないでインターネット経由で HLS を見られるようにする。
- 動画中継サーバの負荷試験。スクリーンキャスト動画をあらかじめ10個 mp4 形式で保存。それらを並列で一台の動画中継サーバにライブストリームし、動画中継サーバ上で10個並列でHLS形式で保存。マシン負荷を計測。
- live-v3 の機能テスト。2の構成と同じく動画中継サーバ上で HLS を10個作成し、動画アクセスポイントとつないで HLS をインターネット経由で見られるようにする。並行して審判サーバを動かし、10チーム参加のプログラミングコンテストを開催。 live-v3 でコンテストのスコアボードと HLS の動画の両方を処理できることを確認。
![](architecture-2023-with-tests.png#center)
テストはおおよそ VM をセットアップして行っていました。もちろん負荷試験は例外です。3の負荷試験は実機を動画中継サーバとして用意し、それに動画10本を並列で与えてCPUを5%も使用していないことを確認しました。その結果を見て、60個の動画でも大丈夫だろうという結論を立てていました。
一方で、以下のようなテストはあまりしていませんでした。
- スクリーンキャストの遅延試験。選手コンピュータからスクリーンキャストを行い、動画中継サーバで受け取ってHLSで保存し、動画アクセスポイントとつないでインターネット経由でスクリーンキャストを見られるようにする。これを1時間放置し、動画の遅延を計測。
- 実際に競技プログラミングをやりながらスクリーンキャストを動かしての負荷や帯域の計測。動画の容量は作業によって変わるので。テストの際は、静止画だとだめだと思っていたので、システムモニタを起動したり一秒ごとに現在時刻を表示するスクリプトを動かしたりしていました。
完全に余談ですが、動画のテストをやるのはこの仕事が初めてだったので色々変な知見を得ました。例えばテスト2や4では実際のスクリーンキャストは不要なので、仮の動画を動画中継サーバ上で生成しています。ちょっと探すと以下のように ffmpeg でテスト用の動画が作れることがわかるので、この上に drawtext フィルタで動画番号や現在時刻を書き込んでテスト用動画を作っていました。
問題はテスト動画で何を使うかです。負荷や動画サイズの関係で静止画像はあまり望ましくなく、適度に動きがあるのが嬉しいです。はじめはマンデルブロ集合を使っていたのですが、これを長く動かしていると CPU を多く消費し動画が遅れたりすることがわかりました。そのためテスト動画をシェルピンスキーに変更しました。オートマトンやライフゲームだと長時間動かすとほぼ静止画になってしまう可能性があったので避けました。
感想
スクリーンキャスト整備はかなり大変な作業で、これだけで私の準備時間の 1/2 – 1/3 くらいを消費しています。これを続ける私のモチベーションは二つあります。まずは、せっかくシステム整備をしているのでコンテストを楽しくできるようなシステムを作れた方が嬉しいということ。コンテストセキュリティを考えると、システム担当以外にこの作業に触れる人はいません。それからもう一つ、スクリーンキャストを使えるところまで持っていけばもっと準備は楽になるんじゃないかと思っています。作業時間の多くは不明なところを明らかにするところであり、今までも ffmpeg の使い方やライブストリーム通信のプロトコルの調査、それから今年度は上記の live-v3 のソースコード解析などに時間を使ってきました。それらには再度時間を使う必要はありません。来年度 WebRTC に挑戦するなら、再度プロトコルやネットワークの調査が必要になりますが、それでも例えばネットワーク帯域などの心配をする必要はあまりありません。
一方で、例えばテストがもう少し気軽にできたら、トラブルが減るのではないかとは思います。今は本番と同等の試験ができるのは本番とそのリハーサルしかなく、実物を中継班に共有するのも現地でだけです。試行錯誤がもう少しできれば、もう少し安定したものを提供しやすいと思います。とはいえ、例えば本番の回数を増やすとかで対応したくはないですが。労力がかかりすぎるので。
FAQ
Q. 任意のチームの動画が視聴者に見られるようになったりしませんか?
A. YouTube Live を 60 チャンネル提供すると回線が大変そうで無理です。 動画アクセスポイントも公開してしまうと、動画アクセスポイント - 動画中継サーバ間の通信が莫大になるので無理です。
Q. コンピュータ画面よりも選手の顔を撮ったほうが良いのでは?
A. そのためにはウェブカメラが必要で、全チーム分のウェブカメラを用意しセッティングするのはちょっと大変です。お金と労力両方の問題になります。やるとしても、スクリーンキャストが安定してできて労力が無駄にならないことを確認してからですね。
少数のウェブカメラをスタッフが手持ちで使って選手の様子を撮るのならありです。ボランティアが増えれば検討できると思います。
Q. スクリーンキャスト取得に失敗し過ぎでは? もう少しうまくできる方法があるのでは?
A. 年に一回しか試せないので難しいです。私は動画専門エンジニアでもないですし、まずはコンテストがちゃんと動くことを優先しないといけないですし。
ボランティアは歓迎します、と言いたいところですが、コンテストセキュリティとの兼ね合いがあるので実働を頼むのは難しいです。意見は大歓迎です。
Q. 選手のコンピュータへの負荷が気になります。
A. CPU負荷は数%であることを確認しています。
Q. 世界大会の映像はかなり色々やっていますが、これと同等のことはできないんですか? 例えば正解を受け取ったときの選手の顔動画とか。
A. 選手顔動画は上記の通りです。あと、世界大会は映像ディレクターチームが8人とかいるという話を聞きました。こちらは映像ディレクター1人と、システムインフラで片手間の対応です。
Q. 動画アクセスポイントを建てなくても、コンテスト会場のIPで直接つないでしまえばよいのでは?
A. コンテスト会場のインターネット出口の挙動は実地でないとうまく実験ができないので避けました。ネットワーク班に頼めばなんとかなった可能性はあります。