メディアアートのためのバックエンド構築入門(Chap.01 Processing & Node.js導入編)

ニューメディアアートやクリエイティブコーディングのための サーバサイドやデータベースを構築する入門用の情報が少ないわりに、 質問されることが多いと感じたので書き始めました。

メディアアートのためのバックエンド構築入門では Processingやp5.jsなどのメディアアート作品の制作に使用される環境を使った、 通信やデータベースの取り扱いについて書いていこうと思います。

全てのソースコードはこちらのリポジトリにまとめて置いていきます。

https://github.com/enkatsu/backend-for-new-media-art

最初のテーマ: データを共有・永続化する

まずはDBにデータを永続化し、 サーバを介してデータを共有するシステムを構築していこうと思います。 構築する環境は以下のようになっています。

bfcc-processing-node-mysql

注意事項

今回は環境構築を容易にするためにDBにSQLiteを使っていますが、 同時アクセスが想定される場合には他のDB(MySQLやPostgreSQLなど)を選定することをお勧めします。 SQLiteは主に組み込み用(スマートフォンアプリなど)のDBとして使われます。 現状では同時書き込みに対応していません。

なので、このブログで紹介するサンプルコードも、 同時に書き込みを行うとエラーが発生すると思います。 このように、実際に作品を制作する際には用途に合わせたDB選定が必要になります。

上記の通り、SQLiteは組み込み用途で使われるので、 むしろProcessingから直接触った方が自然です。 もし、DBとしてSQLiteを選定したなら、 こちらの記事に詳しく書いてあるので、参考にしてみてください。

http://mslabo.sakura.ne.jp/WordPress/make/processing%E3%80%80%E9%80%86%E5%BC%95%E3%81%8D%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/sqlite%E3%82%92%E4%BD%BF%E3%81%86-db%E3%82%AA%E3%83%BC%E3%83%97%E3%83%B3/

事前準備

ProcessingとNode.jsをインストールする

ここでは詳細な説明は省略しますが、 まずProcessingNode.jsをインストールする必要があります。

Processingはこちらのリンクから比較的簡単にインストールできると思います。

https://processing.org/download

またProcessingスケッチでHTTP通信をするためのライブラリとして、 HTTP-Requests-for-Processing を使用しています。 Processing の contribution manager から簡単にインストールできると思うので, 必要に応じてインストールしてください。

Node.jsはこちらのリンクの手順でインストールすることができます。 macOSユーザの方はnvmをインストールしてnsm経由でNode.jsをインストールすることをお勧めします。

https://nodejs.org/en/download/package-manager

サンプルコードをダウンロードする

以下のリンクから.zipでダウンロードできます。

https://github.com/enkatsu/backend-for-new-media-art/archive/refs/heads/main.zip

もしGitを使えるようでしたら git clone でダウンロードしていただいても大丈夫です。

Chap. 01 イントロダクション(Node.js から Processing に データを提供する)

サーバとは、サービスを提供するコンピュータおよびプログラムのことを指します。 また、クライアントとは、サービスを受けるコンピュータおよびプログラムのことを指します。 今回の場合は、HTTPによってサーバとクライアントが通信をするので、 これらをHTTPサーバ、HTTPクライアントといいます。

ここではサービスを提供するのがNode.jsなので、 Node.jsのプログラムとプログラムが実行されるコンピュータをHTTPサーバとします。 また、サービスを受けるのがProcessingなので、 Processingのスケッチとスケッチが実行されるコンピュータをHTTPクライアントとします。

DBを導入する前に、ランダムな円の情報を提供してくれるサーバと、 受け取った円の情報をもとに円を描くクライアントを起動してみましょう。

まずはDBを使わないので図のこの部分だけを扱うことになります。

bfcc-processing-node-mysql

サーバ(Node.js)の起動

サーバは以下のコマンドで起動できます。 npm install はサーバを起動するのに必要なライブラリをインストールするコマンドです。 npm start は実際にサーバを起動するコマンドです。

cd backend-for-new-media-art/chap01-intro/node-server
npm install
npm start

