🌐

node.jsとexpressを使ってやるVideoPlayer/URLTextureの錬金術 - 画像を表示するだけじゃない

2021/12/21に公開

これはるーしっどさん主催のclusterユーザーと再定義する非公式アドカレ Advent Calendar 2021
12月21日の記事です
https://adventar.org/calendars/6363
昨日12月20日の記事は柏葉くるみさんの写真と共にcluster人生を振り返る【前編】 でした
https://note.com/kashiwaba/n/n374b56a73a40

VideoPlayer、URLTextureとかで作ったもの

実際にこれを使って何ができるかを簡単に紹介しておきましょう

ClusTimesワールド版

https://clustimes.com/ワールド版
ClusTimesというcluster向けの記事を4枚程度のポスターにまとめて、ワールド向けに配信しています
2週間に1度配信されるため、一般的な方法では画像を配布し、ワールド制作者の型にワールドを更新してもらう必要がありました
しかし、Unity標準のVideoPlayerにはURLから動画を読み込む機能があります
https://creator.cluster.mu/2021/02/04/set-up-movie/
作成した記事をpngではなく、mp4として出力し、ストレージサーバーに置いておきます
例えばそのストレージサーバーは、ファイルパスをURLに入力することで、httpで直に読み込むことができるとしましょう
その動画のURLを仮にhttp://storage.example.com/video/example.mp4とします
そしてその動画を差し替える場合には、いったんサーバー上からファイルを削除し、同じ名称、ファイルパス上にアップロードした場合、URLを変更することなく、同じURlを通して動画を参照できます
つまり、VideoPlayerを使用した実装により、ワールドを更新せずに、ワールド上の動画を差し替えることができます

URLTextureの登場

10月26日、ClusterCreaterKit v1.14.0のリリースの際に、URLTextureとRawTextureがリリースされました
https://creator.cluster.mu/2021/11/18/url-texture-exhibition/
今までのVideoPlayerでは、mp4などの動画ファイルのみを読み込むことができましたが、このURLTextureによって、pngやjpegの画像をURLから読み込むことができるようになりました

node.jsとexpressとVideoPlayerとURLTexture

さてこれからが本題です
今までに紹介したものは、ストレージサーバーを使用していましたが、node.jsを使用して画像APIを作成することも可能です

作成できるAPIの例

フォルダー上のランダムな画像を返却

ディレクトリ構成

ディレクトリ構成
|-src
|  |-images
|     |-example1.png
|     |-example2.png
|     |-example3.png
|-node_modules
|-index.js
|-pankage.json
|-package-lock.json

パッケージをnpmでインストール

今回はexpressを使用してhttpサーバーを作成します

expressのインストール
npm i express

サンプルコード

index.js
function getRandomInt(max) {  //乱数の生成
    return Math.floor(Math.random() * max);
}

//パッケージの読み込み
const express = require('express');
const app = express();
const fs = require('fs');

app.get('/image', function (req, res, next) {
    try {
        let files = fs.readdirSync('./src/images'); //フォルダー内のファイル一覧を取得
        let return_file = files[getRandomInt(files.length)];  //ランダムで表示するファイルを選択
        fs.readFile(`./src/images/${return_file}`, (err, data) => {  //ファイルを読み込み
            res.type('png');
            res.send(data); //画像を返却
        })
        res.set(``);
    }catch(err){
        console.log(err);
    }
});

app.listen(3030); //ポート3030で開始

実行

CCKを導入したUnityプロジェクトを用意して、今回は、PlayerLocalUI内にURLRawTextureを用意して、以下のように設定しました

ローカル環境での実行の例
これで一応ローカル環境では動きます
ですが、実際にワールドへアップロードし、他のユーザーにしてもらうには、ポート開放(今回は3030)を行い、常に使用できるようにするには、サーバーを常時起動しておく必要があります

ワールド入室時にGETを受け取り、Discordサーバーへメッセージを送信する

VideoPlayerやURLTextureはhttpで画像を取得します
つまり、画像を読み込むときには、サーバーに対してGETを送信します
そのタイミングでDiscordサーバーへメッセージを送信する、いわゆる入室ロガーを作成してみましょう

ディレクトリ構成

ディレクトリ構成
|-node_modules
|-index.js
|-pankage.json
|-package-lock.json

パッケージをnpmでインストール

Discordへメッセージを送信するのに、discord-webhook-nodeを使用します

discord-webhook-nodeのインストール
npm i discord-webhook-node

サンプルコード

index.js
//パッケージの読み込み
const express = require('express');
const app = express();
const { Webhook } = require('discord-webhook-node');
const hook = new Webhook('https://discord.com/api/webhooks/*****************************'); //ここにWebhookのURLを入力

app.get('/discord', function (req, res, next) {
    try {
        hook.success('**ワールドに誰かが来ました**'); //Discordへメッセージを送信する
        res.set(``);
    }catch(err){
        console.log(err);
    }
});

app.listen(3030); //ポート3030で開始

実行

先ほどと同じように、URLTextureまたは、VideoPlayerで、http://localhost:3030/discordへアクセスすることで、Discordへメッセージが送信されます

こんな感じで、node.jsとexpressを使用してさまざまなことができます
ある意味無限の可能性があります

今これで作ってるやつ

Cluster Poster SystemというWebサービスを制作しています

イベントの告知やワールドの紹介などのポスターをこのシステムにWebサイトからアップロードすることで、ワールド向けに自動で配信するシステムです。

画面は開発中のものです
アップロードされたポスターは、ワールド上に設置された画面(URL Raw imageなど)に表示されます。(ポスターをセットアップ済みのアセットも配布予定)

バックエンドの模式図

うまくいけば今月中、1月中にはリリースする予定なので、ぜひ楽しみにしてください

Discussion