unityController - Genvid クライアント初期化¶
Genvid クライアント初期化セクションには、ストリーム開始、さまざまな変数の初期化、イベントリスナーの割り当てに必要なほとんどのコードが含まれています。
In This Section
onConnect¶
onConnect()
onConnect メソッドがサービスへの接続を開始します。接続が適切に実行できると、検出した IChannelJoinResponse()
で on_channel_join
を実行します。
// Start the connection to the services
onConnect() {
let promise = $.post("/api/public/channels/join", {}, (joinRep) => {
this.on_channel_join(<genvid.IChannelJoinResponse>joinRep);
});
promise.fail((err) => {
alert("Can't get the stream info:" + err);
});
}
on_channel_join¶
on_channel_join(info: genvid.IChannelJoinResponse)
on_channel_join メソッドは、サービスとチャネルに接続後、Genvid クライアントを作成します。このプロセスで検出された情報と、class 作成プロセスで送信された video_player_id
を使用してクライアントを作成します (これは unityController class の引数です)。
その後、この class に特定のイベントを関連付ける必要があります。
- onVideoPlayerReady
- ビデオストリームの準備が完了した時にトリガします (コンテンツの初期化に使用)。
- onStreamsReceived
- ストリームコンテンツを受信した時にトリガします (タイムコードとゲームデータの取得に使用)。
- ゲームデータの取得に使用)。
- onNotificationsReceived
- 通知を受信した時にトリガします (popularity に使用)。
- onDraw
- ビデオで新しいフレームの描画時にトリガします。
次に、 start()
メソッドでクライアントを開始します。
// Create the genvid Client and the function listening to it
private on_channel_join(joinRep: genvid.IChannelJoinResponse) {
this.streamInfo = joinRep.info;
this.client = genvid.createGenvidClient(this.streamInfo, joinRep.uri, joinRep.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.onDisconnect(() => {this.on_disconnect_detected();});
this.client.start();
}
on_disconnect_detected¶
on_disconnect_detected()
このサンプルでは、onDisconnect()
コールバック (IGenvidClient()
インターフェイスにより公開) を使って、クライアントのソケットが閉じるタイミングを通知します。指定のコールバックをバインドすることで、実行しています。
this.client.onDisconnect(() => {this.on_disconnect_detected();});
クライアントソケットの閉鎖通知が届いたら、スクリプトに再接続試行の指示を行います。
private on_disconnect_detected(){
let promise = $.post("/api/public/channels/join", {}, (joinRep) => {
this.client.reconnect(joinRep.info, joinRep.uri, joinRep.token);
this.resetFibNums();
});
promise.fail( async () => {
await this.sleep(this.getNewSleepDuration());
this.on_disconnect_detected();
});
}
ここで、新しい leaf アドレス、新しいトークン、新しい streamInfo の情報リクエストを行います。
リクエストが成功した場合、reconnect()
を呼び出して、この情報を使用して新しい websocket 接続を確立します。
リクエストが失敗した場合 (利用可能な leaf がないなど)、しばらく待って再試行します。インクリメンタルなフィボナッチ数の計算結果を使用して、待機時間を決定します。
private sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
private getNewSleepDuration() {
this.fibNumResult = this.fibNumOne + this.fibNumTwo;
this.fibNumOne = this.fibNumTwo;
this.fibNumTwo = this.fibNumResult;
this.delayBetweenReconnectionAttempts = this.fibNumResult + (this.fibNumResult * Math.floor(Math.random() * 10) * 0.01); // + 0 to 10%
return this.delayBetweenReconnectionAttempts * 1000; // milliseconds
}
private resetFibNums() {
this.fibNumOne = 0;
this.fibNumTwo = 1;
}
フィボナッチ数列の結果に 10% のランダム要素を追加します。これにより、2 つのサービスが同時に接続を開始する状況を回避します。接続に成功したときにフィボナッチ数をリセットします。
on_video_player_ready¶
on_video_player_ready(_elem: HTMLElement)
変数の開始、WebGL コンテキストの作成、イベントリスナーの追加に使用します。
この関数では、Div と Link エレメントのほとんどを JQuery で取得します。
this.video_player = this.client.videoPlayer; this.timeLocalDiv = <HTMLDivElement>document.querySelector("#time_local"); this.timeVideoDiv = <HTMLDivElement>document.querySelector("#time_video"); this.timeVideoRawDiv = <HTMLDivElement>document.querySelector("#time_video_raw"); this.timeComposeDiv = <HTMLDivElement>document.querySelector("#time_compose"); this.timeComposeLastDiv = <HTMLDivElement>document.querySelector("#time_compose_last"); this.timeStreamDiv = <HTMLDivElement>document.querySelector("#time_stream"); this.latencyDiv = <HTMLDivElement>document.querySelector("#latency"); this.delayOffsetDiv = <HTMLDivElement>document.querySelector("#delay_offset"); this.controlsDiv = <HTMLDivElement>document.querySelector("#game-controls"); this.timeCamSceneDiv = <HTMLDivElement>document.querySelector("#timeCamScene_overlay"); this.promptOverlay = <HTMLDivElement>document.querySelector("#prompt_overlay"); this.videoOverlay = <HTMLDivElement>document.querySelector("#video_overlay"); this.canvas3d = <HTMLCanvasElement>document.querySelector("#canvas_overlay_3d"); this.mouseOverlay = <HTMLDivElement>document.querySelector("#mouse_overlay"); this.genvidOverlayButton = <HTMLLinkElement>document.querySelector("#genvid_overlay_button"); this.genvidOverlay = <HTMLDivElement>document.querySelector("#genvid_overlay"); this.help_overlay = <HTMLDivElement>document.querySelector("#help_overlay"); this.helpButton = <HTMLLinkElement>document.querySelector("#help_button"); this.fullScreenDiv = <HTMLDivElement>document.querySelector(".fullscreen-button"); this.fullScreenElement = <HTMLElement>document.querySelector(".fa-expand");
canvas3d を選択して WebGLContext を作成します。
ウィンドウ変更のイベントリスナー (全画面、サイズ変更) をすべて追加します。
mouseOverlay のクリック操作用イベントリスナー (ビデオオブジェクトのクリック判定用)、 Genvid ボタン、 Help ボタンのクリック操作用イベントリスナーを追加します。
this.hideOverlay(); this.client.videoPlayer.addEventListener(genvid.PlayerEvents.PAUSE, () => { this.hideOverlay(); }); this.client.videoPlayer.addEventListener(genvid.PlayerEvents.PLAYING, () => { this.showOverlay(); }); this.genvidWebGL = genvid.createWebGLContext(this.canvas3d); // Need to assign before any resize. document.addEventListener("fullscreenchange", () => { this.onResize(); }); document.addEventListener("webkitfullscreenchange", () => { this.onResize(); }); document.addEventListener("mozfullscreenchange", () => { this.onResize(); }); _elem.addEventListener("resize", () => { this.onResize(); }); window.addEventListener("resize", () => { this.onResize(); }, true); window.addEventListener("orientationchange", () => { this.onResize(); }, true); window.addEventListener("sizemodechange", () => { this.onResize(); }, true); window.setInterval(() => { this.onResize(); }, 1000); // Just a safety, in case something goes wrong. this.mouseOverlay.addEventListener("click", (event) => { this.clickCube(event); }, false); this.genvidOverlayButton.addEventListener("click", (_event) => { this.toggleGenvidOverlay(); }, false); this.helpButton.addEventListener("click", (_event) => { this.onHelpActivation(); }, false); this.fullScreenDiv.addEventListener("click", (_event) => { this.toggleFullScreen(); }, false);
onResize() を実行して、適切なウィンドウサイズにオーバーレイを合わせます (この処理を行わないと、オーバーレイが小さくなりすぎます)。
最後に WebGL オーバーレイを初期化します。
this.onResize(); // Initialize graphics stuff. this.genvidWebGL.clear(); let gl = this.genvidWebGL.gl; gl.disable(gl.DEPTH_TEST); this.gfx_initShaders(); this.gfx_initRenderCommands(); const muteIcon = document.getElementById("mute-button"); muteIcon.addEventListener("click", () => this.onMute()); if (!this.video_player.getMuted()) { this.onMute(); } this.videoReady = true;