Unreal Tournament サンプル Web サイト¶
Unreal Tournament の Web サイトは、サーバーに Node.js を使用し、フロントエンドに jQuery を使用するように最適化しています。型の確認がしやすいように、コード全般に TypeScript を使用しています。
このセクションでは、各コンポーネントを Genvid Web API とリンクさせるコードについてのみ説明します。
サーバーコード¶
サーバーの記述には Node.js を使用しています。これが、パブリック URL と内部 Genvid サービスの接続を行います。
routes/streams.t.ts
ファイル内の経路再選択を指定します。このファイルは、あらかじめ指定したシークレットを使用して、クライアントから disco サービスへのウェブ要求を転送します。
Consul を使用して、URL、disco のシークレット、webgatewayサービスを見つけます。config.ts
ファイルは、これらのサービスの検出方法を示しています。
// Copyright 2016-2022 Genvid Technologies LLC. All Rights Reserved.
let envs = require("envs");
import * as Consul from "consul";
let consul_addr = envs("CONSUL_HTTP_ADDR", "127.0.0.1:8500").split(":");
let port = consul_addr.pop();
let host = consul_addr.join(":");
export let consul = Consul({ host: host, port: port });
export let disco_url = envs("GENVID_DISCO_URL", "http://localhost:8080");
export let disco_secret = envs("GENVID_DISCO_SECRET", "discosecret");
export let webgateway_url = envs(
"GENVID_WEBGATEWAY_URL",
"http://localhost:8089"
);
export let webgateway_secret = envs(
"GENVID_WEBGATEWAY_SECRET",
"webgatewaysecret"
);
export let webEndpointConfig = {
endpoint: envs("ENDPOINT", undefined),
secret: envs("CLIENT_SECRET", undefined),
ssl: envs("SSL", "false")
};
export interface ITaggedAddresses {
lan: string;
wan: string;
}
export interface IServiceEntry {
Node: {
ID: string;
Node: string;
Address: string;
Datacenter: string;
TaggedAddresses: ITaggedAddresses;
Meta: {
[name: string]: string;
};
};
Service: {
ID: string;
Service: string;
Tags: string[];
Address: string;
Meta: {
[name: string]: string;
};
Port: number;
};
Checks: {
Node: string;
CheckID: string;
Name: string;
Status: string;
Notes: string;
Output: string;
ServiceID: string;
ServiceName: string;
ServiceTags: string[];
}[];
}
function wrapIPv6Address(address: string): string {
if (address.includes(":")) {
return `[${address}]`;
}
return address;
}
function watchService(serviceName: string, setUrl: (url: string) => void) {
const watchOptions: Consul.Health.ServiceOptions = {
service: serviceName,
passing: true
};
const serviceWatch = consul.watch({
method: consul.health.service,
options: watchOptions
});
serviceWatch.on("change", (services: IServiceEntry[], _res) => {
console.log(services);
if (services.length === 0) {
console.error(`${serviceName} service is not available from consul`);
} else {
let service = services[Math.floor(Math.random() * services.length)];
let serviceUrl = `http://${wrapIPv6Address(service.Service.Address)}:${
service.Service.Port
}`;
setUrl(serviceUrl);
console.info(`Watch ${serviceName} url: ${serviceUrl}`);
}
});
serviceWatch.on("error", err => {
console.error(`${serviceName} watch error:`, err);
});
}
watchService("disco", url => {
disco_url = url;
});
watchService("webgateway", url => {
webgateway_url = url;
});
サーバーが、2 キーの URL パスのトラフィックを転送します。
- /api/streams =>
GET /disco/stream/info
このメソッドは、現在のストリームに関する情報を取得します。ブラウザは、このメソッドでストリーム名、説明、チャンネルなどを取得します。
- /api/channels/join =>
POST /disco/stream/join
この Web メソッドは、Genvid システムへの接続に使用する URI とトークンを返します。
ブラウザコード¶
Unreal Tournament Genvid のサンプル Web サイトは次のようになります。
YouTube からの Unreal Tournament のライブ配信の映像を表示する、シンプルな Web アプリケーションです。プレイヤーを直接選択して、体の周囲に丸いハイライトを表示するビデオオーバーレイが存在します。ビデオの下には、各プレイヤーが視聴者に選択、キル、応援を許可できるコントロールがあります。このコントロールを使って、視聴者は Web ページを通してインタラクとすることができます。
グローバルショートカット¶
A | すべてのプレイヤーを選択、または選択解除 |
M | ストリームのミュート、またはミュート解除 |
Z | ストリームのボリュームを下げる |
X | ストリームのボリュームを上げる |
スペース | ストリームの一時停止、または一時停止解除 |
+ | DelayOffset を増やす |
- | DelayOffset を減らす |
* | DelayOffset をリセット |
F | フロアグリッドの表示 |
G | Genvid オーバーレイの表示、または非表示 |
H | ヘルプメニューの表示、または非表示 |
ビデオ¶
プレイヤーをクリック | プレイヤーを選択 (ビデオに丸いハイライトを付ける) |
ヘッダーボタン¶
Genvid アイコンボタン | Genvid オーバーレイの表示、または非表示 |
? | ヘルプメニューの表示、または非表示 |
ボトムパネル¶
👍 | こプレイヤーのカメラ変更 |
☠ | プレイヤーをキルする |
プレイヤーパネル | プレイヤーを選択 (ビデオに丸いハイライトを付ける) |
Genvid オーバーレイ¶
Genvid オーバーレイは、YouTube プレイヤーとの交流を回避しながら、各キューブの横に、色付きの円と名前、デバッグ情報を表示します。
Local | Web ページを表示するマシンのローカルタイム。 |
Raw Video | ビデオプレイヤーの現在の内部時間。 |
Est. Video | ビデオプレイヤーの予測時間。 |
Last Compose | Compose service からレポートされた直前のデータの時間。 |
Est. Compose | Compose service の予測時間。 |
ストリーム | 一般化されたストリームの現在時刻。 |
Latency | ゲームと視聴者の間の予測遅延時間。 |
DelayOffset | 同期を調整するための遅延オフセット (オプション) |
ut4_app.ts¶
ut4_app.ts
ファイルは、プレイヤーのキーボード入力、ビデオプレイヤーコントロール、およびヘルプの処理を行います。
ut4_engage.ts¶
ut4_engage.ts
は Genvid システムを初期化します。
以下の関数は、GenvidClient の初期化方法を示します。ブラウザがストリーム情報を受け取った時に呼び出されます。
private on_channel_join(info: genvid.IChannelJoinResponse) {
this.client = genvid.createGenvidClient(
this.streamInfo, info.uri, info.token, this.video_player_id);
this.client.onVideoPlayerReady((elem) => { this.on_video_player_ready(elem); });
this.client.onStreamsReceived((streams) => { this.on_streams_received(streams); });
this.client.onNotificationsReceived(this.on_notifications_received.bind(this));
this.client.onDraw((frame) => { this.on_new_frame(frame); });
this.client.start();
}
主な関数には、次のものがあります。
onVideoPlayerReady
: ビデオプレイヤーの準備ができた時に呼び出されます。onStreamsReceived
: ストリーム情報を受け取った時に呼び出されます。onNotificationsReceived
: 通知を受け取った時に呼び出されます。onDraw
: オーバーレイやコントロールの描画のために、- 毎秒 30 回呼び出されます。
また、このファイルが GenvidClient にイベントを送信します。
public cheer_player(player_name) {
if (this.client) {
console.log(`Sending cheer ${player_name}`);
this.client.sendEventObject({ "cheer": player_name });
} else {
console.log("No client connected.");
}
}
ut4_data.ts¶
このファイルには、コードで使用されるデータ構造体が含まれています。
ut4_model.ts¶
ut4_model.ts
のファイルは、受信したデータを分析し、使用可能なデータに変換します。
onStreamReceived
のメソッドは、ストリームから JSON 情報を解析します。アノテーションの解釈もここで行われます。
// Shows how to parse the JSON inside the streams and annotations
for (let stream of [...streams.streams, ...streams.annotations]) {
for (let frame of stream.frames) {
try {
frame.user = JSON.parse(frame.data);
}
catch (err) {
console.error("Not able to parse JSON: ", err);
}
}
}
onNotificationsReceived
のメソッドは、通知を解釈します。応援コメント (cheer) は通知を使用して処理されるため、ビデオとの同期よりも、受信タイミングが重要な場合があります。
newGameFrame
のメソッドは、ストリーム情報を処理しやすい形式に変換します。
updateGameFrame
のメソッドは、フレーム内の情報の分析や更新を行います。このメソッドで、データの表示準備が完了した状態になります。
ut4_gui_playerList.ts¶
ut4_gui_playerList.ts
のファイルは、ビデオの下に表示するコントロールのビューをカプセル化します。また、プレイヤーに重ねて表示するプレイヤーの死亡アイコンを制御します。
PlayerControl
の class には、クリックイベントを処理する単一のコントロールが含まれています。
PlayerIndicatorControl
の class は、プレイヤーの死亡オーバーレイを制御します。
ut4_gui_infoOverlay.ts¶
ut4_gui_infoOverlay.ts
のファイルには、デバッグ情報のオーバーレイが含まれています。
ut4_webgl.ts¶
ut4_webgl.ts
のファイルは、ビデオ上に WebGL オーバーレイを表示します。オーバーレイには、プレイヤー選択とグリッドが含まれます。視聴者がオーバーレイでプレイヤーをクリックすると、プレイヤーが選択されたかどうかを判断する選択ルーチンが呼び出されます。