技術アーキテクチャ
概要
技術スタック
| コンポーネント | 技術 | 役割 |
|---|---|---|
| デスクトップフレームワーク | Tauri 2.x (Rust) | ネイティブウィンドウ、IPC、パッケージング |
| インターフェース | Vue.js 3 + Composition API | リアクティブUI |
| 状態管理 | Pinia | グローバル状態 |
| 国際化 | vue-i18n | FR / EN / ES / JA |
| 通信 | WebSocket (tokio-tungstenite) | OBSオーバーレイ + Stream Deck |
| ユニットテスト | Vitest | コンポーザブル、ストア |
| E2Eテスト | Playwright | フルフロー |
4つのコンポーネント
1. メインアプリケーション(Tauri)
システムの中核。ユーザーがセットリストを管理し、デッキを設定し、再生を制御します。変更があるたびに、すべての接続クライアントへWebSocketブロードキャストが送信されます。
UIサイドはVue.js 3、バックエンドはRustで構築。Tauriが型付きIPCコマンドで両者を橋渡しします。
2. OBSオーバーレイ
OBS Studioにブラウザソースとして追加するシンプルなHTMLファイル(obs-overlay/index.html)。アプリのWebSocketに接続し、PLAYING_UPDATEメッセージごとに表示を更新します。外部サーバー不要 — すべてlocalhost経由。
3. Stream Deckプラグイン
Elgato Stream Deck用のJavaScriptプラグイン。各ボタンはデッキを表します。同じWebSocketに接続し、コマンドを送り返します(TOGGLE_DECK、PLAY_TRACK、STOP_DECK)。ボタンは動的に更新されます(アートワーク、タイトル、再生/アイドル状態)。
4. dlp-player npmウィジェット
スタンドアロンのJavaScriptパッケージ(npm公開予定)。DLPからエクスポートしたプレイリストJSONを読み込み、メディアプレーヤー(<video>、<audio>、YouTubeまたはSoundCloudのiframe)とトラック表示を同期します。2つの表示モード:list(プレーヤーの横にトラックリスト)とoverlay(下部に重ねて表示)。デスクトップアプリへの依存なし — 完全にクライアントサイドで動作します。
WebSocketサーバー
Rustバックエンドはアプリ起動時にlocalhost:9876でWebSocketサーバーを開始します。以下を処理:
- 複数接続 — OBSオーバーレイとStream Deckを同時接続可能
- ブロードキャスト — トラックが変わると、すべてのクライアントが
PLAYING_UPDATEを受信 - 設定同期 — Stream Deckプラグインは起動時に
GET_DECKS_CONFIGを送信して設定済みデッキを取得
プロトコル
任意のWebSocketクライアントが接続可能 — 認証不要、サーバーはローカルのみ。
const ws = new WebSocket('ws://localhost:9876')
ws.onmessage = (event) => {
const { type, payload } = JSON.parse(event.data)
if (type === 'PLAYING_UPDATE') {
// 表示を更新
}
}送信メッセージ(App → クライアント)
PLAYING_UPDATE — 再生中のトラックが変わったときに送信。
{
"type": "PLAYING_UPDATE",
"payload": {
"tracks": [
{
"id": "uuid",
"title": "トラックタイトル",
"artist": "アーティスト名",
"image": "data:image/jpeg;base64,... または URL",
"deckName": "Vinyl 1",
"qrCodeUrl": "https://..."
}
]
}
}DECK_CANDIDATES — GET_DECK_CANDIDATESへの応答。指定デッキの候補トラックを提供。
{
"type": "DECK_CANDIDATES",
"payload": {
"deckId": "deck-1",
"currentlyPlaying": { "id": "...", "title": "...", "artist": "...", "image": "..." },
"lastPlayed": { "id": "...", "title": "...", "artist": "...", "image": "..." },
"nextUnplayed": { "id": "...", "title": "...", "artist": "...", "image": "..." }
}
}DECKS_CONFIG — GET_DECKS_CONFIGへの応答。設定済みの全デッキを一覧。
{
"type": "DECKS_CONFIG",
"payload": {
"decks": [
{ "id": "deck-1", "name": "Vinyl 1", "deckType": "vinyl", "image": "data:image/png;base64,..." },
{ "id": "deck-2", "name": "CDJ 1", "deckType": "cd", "image": "data:image/png;base64,..." }
]
}
}CONFIG_UPDATE — オーバーレイのビジュアル設定が変更されたときに送信(テーマ、表示オプション、アニメーション)。
受信メッセージ(クライアント → App)
| メッセージ | ペイロード | 説明 |
|---|---|---|
GET_DECKS_CONFIG | {} | 設定済みデッキの一覧を要求 |
TOGGLE_DECK | { "deck_id": "deck-1" } | デッキのオン/オフ切り替え |
GET_DECK_CANDIDATES | { "deck_id": "deck-1" } | デッキの候補トラックを要求 |
PLAY_TRACK | { "track_id": "uuid" } | 特定のトラックを再生開始 |
STOP_DECK | { "deck_id": "deck-1" } | デッキを停止 |
デッキタイプ
| 値 | 説明 |
|---|---|
vinyl | ターンテーブル |
cd | CDプレーヤー / CDJ |
controller | DJコントローラー |
software | ソフトウェア(Rekordbox、Serato、Traktor...) |
バージョン管理
バージョンはpackage.jsonに一度だけ定義され、sync-version.jsスクリプトでtauri.conf.jsonとCargo.tomlに自動同期。npmのprebuild/pretauriフックで各buildとtauriの前に自動呼び出し。

