ノードエディタ形式の画像・オーディオ処理ツール「Multimodal-Node-Editor」
はじめに
ノードエディタ形式の画像・オーディオ処理ツール「Multimodal-Node-Editor」を作りました。
今まで以下の、ノードエディタ形式の画像処理ツール「Image-Processing-Node-Editor」、オーディオ処理ツール「Audio-Processing-Node-Editor」を作ってきました。
しかし、これらのアプリは、初期設計をワーッとやって、実装をガーッとやった結果、
色々設計が微妙なところとか、実装が微妙なところとか、
良かれと思って入れた設計が裏目に出ていたところとか、
ちょいちょいあり、ずーっと作り直したいなー。と思っていました。
(特にノード追加方法とか、GUIに自由度を持たせようとした結果、実装漏れが発生しやすいつくりになっていたり。。。)
改めて、設計・実装を刷新し、画像やオーディオを1つのノードエディターで扱えるようにしたのが、「Multimodal-Node-Editor」です。
ちなみに、裏の目的として「フルコーディングエージェントで、ある程度の規模のアプリを作る」経験をしたかった。と言う目的があります。
今まで業務や趣味では、小さなデモ作成や機能追加・機能修正でしか使用していなかったため、使い勝手やハマリどころを体験したく。
ちなみにちなみに、今回も見切り発車でClaude Codeを駆使して作り始め、
その後、年末年始にスペック駆動開発の本を読んだ結果、
早くもClaude Code周りの設定を刷新して、設計・実装も刷新したい気持ちが湧いています😇
まあ「家は3回建てないと理想の家にならない」と言われるように、
ソフトウェアも3回は設計・実装を刷新しないと満足いくものは出来ませんよね。。。( ´ー`)y-~~
「Multimodal-Node-Editor」とは
以下のように、ノードを接続していくことで、画像処理やオーディオ処理、OpenAI API を利用した LLM や VLM が実行できるツールです。
ちなみに「Image-Processing-Node-Editor」は常に処理が動作していましたが、オーディオ処理と統合した結果、Startボタンで明確に処理開始を指示する仕様に変更しました。

特徴
以下のような特徴があります。
- 画像・音声・テキスト・深層学習など、100 以上のノードを標準搭載
- TOML + Python による新規ノードの簡単な追加が可能(GUI を自作しない場合)
- Cropなどの一部ノードでマウス操作での指定に対応
- 簡易オートレイアウト機能
- ノードへのコメント機能
- Google Colaboratory バックエンドでのシステム起動可能
- 保存したグラフを ReactFlow GUI なしでヘッドレス実行可能
- モデルウェイトの保存方法を変更し、「Image-Processing-Node-Editor」「Audio-Processing-Node-Editor」では対応していなかった100MB以上のサイズの重みへ対応
- 「Image-Processing-Node-Editor」「Audio-Processing-Node-Editor」の放置不具合の根本改善(ノード配置前しかグラフjsonをロードできない問題、ノードを重ねた時にヒストグラムなどの表の表示が崩れる問題、エッジ接続解除時に線描画が残る問題、など)
いくつかの特徴の詳細はこちら↓
詳細:TOML + Python による新規ノードの簡単な追加が可能(GUI を自作しない場合)
「Image-Processing-Node-Editor」では、GUI実装の自由度が高すぎたため、
TOML(ノードのメタデータ + GUI情報)とPython(実装)に分離して、GUIパーツを絞ることで比較的シンプルな実装になるよう変更。
※GUIパーツを用意する形式にしたため、パーツにないGUIを作ろうとするとそれなりに苦労が発生しますが。。。 ※既に再設計したい箇所の第一位😇
以下は、Image/Filter/Cannyノードの実装例。
toml例
name = "image.filter.canny"
version = "1.0.0"
display_name = "Canny"
description = "Applies Canny edge detection to an image."
order = 50
gui = ["reactflow", "headless"]
[[ports]]
name = "image"
data_type = "image"
direction = "inout"
[[ports]]
name = "low_threshold"
data_type = "float"
direction = "in"
[[ports]]
name = "high_threshold"
data_type = "float"
direction = "in"
[[properties]]
name = "low_threshold"
display_name = "Low"
type = "int"
default = 50
widget = "slider"
min = 0
max = 255
[[properties]]
name = "high_threshold"
display_name = "High"
type = "int"
default = 150
widget = "slider"
min = 0
max = 255
python例
from typing import Dict, Any
from node_editor.node_def import ComputeLogic
import cv2
class CannyNodeLogic(ComputeLogic):
"""
Cannyエッジ検出を実行するノードロジック。
入力・出力ともにOpenCV画像(numpy配列)。Base64変換はcore.pyで自動処理。
"""
def compute(
self,
inputs: Dict[str, Any],
properties: Dict[str, Any],
context: Dict[str, Any] = None,
) -> Dict[str, Any]:
img = inputs.get("image")
if img is None:
return {"image": None}
low_threshold = int(properties.get("low_threshold", 50))
high_threshold = int(properties.get("high_threshold", 150))
# グレースケールに変換
if len(img.shape) == 2 or img.shape[2] == 1:
gray = img
else:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, low_threshold, high_threshold)
# 出力をBGRに変換(他ノードとの互換性のため)
edges_bgr = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)
return {"image": edges_bgr}
詳細:Cropなどの一部ノードでマウス操作での指定に対応
数は多くありませんが、以下のようにマウス操作で領域指定などが出来るノードを実装しました。

詳細:簡易オートレイアウト機能
簡易的なアルゴリズムのため、つなぎ方によってはエッジが交差してしまいますが、
オートレイアウト機能を用意しました。

詳細:ノードへのコメント機能
ノードに対してコメントを付与できるようになりました。

詳細:Google Colaboratory バックエンドでのシステム起動可能
システム構成を、ReactFlow ⇔ FastAPI ⇔ 自作ノードエディターコア に変更し、
Google Colaboratoryバックエンドでの起動も可能になりました。

詳細:保存したグラフを ReactFlow GUI なしでヘッドレス実行可能
たとえば、ReactFlow上で作成した以下のようなフローをグラフjsonとして保存して、

その後、ヘッドレス実行用のスクリプトrun_headless.pyで、ノードエディターを介さずに実行ができます。
※プレビュー画像などをReactFlow⇔FastAPIでやりとりしているため、ReactFlow利用時ではGUIのオーバーヘッドが数ms~数十msありました

アーキテクチャ概要
ざっくり概要ですが、以下のように、フロントエンド(ReactFlow)、バックエンド(FastAPI)、コア、ノード群のような構成になっています。

フロントエンド(ReactFlow):
ノードエディタUI、画像/音声プレビュー表示、履歴管理 など
バックエンド(FastAPI):
REST APIエンドポイント提供 など
コア:
データモデル定義、グラフ実行エンジン など
ノード群:
ノードの構成定義、個々のノードの計算ロジック実装 など
動作シーケンスのざっくり概要は以下↓
アプリ起動シーケンス
グラフ実行シーケンス(START〜実行ループ〜STOP)
動作例
今までの「Image-Processing-Node-Editor」「Audio-Processing-Node-Editor」で出来なかった事例をいくつか記載しています。
運転動画を15秒おきに OpenAI VLM で解析

LLIE した動画に Before/After の HSV ヒストグラムを重畳表示

動画へウェーブフォームやスペクトログラムを結合

OpenAI LLM を用いた Python コードの自動生成

まとめ
画像処理と音声処理、それぞれで作っていたノードエディターを統合し、
設計・実装を一から見直した「Multimodal-Node-Editor」を公開しました。
今回の Multimodal-Node-Editor では、
・画像・音声・テキスト・深層学習を1つのノードエディターで扱えること
・TOML + Python による比較的シンプルなノード追加方法
・ReactFlow を使わずに実行できるヘッドレス実行
・Colaboratory をバックエンドにシステム起動
・過去ツールで抱えていた設計・実装上の問題の改善
といった点を重視して作り直しています。
(すでに「ここは再設計したい……」という箇所はちょいちょいありますが😇)
興味があれば、ぜひ触ってみてください🦔
Discussion