API 仕様書

Live Comment Hub — Base URL: http://localhost:11280

API 連携でできること

独自オーバーレイ

外部アプリ連携

リアルタイム演出

サンプルから開始

3分で使い始める

var es = new EventSource('http://localhost:11280/api/stream');

es.onmessage = function (event) {
  var msg = JSON.parse(event.data);

  if (msg.type === 'version') {
    console.log('App version:', msg.data);
    return;
  }

  if (msg.type === 'reload') {
    console.log('Overlay reload requested');
    location.reload();
    return;
  }

  if (msg.type === 'status') {
    console.log('Connected:', msg.data.connected, 'videoId:', msg.data.videoId);
    return;
  }

  if (msg.type === 'event') {
    if (msg.event === 'comment') {
      console.log(msg.data.name + ': ' + msg.data.comment);
    } else if (msg.event === 'reaction') {
      console.log('Reaction:', msg.data.emoji, 'x' + msg.data.count);
    }
  }
};

エンドポイント早見表

sample-overlay-demo.zip
GET /api/stream
GET /api/status
GET /api/events
GET /api/comments
GET /effects/{sceneId}/
GET /effects/{sceneId}/stream
POST /api/trigger/{sceneId}/{performanceId}

SSE ストリーム(リアルタイム)

GET /api/stream

接続直後に来るもの

  • version
  • status

その後に来るもの

  • event (`comment`, `reaction`)
  • performance
  • reload

特性

メッセージ形式

イベントメッセージ

data: {"type":"event","event":"comment","data":{...},"timestamp":1710806400000}
typestring
eventstring
dataobject
timestampnumber

ステータスメッセージ

data: {"type":"status","data":{"connected":true,"videoId":"xxx","viewerCount":0}}
data.connectedboolean
data.videoIdstring|null
data.viewerCountnumber

バージョンメッセージ

data: {"type":"version","data":"0.5.2"}
typestring
datastring

リロードメッセージ

data: {"type":"reload"}

演出メッセージ

data: {"type":"performance","sceneId":"game","data":{"effect":{"type":"sprout"},"context":{"userName":"@viewer","comment":"Hello"}},"timestamp":1710806400000}

イベント種別

comment

{
  "type": "event",
  "event": "comment",
  "data": {
    "id": "yt-ChwKGkNO...",
    "name": "@username",
    "comment": "Hello!",
    "commentHtml": "Hello! <img class=\"emoji\" src=\"...\" alt=\"stamp\">",
    "emojis": [
      { "src": "https://yt3.ggpht.com/...", "alt": "stamp", "emojiId": "UCxxx/xxxxx", "isCustom": true }
    ],
    "profileImage": "https://yt4.ggpht.com/...",
    "timestamp": "2026-03-19T00:00:00.000Z",
    "hasGift": false
  },
  "timestamp": 1710806400000
}
idstring
namestring
commentstring
commentHtmlstring
emojisarray
emojis[].srcstring
emojis[].altstring
emojis[].isCustomboolean
profileImagestring
timestampstring
hasGiftboolean
isMemberboolean
memberMonthsnumber
amountnumber
currencystring
stickerImagestring
isMembershipboolean
membershipHeaderstring
isMembershipGiftboolean
giftCountnumber

reaction

{
  "type": "event",
  "event": "reaction",
  "data": { "emoji": "heart", "count": 1 },
  "timestamp": 1710806400000
}
emojistring
countnumber

HTTP エンドポイント

GET /api/status

{ "connected": true, "videoId": "BimDylJsK_U", "viewerCount": 0 }

GET /api/events

GET /api/events
GET /api/events?type=comment&limit=50
limitnumber500
typestring
[
  {
    "type": "event",
    "event": "comment",
    "data": { "id": "...", "name": "...", "comment": "..." },
    "timestamp": 1710806400000
  }
]

GET /api/comments

GET /api/comments?limit=50
[
  {
    "id": "...",
    "name": "@user",
    "comment": "Hello!",
    "profileImage": "https://...",
    "timestamp": "2026-03-19T00:00:00.000Z",
    "hasGift": false
  }
]

POST /api/trigger/{sceneId}/{performanceId}

POST /api/trigger/game/perf_abc123
{ "success": true }

シーン別演出SSE

GET /effects/{sceneId}/stream

開発時の注意

オーバーレイ配信

GET /effects/{sceneId}/

クライアント実装例

配布用サンプル

JavaScript

var es = new EventSource('http://localhost:11280/api/stream');
es.onmessage = function(event) {
  var msg = JSON.parse(event.data);
  if (msg.type === 'version' || msg.type === 'reload') return;
  if (msg.type === 'status') {
    console.log('connected:', msg.data.connected);
    return;
  }
  if (msg.type === 'event') {
    switch (msg.event) {
      case 'comment':
        console.log(msg.data.name + ': ' + msg.data.comment);
        break;
      case 'reaction':
        console.log('Reaction:', msg.data.emoji, 'x' + msg.data.count);
        break;
    }
  }
};

Python

import requests, json

response = requests.get('http://localhost:11280/api/stream', stream=True)
for line in response.iter_lines():
    if line and line.startswith(b'data: '):
        data = json.loads(line[6:])
        print(data)

curl

# Real-time stream
curl http://localhost:11280/api/stream

# Check status
curl http://localhost:11280/api/status

# Latest 50 comments
curl "http://localhost:11280/api/events?type=comment&limit=50"

詳細仕様