コメントビューア用。
OAuthが要るようなAPIは使わず、未登録で取得できるコメントを取得。
あくまで執筆時点の情報です。仕様が変わる可能性もあるのであしからず。
前提として、ニコ生チャット取得はWebSocketの接続を2本行う必要があることに留意。
コミュニティIDを元に、配信ページを取得
-
https://live.nicovideo.jp/watch/co{コミュニティID}
- 例:
https://live.nicovideo.jp/watch/co4930985
- 例:
(2021/05/29にURLが変わったようです。live2
-> live
)
ページに埋め込まれた放送情報を取得する
(2023/05/13あたりでprogram.broadcastIdが無くなったようです。audienceTokenの先頭に同じIDが入ってるので適当に切り出してください)
const embeddedData = JSON.parse(document.getElementById("embedded-data").getAttribute("data-props"));
- 以下の場合は配信が終了してる
- embeddedData.program.status === 'ENDED'
- embeddedData.program.endTime < 現在時刻
const audienceToken = embeddedData.player.audienceToken;
const frontendId = embeddedData.site.frontendId;
const broadcastId = audienceToken.match(/^\d+/)[0];
スレッドIDを取得する
WebSocketで以下に接続
const url = `wss://a.live2.nicovideo.jp/unama/wsapi/v2/watch/${broadcastId}?audience_token=${audienceToken}&frontend_id=${frontendId}`
2021/01/21追記
WebSocket接続時、ちゃんとしたブラウザのUser-Agent
をヘッダに含めないと、CONNECT_ERRORが返ってくるようになりました。ChromeのUser-Agentあたりを適当に含めてあげてください。
メッセージのやり取りは以下の通り。簡単のためにJSONで表記しているが、実際は文字列化して送受信される。
{
"type": "startWatching",
"data": {
"stream": { "quality": "high", "protocol": "hls", "latency": "low", "chasePlay": false },
"room": { "protocol": "webSocket", "commentable": true },
"reconnect": false
},
}
{
"type": "getAkashic",
"data": { "chasePlay": false }
}
{
"type":"room",
"data":{
isFirst: boolean,
messageServer: {
type: string,
/** コメントサーバのWebSocketURL */
uri: string,
},
name: string,
/** スレッドID */
threadId: string,
waybackkey: string,
}
}
- ここで抜き出すべき要素は以下。
- data.messageServer.uri
- data.threadId
チャットサーバに接続してスレッドIDを送信
先程取得したコメントサーバのURLにWebSocket接続。
WebSocketのリクエストヘッダの指定が必要。
const ws = new WebSocket(wsUrl, 'niconama', {
headers: {
'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
'Sec-WebSocket-Protocol': 'msg.nicovideo.jp#json',
},
});
以下WebSocketでの送受信。
[
{
"ping": {
"content": "rs:0"
}
},
{
"ping": {
"content": "ps:0"
}
},
{
"thread": {
"thread": "★スレッドID★",
"version": "20061206",
"user_id": "guest",
"res_from": -150,
"with_global": 1,
"scores": 1,
"nicoru": 0
}
},
{
"ping": {
"content": "pf:0"
}
},
{
"ping": {
"content": "rf:0"
}
}
]
チャット情報の受信
コメントサーバのWebSocketにスレッドIDを送信したら、コメント情報が返ってくる。
開いた時点までのチャット情報がドカッと来る。
obj.ping.content: 'rf:0'のものを受信したらおしまい。
以降は下記のchatオブジェクトを含んだメッセージを受信し続ける。
{
chat: {
anonymity?: number;
/** チャットコメント */
content: string;
/** Dateを数値化したやつ */
date: number;
date_usec: number;
/** 匿名の時は184が入ってる */
mail?: string;
/** コメント番号 */
no: number;
/**
* 謎のフラグ
* - 1: プレミアム会員
* - 3: 配信者自身
*/
premium?: number;
score?: number;
thread: string;
user_id: string;
vpos: number;
};
}
また、定期的にWebSocketに対してpingを打つ必要がある。特にメッセージを含める必要はない。
これをしないと途中でメッセージが来なくなる。
JavaScriptなら、WebSocketインスタンスが持っているpingをsetInterval実行するだけでOK。
ws.ping();