いいね、そのレイヤーに来たか。
じゃあ「Plugin → Webサーバ → Roblox」の通信を、OSレベルの正式仕様として一度きっちり言語化しよう。


全体像:レイヤーと責務

  • Plugin Layer(作者のIDE層)
    • ユーザー操作・UI・パラメータ編集
    • 「こういう曲を生成して」と AI サーバにリクエストを送る
  • Webサーバ / AI Layer(意味生成層)
    • Structure / Melody / Rhythm を生成
    • 最終的に Playback JSON v1 を返す
  • Roblox Game Layer(物理層)
    • 受け取った JSON をそのまま PlaybackEngine に渡して「鳴らすだけ」

1. 通信方向とトランスポート

  • Plugin → Webサーバ
    • HTTP(S) POST /generateSong
    • Content-Type: application/json
  • Webサーバ → Plugin
    • 同じく HTTP レスポンスで JSON を返す
  • Plugin → Roblox Game
    • RemoteEvent / RemoteFunction(Roblox 標準)←直接は不可
    • ReplicatedStorage:WaitForChild("PlaybackRequest") など

2. Plugin → Webサーバ リクエスト仕様

エンドポイント

  • POST /generateSong

Request JSON(例:v1.0)

{
  "version": "1.0",
  "projectId": "love_dance_demo_001",
  "seed": 12345,
  "bpm": 128,
  "lengthBeats": 128,
  "style": "LoveDance",
  "structure": {
    "sections": [
      { "name": "Intro", "startBeat": 0, "lengthBeats": 16 },
      { "name": "A",     "startBeat": 16, "lengthBeats": 32 },
      { "name": "B",     "startBeat": 48, "lengthBeats": 32 }
    ]
  },
  "tracks": [
    { "role": "Lead",  "instrument": "SynthLead", "enabled": true },
    { "role": "Pad",   "instrument": "Pad",       "enabled": true },
    { "role": "Bass",  "instrument": "Bass",      "enabled": true },
    { "role": "Drums", "instrument": "Drums",     "enabled": true }
  ]
}

ポイント

  • Plugin は「意味の要求」だけ送る
    • BPM / 長さ / スタイル / セクション構造 / トラック構成
  • 音符は 一切送らない(それは AI の責務)

3. Webサーバ → Plugin レスポンス仕様(Playback JSON v1)

Response JSON

{
  "version": "1.0",
  "projectId": "love_dance_demo_001",
  "bpm": 128,
  "tracks": [
    {
      "instrument": "SynthLead",
      "notes": [
        { "note": 72, "velocity": 110, "startBeat": 16.0, "durationBeats": 0.5 },
        { "note": 76, "velocity": 105, "startBeat": 16.5, "durationBeats": 0.5 }
      ]
    },
    {
      "instrument": "Bass",
      "notes": [
        { "note": 36, "velocity": 120, "startBeat": 16.0, "durationBeats": 1.0 }
      ]
    }
  ]
}

ここが OS 的に重要

  • Roblox 側は この JSON だけ知っていればよい
  • note / velocity / startBeat / durationBeats / instrument / bpm
  • それ以外の意味・理論はすべて AI 側に閉じ込める

4. Plugin → Roblox Game 通信仕様

RemoteEvent 名

  • PlaybackRequest(例)

送るデータ構造(Lua テーブル)

local playbackData = {
    version = "1.0",
    bpm = songJson.bpm,
    tracks = songJson.tracks
}

PlaybackRequest:FireServer(playbackData)

サーバ側受信

PlaybackRequest.OnServerEvent:Connect(function(player, playbackData)
    -- ここで PlaybackEngine.playSong(playbackData, baseNote) を呼ぶだけ
end)

ポイント

  • Plugin は「ただ JSON を Lua テーブルにして渡すだけ」
  • Game サーバは「ただ PlaybackEngine に渡すだけ」
  • 双方とも 音楽理論を一切知らない

5. バージョニングと互換性

トップレベルに version を必須

  • "version": "1.0"
  • 将来:
    • 1.1 で swing, humanize, automation などを追加しても
    • 1.0 のフィールドは壊さない

Plugin 側の方針

  • 未知のフィールドは 無視
  • version が想定外なら:
    • ログに警告
    • それでも基本フィールドがあれば鳴らす

6. セキュリティ / 儀式的制約

  • Plugin → Webサーバ
    • APIキー or トークン(ヘッダ)
    • 例:X-Client-Id, X-Auth-Token
  • Plugin → Roblox Game
    • RemoteEvent は Plugin からのみ呼ぶ前提(開発用)
    • 公開ゲームで使う場合は:
      • サーバ側で player を検証
      • 必要なら projectId と player.UserId を紐づける

7. OS 的まとめ

  • Structure / Melody / Rhythm / Playback の責務分離
    • Structure〜Rhythm:AIサーバ
    • Playback:Roblox(物理層)
  • Plugin の役割
    • 人間の意図 → AIリクエスト
    • AIレスポンス → Roblox に橋渡し
  • Roblox の役割
    • 「Playback JSON v1」を受け取り、
      PlaybackEngine に渡して ただ鳴らすだけ

ここまでが「通信プロトコル仕様 v1.0」の骨格。

次の一手としては:

  • Playback JSON v1 の正式スキーマ(擬似 JSON Schema)を書く
  • Plugin UI の「プリセット → リクエスト JSON 変換表」を OS 化する
  • Mixing Layer(音量・パン・FX)をどのレイヤーに置くか決める

どこから OS 図に落としていきたい?