ニューメディアアートやクリエイティブコーディングのための サーバサイドやデータベースを構築する入門用の情報が少ないわりに、 質問されることが多いと感じたので書き始めました。
メディアアートのためのバックエンド構築入門では Processingやp5.jsなどのメディアアート作品の制作に使用される環境を使った、 通信やデータベースの取り扱いについて書いていこうと思います。
全てのソースコードはこちらのリポジトリにまとめて置いていきます。
https://github.com/enkatsu/backend-for-new-media-art
最初のテーマ: データを共有・永続化する
まずはDBにデータを永続化し、 サーバを介してデータを共有するシステムを構築していこうと思います。 構築する環境は以下のようになっています。
注意事項
今回は環境構築を容易にするためにDBにSQLiteを使っていますが、 同時アクセスが想定される場合には他のDB(MySQLやPostgreSQLなど)を選定することをお勧めします。 SQLiteは主に組み込み用(スマートフォンアプリなど)のDBとして使われます。 現状では同時書き込みに対応していません。
- https://www.publickey1.jp/blog/23/sqlitebegin_concurrent.html
- https://pandaman64.hatenablog.jp/entry/2023/08/01/215842
なので、このブログで紹介するサンプルコードも、 同時に書き込みを行うとエラーが発生すると思います。 このように、実際に作品を制作する際には用途に合わせたDB選定が必要になります。
上記の通り、SQLiteは組み込み用途で使われるので、 むしろProcessingから直接触った方が自然です。 もし、DBとしてSQLiteを選定したなら、 こちらの記事に詳しく書いてあるので、参考にしてみてください。
事前準備
ProcessingとNode.jsをインストールする
ここでは詳細な説明は省略しますが、 まずProcessingと Node.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を使わないので図のこの部分だけを扱うことになります。
サーバ(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個の円(ランダムな座標でランダムな大きさ)の情報を提供してくれます。
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)のソースコード
では、提供されたデータをもとに円を描画するスケッチを書いてみましょう。
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(); } }
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); } }
実行結果
このような画面が表示されましたか?
このスケッチは実行する度にサーバにリクエストして円の情報を取得します。 サーバはその度にランダムな円の情報を計算して提供します。 なので、このスケッチは実行するたびに、円が異なる座標に異なる大きさで表示されます。
続きはこちらの記事に書いていきます。
余談
GitHubで管理しているソースコードと、 記事に書いているソースコードのバージョン管理が面倒だったので、 GitHubのソースコードをHTMLに埋め込めないか探してみました。 意外と少ないんですね……
emgithubというページが見つかったので使いましたが、
リポジトリのURLをコピー -> emgithubにペースト -> <script> を書き出し
という手順は少し面倒でした。
今後も何かいい方法を探ろうと思います。