ブラウザ上の p5.js のプログラムで OSC を使う(サーバー・クライアントは osc-js で実装)


以下の記事の続きです。

●ブラウザで OSC を扱う初めの一歩(osc.js、osc-js、p5.js用ライブラリを見てみたりなど)【2021年9月】 - Qiita
 https://qiita.com/youtoy/items/efe9b07be57454dec5d5

上記の記事の中で記載していた「osc-js」を使い、Node.js でサーバーを用意しつつ、ブラウザ上で動くクライアントも実装してみます(osc-js を使いつつ、p5.js と併用する形)。

OSC のサーバー(WebSocket を利用するもの)を Node.js + osc-js で準備

前の記事にも書いたように、ブラウザで扱う場合は WebSocket を使う形になるため、仲介役になるサーバーが必要です。

それについて、osc-js の Wiki の「Node.js Server」の項目を見つつ、準備していきます。

Node.js の npm コマンドで、osc-js を準備します。
今回、グローバルインストールではなくローカルインストールで進めます。

$ npm install osc-js

上記でインストール後に、こちらを使ったサンプルプログラムを準備します。
公式の内容をほぼそのまま使う形で用意します(ファイル名は「app.js」にしました)。

app.js
const OSC = require('osc-js')

const plugin = new OSC.WebsocketServerPlugin({ port: 9912 })
const osc = new OSC({ plugin: plugin })

osc.on('/test', message => {
  console.log(message.args)
})

osc.on('open', () => {
  console.log("open");
  setInterval(() => {
     osc.send(new OSC.Message('/response', Math.random()))
  }, 1000)
})

osc.open()

そして、以下のコマンドでサーバーを立ち上げます。

ブラウザで動く OSC のクライアントを osc-js で準備

サーバーの準備ができたところで、それに接続するクライアントを準備します。

プログラムは、オンラインの開発・実行環境である p5.js Web Editor を使ってみようと思います。

ライブラリの読み込み

p5.js Web Editor のサンプルプログラムでは osc-js を利用できないので、ライブラリの読み込みをするようにします。

index.html で、以下のページに掲載された CDN上のライブラリの URL を読み込みます。
 ●osc-js CDN by jsDelivr - A CDN for npm and GitHub
  https://www.jsdelivr.com/package/npm/osc-js

具体的には https://cdn.jsdelivr.net/npm/[email protected]/lib/osc.min.js です。

サーバーにメッセージを送るプログラムを軽く動かしてみる

以下の公式の Wiki の内容を見つつ、まずはサーバーに接続する部分を最小限で作ってみます。
 ●Websocket Client Plugin · adzialocha/osc-js Wiki
  https://github.com/adzialocha/osc-js/wiki/Websocket-Client-Plugin

上記のサンプルそのままだと、接続先が「ws://localhost:8080」になり、ポート「9912」で待ち受けているサーバーにつながらないので、この部分はポート指定を行うようにします。
また、Webページ上のボタンをクリックして動作させる前提の部分も、p5.js用の処理に置きかえます。

具体的には、以下のようなソースコードになりました。

sketch.js
let osc;

function setup() {
  createCanvas(400, 400);

  osc = new OSC();
  osc.open({ port: 9912 });
}

function draw() {
  background(220);
}

function keyPressed() {
  if(key === 's') {
    const message = new OSC.Message("/test", Math.random());
    osc.send(message);

    console.log("send message")
  }
} 

これで、3回くらいメッセージ送信を行ってみると、クライアント・サーバー側のそれぞれのメッセージ出力が以下のようになりました。

【クライアント側の出力(メッセージ送信側)】

【サーバー側の出力(メッセージ受信側)】

クライアント側でサーバーからのメッセージを受けとってみる

今回動かしているサーバー側のサンプルは、setInterval() で定期的なメッセージ送信をしています。
それをクライアント側(ブラウザで動いているプログラム)で受信して出力できるよう、プログラムを書きかえてみます。

差分は数行ほどになりますが、書きかえ後のプログラム全体は以下のとおりです。

let osc;

function setup() {
  createCanvas(400, 400);

  osc = new OSC();
  osc.open({ port: 9912 });

  osc.on("/response", (message) => {
    console.log(message.args);
  });
}

function draw() {
  background(220);
}

function keyPressed() {
  if (key === "s") {
    const message = new OSC.Message("/test", Math.random());
    osc.send(message);

    console.log("send message");
  }
}

これで、ブラウザ側のコンソール出力を見てみると、一定時間ごとに数値が出力がされて以下のようになりました。

正常に動作していそうです。

おわりに

今回、p5.js で OSC を扱うために osc-js というライブラリを用いた実装を行いました。

サーバー側もクライアント側(ブラウザ側)も osc-js を用いたプログラムを動かし、双方向のメッセージのやりとりができたことを確認できました。

今後は、別のデバイス・アプリ・プログラムとの間の OSC を用いた通信を試せればと思います。

追記

UDP を使った OSC通信についても試して記事にしました。

●ZIG SIM と Node.js のプログラム(osc.js を利用)との間で UDP による OSC通信を軽く試す(OSC Data Monitor の話も) - Qiita
 https://qiita.com/youtoy/items/fddc750759f4ecef7ca7

上記について、当初は osc.js ではなく今回使った osc-js を使おうとしました。
でも、UDP を用いた通信がうまくいかず、自分の実装・使い方がまずいだけかもしれないですが osc.js を使ってみることにしました。