今回のサーバは、Express という軽量なWebフレームワークを使用しています。 以下のコードでは /balls でHTTPリクエストを受け取ったら、 50個の円(ランダムな座標でランダムな大きさ)の情報を提供してくれます。

Copy
const express = require('express')
const app = express()
const port = 3000
app.get('/balls', (req, res) => {
const balls = [];
for (let i = 0; i < 50; i++) {
balls.push({
x: Math.random(),
y: Math.random(),
r: Math.random(),
});
}
res.json({
balls,
})
})
app.listen(port, () => {
console.log(`http://localhost:${port}`)
})

試しに http://localhost:3000/balls をブラウザで開いてみましょう。 ブラウザにJSONの文字列が表示されると思います。

{
    "balls": [
        {
            "x": 0.20340738836683947,
            "y": 0.32331989634177094,
            "r": 0.7617287215962436
        },
        {
            "x": 0.6634966396360533,
            "y": 0.3680254467409587,
            "r": 0.5295844601908122
        },
        {
            "x": 0.6951548346877747,
            "y": 0.1533126911834375,
            "r": 0.3339869693341633
        },
        // ...
    ]
}

このように、サーバがクライアントに提供するHTTPのインタフェースのことを、 Web API(Application Programming Interface) と言います。 私たちが普段ブラウザで情報を閲覧するのと同じように、 Processingスケッチが情報を閲覧しているようなものです。 私たちはWebページのような視覚的に整理された情報が見やすいのですが、 コンピュータにとってはこのようにデータ構造が整理された情報の方が理解しやすいのです。

Tips

なぜwidthからheightではなく、 0から1の数値で管理するのか気になった人もいると思います。 理由としては、クライアントの画面サイズが違くても、 このWeb APIを扱うことができるようにするためです。 このように0から1の値にマッピングされた座標を正規化座標系といいます。 Web APIを開発する際には、 「どのようなクライアントで使われる想定なのか」ということを 考慮して仕様を決める必要があります。

クライアント(Processing)のソースコード

では、提供されたデータをもとに円を描画するスケッチを書いてみましょう。

Copy
import http.requests.*;
String API_URL = "http://localhost:3000/balls";
ArrayList<Ball> balls;
void setup() {
size(640, 480);
balls = new ArrayList<Ball>();
GetRequest get = new GetRequest(API_URL);
get.send();
JSONObject result = parseJSONObject(get.getContent());
JSONArray ballsData = result.getJSONArray("balls");
for (int i = 0; i < ballsData.size(); i++) {
JSONObject ballData = ballsData.getJSONObject(i);
Ball ball = new Ball(
ballData.getFloat("x") * width,
ballData.getFloat("y") * height,
ballData.getFloat("r") * 9 + 1
);
balls.add(ball);
}
}
void draw() {
background(0);
for (Ball ball: balls) {
ball.draw();
}
}
Copy
class Ball {
float x, y, r;
Ball(float x, float y, float r) {
this.x = x;
this.y = y;
this.r = r;
}
void draw() {
noStroke();
fill(100, 200, 250);
ellipse(x, y, r * 2, r * 2);
}
}

実行結果

chap01

このような画面が表示されましたか?

このスケッチは実行する度にサーバにリクエストして円の情報を取得します。 サーバはその度にランダムな円の情報を計算して提供します。 なので、このスケッチは実行するたびに、円が異なる座標に異なる大きさで表示されます。

続きはこちらの記事に書いていきます。

余談

GitHubで管理しているソースコードと、 記事に書いているソースコードのバージョン管理が面倒だったので、 GitHubのソースコードをHTMLに埋め込めないか探してみました。 意外と少ないんですね……

emgithubというページが見つかったので使いましたが、 リポジトリのURLをコピー -> emgithubにペースト -> <script> を書き出し という手順は少し面倒でした。

今後も何かいい方法を探ろうと思います。

https://github.com/yusanshi/emgithub


メディアアートやクリエイティブコーディングのためのバックエンド構築入門(Chap.01 Processing & Node.js導入編)

By Katsuya Endoh, 2024-06-22