ニコニコ動画 技術的詳細分析(更新版)

@Kongyokongyo / 更新: 2026/05/19 02:45
TEXT 29.6KB
0
  1. # ニコニコ動画 技術的詳細分析
  2. ---
  3. ## アーキテクチャ概要
  4. ニコニコ動画はモダンなマイクロサービスアーキテクチャを採用しており、以下のような技術スタックで構成されています:
  5. - **フロントエンド**: React/Remix ベースの SPA (`nvpc_next` = NicoNico Video Player Client Next)
  6. - 視聴ページ (`/watch/{id}`) は Remix ベースのコード分割バンドル
  7. - トップ系ページ (`/`, `/video_top`) は従来型のバンドル (`vendor.js` + `pages_index_*.js`)
  8. - **共通ヘッダー**: `common-header.nimg.jp/3.9.0/pc/CommonHeader.min.js` (バージョン 3.9.0)
  9. - **動画配信**: HLS (HTTP Live Streaming) + AWS CloudFront (CDN)
  10. - **API**: JSON ベースの RESTful API (フロントエンド ID `6` で識別)
  11. - **コメント**: 専用のコメントサーバー (`public.nvcomment.nicovideo.jp`)
  12. - **認証**: セッションベースの認証 + JWT トークン (`x-access-right-key`, `threadKey`)
  13. - **ヘッダー入札**: Prebid.js による多数の SSP/エクスチェンジ統合
  14. ---
  15. ## フロントエンド技術スタック
  16. ### JavaScriptバンドル構造
  17. ニコニコ動画はページの性質に応じて 2 種類のバンドルを使い分けています:
  18. ```
  19. https://resource.video.nimg.jp/web/scripts/
  20. ├── nvpc_next/assets/ # 視聴ページ用 Remix バンドル (Vite hash付き)
  21. │ ├── manifest-*.js # マニフェスト
  22. │ ├── entry.client-*.js # クライアントエントリーポイント
  23. │ ├── root-*.js # ルートコンポーネント
  24. │ ├── index-*.js # 共通コンポーネント (複数)
  25. │ ├── api-client-*.js # API クライアント
  26. │ ├── use-media-query-*.js # メディアクエリフック
  27. │ ├── useDeferredLoadable-*.js # 遅延ロードフック
  28. │ ├── useLayoutType-*.js # レイアウト判定フック
  29. │ ├── usePreviewVideoStatus-*.js # プレビュー再生フック
  30. │ ├── ab-testing-*.js # A/B テスト
  31. │ ├── enum-*.js # 列挙型定数
  32. │ ├── _web-*.js # 視聴ページ共通ルート
  33. │ ├── _web.watch._id._-*.js # 動画視聴ページ
  34. │ ├── _web.random_play._itemId._-*.js # ランダム再生ページ
  35. │ └── _web.easy_nicos._id._-*.js # 簡単ニコ動ページ
  36. └── bundle/
  37. ├── vendor.js # サードパーティライブラリ
  38. ├── pages_index_TopPage.js # サービス統合トップ (`/`)
  39. └── pages_index_VideoTop.js # 動画トップ (`/video_top`)
  40. ```
  41. ### 主要なフロントエンド機能 (視聴ページ)
  42. | コンポーネント | 説明 |
  43. |--------------|------|
  44. | `PlayerVolumeBar` | プレイヤーボリュームコントロール |
  45. | `PlayerSeekBar` | プレイヤーシークバー |
  46. | `VideoCard` / `NicoadVideoCard` | 動画カード表示 (通常版 / ニコニ広告版) |
  47. | `VideoMediaObject` | 動画メディアオブジェクト (スケルトン付き) |
  48. | `FollowButton` | ユーザーフォローボタン |
  49. | `Toast` | 通知表示 |
  50. | `WakutkoolNotice` | わくくおる通知 (ポータル横断告知) |
  51. | `TagRelatedBanner` | タグ関連バナー |
  52. | `SearchRelatedTag` | 関連タグ検索 |
  53. | `WatchLayoutLazySidebar` / `WatchLayoutLazyBottom` | 視聴ページの遅延ロード領域 |
  54. | `FloatingBottomRightPresenter` | 右下フローティング UI |
  55. | `GiftAuditionPresenter` | 動画ギフト + オーディションプレゼンター |
  56. | `AfkStopMessagePresenter` | 放置検知後の停止メッセージ |
  57. | `MutedVideoThumbnail` | ミュート扱い動画のサムネイル |
  58. | `VideoShareTimeInput` | 時刻指定シェアの入力 |
  59. | `PremiumRegisterRequired` | プレミアム登録誘導モーダル |
  60. | `CollapsiblePanel` / `Skeleton` / `Tabs` | 汎用 UI プリミティブ |
  61. | `nicoad` | ニコニ広告機能 |
  62. ### メタデータ・OGP
  63. 視聴ページ (`/watch/{id}`) は動画用 OGP に最適化されており、Open Graph Video / Twitter App Card / App Links が含まれます:
  64. ```html
  65. <meta property="og:title" content="新・豪血寺一族 -煩悩解放 - レッツゴー!陰陽師">
  66. <meta property="og:type" content="video.other">
  67. <meta property="og:site_name" content="ニコニコ動画">
  68. <meta property="og:locale" content="ja_JP">
  69. <meta property="og:video" content="https://embed.nicovideo.jp/watch/{id}?autoplay=1">
  70. <meta property="og:video:type" content="video/mp4">
  71. <meta property="og:video:width" content="640">
  72. <meta property="og:video:height" content="360">
  73. <meta property="video:duration" content="320">
  74. <meta property="video:release_date" content="2007-03-06T00:33+0900">
  75. <meta property="fb:app_id" content="378853695459932">
  76. <meta name="twitter:card" content="summary_large_image">
  77. <meta name="twitter:site" content="@nico_nico_info">
  78. <meta name="twitter:app:id:iphone" content="307764057">
  79. <meta name="twitter:app:url:iphone" content="nico://play/?vid={id}">
  80. <meta name="twitter:app:id:googleplay" content="jp.nicovideo.android">
  81. <meta name="twitter:app:url:googleplay" content="nico://watch/{id}">
  82. <meta property="al:ios:url" content="nico://play/?vid={id}&utm_source=facebook&...">
  83. <meta property="al:android:url" content="https://www.nicovideo.jp/watch/{id}?...">
  84. <meta property="al:web:url" content="https://www.nicovideo.jp/watch/{id}">
  85. ```
  86. トップページ (`/`) は `og:type="website"`、動画トップ (`/video_top`) は `og:type="article"` という具合にページ種別ごとに切り替わります。
  87. ---
  88. ## 主要APIエンドポイント
  89. ### 1. 動画アクセス権限 API (HLS)
  90. **エンドポイント**: `POST https://nvapi.nicovideo.jp/v1/watch/{videoId}/access-rights/hls?actionTrackId={actionTrackId}`
  91. 動画のストリーミング URL を取得するためのアクセス権限を要求します。`actionTrackId` クエリパラメータでセッションを識別し、再リクエスト時には `&__retry=N` が付与されます。
  92. #### リクエストヘッダー
  93. ```http
  94. x-access-right-key: {JWTトークン}
  95. x-frontend-id: 6
  96. x-frontend-version: 0
  97. x-request-with: nicovideo
  98. x-niconico-language: ja-jp
  99. Content-Type: application/json
  100. Accept: application/json;charset=utf-8
  101. ```
  102. #### リクエストボディ (初回, `?actionTrackId=...` のみ)
  103. `outputs` のみ。動画の元素材が許可する全 video×audio 組み合わせを列挙します:
  104. sm9 (古い動画) の場合:
  105. ```json
  106. {
  107. "outputs": [
  108. ["video-h264-360p", "audio-aac-128kbps"],
  109. ["video-h264-360p", "audio-aac-64kbps"],
  110. ["video-h264-360p-lowest", "audio-aac-128kbps"],
  111. ["video-h264-360p-lowest", "audio-aac-64kbps"]
  112. ]
  113. }
  114. ```
  115. sm46309015 (新しい動画) の場合:
  116. ```json
  117. {
  118. "outputs": [
  119. ["video-h264-720p", "audio-aac-192kbps"],
  120. ["video-h264-720p", "audio-aac-64kbps"],
  121. ["video-h264-480p", "audio-aac-192kbps"],
  122. ["video-h264-480p", "audio-aac-64kbps"],
  123. ["video-h264-360p", "audio-aac-192kbps"],
  124. ["video-h264-360p", "audio-aac-64kbps"],
  125. ["video-h264-144p", "audio-aac-192kbps"],
  126. ["video-h264-144p", "audio-aac-64kbps"]
  127. ]
  128. }
  129. ```
  130. #### リクエストボディ (heartbeat 付きの後続呼び出し, `?actionTrackId=...&__retry=N`)
  131. 再生開始時や状態変化時に、`outputs` に加えて `heartbeat` フィールドで視聴セッションの状態を送信します:
  132. ```json
  133. {
  134. "outputs": [["video-h264-360p", "audio-aac-128kbps"]],
  135. "heartbeat": {
  136. "method": "guest",
  137. "params": {
  138. "eventType": "start",
  139. "eventOccurredAt": "2026-05-19T02:27:29+09:00",
  140. "watchMilliseconds": 0,
  141. "endCount": 0,
  142. "additionalParameters": {
  143. "___pc_v": 1,
  144. "os": "Windows",
  145. "os_version": "15.0.0",
  146. "nicosid": "{nicosid}",
  147. "is_ad_block": false,
  148. "is_ad_block_by_as": false,
  149. "has_playlist": false,
  150. "playback_rate": "1",
  151. "loop_count": 0,
  152. "suspend_count": 0,
  153. "load_failed": false,
  154. "preview_play": false,
  155. "hot_scene_wave": true,
  156. "seekbar_seek_count": 0,
  157. "performance": {
  158. "watch_access_start": 1779125249692,
  159. "video_loading_start": 1779125249698,
  160. "end_context": {
  161. "ad_playing": false,
  162. "video_playing": false,
  163. "is_suspending": false
  164. }
  165. },
  166. "__pc_is_ai_comment_visible": true
  167. }
  168. }
  169. }
  170. }
  171. ```
  172. #### レスポンス
  173. ```json
  174. {
  175. "meta": { "status": 201 },
  176. "data": {
  177. "contentUrl": "https://delivery.domand.nicovideo.jp/hlsbid/{bid}/playlists/variants/{variantId}.m3u8?session=...&Policy=...&Signature=...&Key-Pair-Id=...",
  178. "createTime": "2026-05-19T02:27:29+09:00",
  179. "expireTime": "2026-05-20T02:27:29+09:00"
  180. }
  181. }
  182. ```
  183. 初回 POST は `201 Created` を返し、heartbeat 付きの後続 POST は `200 OK` を返します。レスポンスに加えて `Set-Cookie: domand_bid=...` (Max-Age=86400, HttpOnly, Secure) が払い出されます。
  184. ### 2. コメントサーバー API
  185. **エンドポイント**: `POST https://public.nvcomment.nicovideo.jp/v1/threads?pc=1`
  186. 動画に紐づくコメントスレッドを取得します。`x-client-os-type: others` ヘッダーと `Content-Type: text/plain;charset=UTF-8` で送信されます。
  187. #### リクエストボディ
  188. ```json
  189. {
  190. "params": {
  191. "targets": [
  192. { "id": "1173108780", "fork": "owner" },
  193. { "id": "1173108780", "fork": "main" },
  194. { "id": "1173108780", "fork": "easy" }
  195. ],
  196. "language": "ja-jp"
  197. },
  198. "threadKey": "{JWTトークン}",
  199. "additionals": {}
  200. }
  201. ```
  202. #### レスポンス構造
  203. ```json
  204. {
  205. "meta": { "status": 200 },
  206. "data": {
  207. "globalComments": [{ "id": "1173108780", "count": 5659900 }],
  208. "threads": [
  209. {
  210. "id": "1173108780",
  211. "fork": "main",
  212. "commentCount": 5581324,
  213. "comments": [
  214. {
  215. "id": "882123066398695732",
  216. "no": 4118020,
  217. "vposMs": 361140,
  218. "body": "コメント本文",
  219. "commands": ["184"],
  220. "userId": "Yg_6QWiiS_T2mq3WJuzUcp41MvQ",
  221. "isPremium": true,
  222. "score": -2200,
  223. "postedAt": "2013-02-17T21:16:30+09:00",
  224. "nicoruCount": 137,
  225. "nicoruId": null,
  226. "source": "leaf",
  227. "isMyPost": false
  228. }
  229. ]
  230. }
  231. ]
  232. }
  233. }
  234. ```
  235. 旧仕様から増えたフィールド: `nicoruId` (押下したニコるの識別子)、`isMyPost` (自分の投稿か)、`source` は `"leaf"` 以外に `"nicoru"` (ニコる経由で表示されたコメント) を取り得ます。
  236. ### 3. レコメンデーション API
  237. **エンドポイント**: `GET https://nvapi.nicovideo.jp/v1/recommend`
  238. ページ種別ごとに `recipeId` を切り替えて呼び出します:
  239. | ページ | recipeId |
  240. |------|----------|
  241. | 視聴ページ | `video_watch_recommendation` (`recipeVersion=2`) |
  242. | 動画トップ (`/video_top`) | `video_top_recommend` (`with_reason=true`) |
  243. ```
  244. ?recipeId=video_watch_recommendation
  245. &recipeVersion=2
  246. &videoId=sm9
  247. &site=nicovideo
  248. &limit=25
  249. &sensitiveContents=mask
  250. ```
  251. レスポンス `data.items[].content` には、`owner.visibility` (`visible`/`hidden`)、`requireSensitiveMasking`、`isMuted`、難読化フィールド (`9d091f87`, `acf68865` のような短いキー) が含まれます。
  252. ### 4. ニコニ広告 API
  253. 旧来の v1 系と、視聴ページで新規導入された v2 系が併存しています:
  254. | エンドポイント | 用途 |
  255. |--------------|------|
  256. | `GET https://api.nicoad.nicovideo.jp/v1/contents/video/decoration?ids={csv}` | 動画一覧 (`/video_top` 等) のニコニ広告装飾を一括取得 |
  257. | `GET https://api.nicoad.nicovideo.jp/v2/contents/video/{id}/pickup_supporters?tags=...` | 視聴ページのピックアップサポーター取得 (v2) |
  258. | `GET https://api.nicoad.nicovideo.jp/v1/nage_video/{id}/gift/effects` | 動画ギフト (投げ銭) の利用可能エフェクト一覧 |
  259. | `GET https://api.nicoad.nicovideo.jp/v1/contents/nage_video/{id}/totalGiftPoint` | 動画ギフトの累計ポイント |
  260. ### 5. その他のAPI
  261. | API | エンドポイント | 用途 |
  262. |-----|---------------|------|
  263. | 広場ウィジェット | `GET eapi.beta.hiroba.nicovideo.jp/v1/square-widget?tags=...` | タグから関連コミュニティ広場を提案 |
  264. | ユーザーフォロー | `user-follow-api.nicovideo.jp/v1/user/followees/` | フォロー情報 |
  265. | 動画マイキー実績 | `GET mjk.nicovideo.jp/api/v1/content_types/video/contents/{id}/achieved_histories?limit=1&order=honor_class` | 動画の実績バッジ履歴 |
  266. | ユーザーマイキー実績 | `GET mjk.nicovideo.jp/api/v1/users/{userId}/achieved_histories?limit=1` | ユーザーの実績バッジ履歴 |
  267. | ストーリーボード | `nvapi.nicovideo.jp/v1/watch/{id}/access-rights/storyboard` | サムネイルシート |
  268. | マーキー | `GET nvapi.nicovideo.jp/v1/marquee` | プレイヤー上部のマーキー告知 |
  269. | AI キャラクターコメント | `GET nvapi.nicovideo.jp/v1/ai-comment/characters` | AI コメントの登場キャラクター一覧 (2026 年導入機能) |
  270. | クリエイターサポート | `GET nvapi.nicovideo.jp/v1/users/{userId}/creator-support` | 投稿者へのサポート (投げ銭/応援) 情報 |
  271. | オーディション応募 | `GET audition.nicovideo.jp/capi/v1/entry_items?item_type=video&item_id={id}&voting_phase=active&limit=1` | 動画が応募中のオーディション情報 |
  272. | ニコニ・コモンズ ライセンス | `GET public-api.commons.nicovideo.jp/v1/works/{id}/license` | コモンズ License (404 になることあり) |
  273. | わくくおる | `GET wktk.nicovideo.jp/v2/wakutkool/frames.json?names=watch-portal-link&tags=...&responseType=pc` | 横断告知 (v2 API) |
  274. | プリロール広告 | `GET ads.nicovideo.jp/api/video/getAd.json.php?...` | 動画再生前の広告枠 (linearType=preroll) |
  275. | ステラ (非会員視聴) | `POST stella.nicovideo.jp/v1/watch/nonmember.json` | 動画トップ等での非ログイン視聴セッション初期化 |
  276. ---
  277. ## 動画配信システム
  278. ### Domand (動画配信プラットフォーム)
  279. ニコニコ動画は **Domand** と呼ばれる社内動画配信プラットフォームを使用しています:
  280. - **配信ドメイン**: `delivery.domand.nicovideo.jp` (プレイリスト, 暗号鍵)
  281. - **アセットドメイン**: `asset.domand.nicovideo.jp` (CMAF セグメント, ストーリーボード)
  282. - **CDN**: AWS CloudFront (`Key-Pair-Id=K11RB80NFXU134`)
  283. - **ブラウザID クッキー**: `domand_bid` (アクセス権限 API 初回 POST 時に発行)
  284. ### 配信品質 (動画別に提供される)
  285. `x-access-right-key` JWT の `v` / `a` フィールドにライセンスされた品質が列挙され、初回 POST の `outputs` で video×audio の組み合わせを全部列挙して送ります。**品質ラベルと実解像度・コーデックは動画の元素材で異なる** ため、ラベルだけでは解像度を一意に決められません。実観測例:
  286. **古い動画 (sm9, 2007 年投稿) の場合**:
  287. | ラベル | 実解像度 | フレームレート | コーデック |
  288. |-------|---------|----------------|------------|
  289. | `video-h264-360p` | 320x240 | 29.970 | `avc1.4d401e` (H.264 Main L3.0) |
  290. | `video-h264-360p-lowest` | 480x360 | 29.970 | `avc1.42c01e` (H.264 Constrained Baseline L3.0) |
  291. | `audio-aac-128kbps` | - | - | `mp4a.40.2` (AAC-LC) |
  292. | `audio-aac-64kbps` | - | - | `mp4a.40.2` (AAC-LC) |
  293. (古い動画では品質ラベル名と実解像度が一致しないことに注意。`360p-lowest` の方が解像度が高い変則ケースが存在する。)
  294. **新しい動画 (sm46309015, 2026 年投稿) の場合**:
  295. | ラベル | 実解像度 | フレームレート | コーデック |
  296. |-------|---------|----------------|------------|
  297. | `video-h264-720p` | 1280x720 | 23.976 | `avc1.4d4020` (H.264 Main L3.2) |
  298. | `video-h264-480p` | 854x480 | 23.976 | `avc1.4d4020` (H.264 Main L3.2) |
  299. | `video-h264-360p` | 640x360 | 23.976 | `avc1.4d401e` (H.264 Main L3.0) |
  300. | `video-h264-144p` | 256x144 | 23.976 | `avc1.4d401e` (H.264 Main L3.0) |
  301. | `audio-aac-192kbps` | - | - | `mp4a.40.2` (AAC-LC) |
  302. | `audio-aac-64kbps` | - | - | `mp4a.40.2` (AAC-LC) |
  303. より高品質な動画では `video-h264-1080p` / `1440p` / `2160p` などのラベルも追加されます。
  304. ### HLS マスタープレイリスト構造
  305. ```
  306. #EXTM3U
  307. #EXT-X-VERSION:6
  308. #EXT-X-INDEPENDENT-SEGMENTS
  309. #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aac-192kbps",NAME="Main Audio",DEFAULT=YES,URI="...audio-aac-192kbps.m3u8?..."
  310. #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aac-64kbps",NAME="Main Audio",DEFAULT=YES,URI="...audio-aac-64kbps.m3u8?..."
  311. #EXT-X-STREAM-INF:BANDWIDTH=3101972,AVERAGE-BANDWIDTH=2261618,CODECS="avc1.4d4020,mp4a.40.2",RESOLUTION=1280x720,FRAME-RATE=23.976,AUDIO="audio-aac-192kbps"
  312. ...video-h264-720p.m3u8?...
  313. #EXT-X-STREAM-INF:BANDWIDTH=2905339,AVERAGE-BANDWIDTH=2078234,CODECS="avc1.4d4020,mp4a.40.2",RESOLUTION=1280x720,FRAME-RATE=23.976,AUDIO="audio-aac-64kbps"
  314. ...video-h264-720p.m3u8?...
  315. #EXT-X-STREAM-INF:BANDWIDTH=2580733,AVERAGE-BANDWIDTH=1863833,CODECS="avc1.4d4020,mp4a.40.2",RESOLUTION=854x480,FRAME-RATE=23.976,AUDIO="audio-aac-192kbps"
  316. ...video-h264-480p.m3u8?...
  317. #EXT-X-STREAM-INF:BANDWIDTH=1100355,AVERAGE-BANDWIDTH=856250,CODECS="avc1.4d401e,mp4a.40.2",RESOLUTION=640x360,FRAME-RATE=23.976,AUDIO="audio-aac-192kbps"
  318. ...video-h264-360p.m3u8?...
  319. #EXT-X-STREAM-INF:BANDWIDTH=475614,AVERAGE-BANDWIDTH=405103,CODECS="avc1.4d401e,mp4a.40.2",RESOLUTION=256x144,FRAME-RATE=23.976,AUDIO="audio-aac-192kbps"
  320. ...video-h264-144p.m3u8?...
  321. (以下、各 video variant の 64kbps 音声バージョン)
  322. ```
  323. ポイント:
  324. - **HLS v6**, `#EXT-X-INDEPENDENT-SEGMENTS` 指定。
  325. - 音声トラックは `#EXT-X-MEDIA` (TYPE=AUDIO) として別 m3u8 に分離 (旧 `128kbps` / `64kbps` の他、新しい動画では `192kbps` / `64kbps` 等)。
  326. - 動画 variant ごとに `#EXT-X-STREAM-INF` で別 m3u8 を参照し、`AUDIO=` で音声グループを指定する **多重化なし** の構成。video × audio の全組み合わせが variant として列挙される。
  327. - フレームレートは元素材依存 (sm9 では 29.970fps, sm46309015 では 23.976fps)。
  328. ### URLディレクトリ構造
  329. ```
  330. https://delivery.domand.nicovideo.jp/hlsbid/{bid}/
  331. ├── playlists/
  332. │ ├── variants/{variantId}.m3u8 # マスタープレイリスト
  333. │ └── media/
  334. │ ├── video-h264-360p.m3u8
  335. │ ├── video-h264-360p-lowest.m3u8
  336. │ ├── audio-aac-128kbps.m3u8
  337. │ └── audio-aac-64kbps.m3u8
  338. └── keys/
  339. ├── video-h264-360p.key
  340. ├── video-h264-360p-lowest.key
  341. ├── audio-aac-128kbps.key
  342. └── audio-aac-64kbps.key
  343. https://asset.domand.nicovideo.jp/{bid}/
  344. ├── video/{track_number}/{quality}/
  345. │ ├── init01.cmfv # CMAF 初期化セグメント
  346. │ ├── 01.cmfv # CMAF メディアセグメント
  347. │ ├── 02.cmfv
  348. │ └── ...
  349. └── audio/{track_number}/{quality}/
  350. ├── init01.cmfa
  351. ├── 01.cmfa
  352. └── ...
  353. ```
  354. `{track_number}` は同一品質内のトラック番号 (動画は通常 `1` または `12` のようにオフセットあり)。
  355. ### 暗号化
  356. HLS セグメントは **AES-128** で暗号化され、鍵 URL は variant の m3u8 から `#EXT-X-KEY` で参照されます。
  357. ### URL署名 (CloudFront)
  358. すべての URL に AWS CloudFront の署名が含まれます。マスタープレイリストは Custom Policy (Policy + Signature)、media playlist と key は Canned Policy (Expires + Signature) を使い分けています:
  359. ```
  360. # variants (Custom Policy: 当該リソースに長期間有効)
  361. ?session={session_id}&Policy={base64_policy}&Signature={signature}&Key-Pair-Id=K11RB80NFXU134
  362. # media playlists / keys / segments (Canned Policy)
  363. ?session={session_id}&Expires={epoch}&Signature={signature}&Key-Pair-Id=K11RB80NFXU134
  364. ```
  365. ---
  366. ## コメントシステム
  367. ### スレッド構造
  368. ニコニコのコメントは「スレッド」と「フォーク」で構成されています:
  369. | フォーク | 説明 |
  370. |---------|------|
  371. | `owner` | 投稿者コメント |
  372. | `main` | メインコメント |
  373. | `easy` | 簡易コメント(HTML5プレイヤー用) |
  374. ### コメントコマンド
  375. コメントには「コマンド」を適用できます:
  376. - `184` - 匿名希望(ユーザー ID をハッシュ化して投稿)
  377. - `ue` / `naka` / `shita` - 表示位置 (上寄せ / 中央 / 下寄せ)
  378. - `big` / `medium` / `small` - 文字サイズ
  379. - `ender` - 描画スタイル変更 (アンチエイリアス無効化系)
  380. - `gothic` / `mincho` / `defont` - フォント
  381. - `full` - 画面いっぱい (横スクロール無効化)
  382. - `#RRGGBB` または色名 (`red`, `blue` 等) - 色指定
  383. ### threadKey JWT
  384. `threadKey` は JWT (`HS512`) で構成されています。ヘッダーは `{"typ": "JWT", "alg": "HS512"}`。実観測したペイロード (未ログイン時):
  385. ```json
  386. {
  387. "jti": "6a0b4c010f6af",
  388. "exp": 1779125729.06307,
  389. "typ": "Thread-Key",
  390. "d": 320,
  391. "tids": ["1173108780"],
  392. "f184s": []
  393. }
  394. ```
  395. | フィールド | 説明 |
  396. |----------|------|
  397. | `jti` | JWT ID |
  398. | `exp` | 有効期限 (浮動小数 Unix エポック秒) |
  399. | `typ` | トークン種別 (`Thread-Key`) |
  400. | `d` | 動画長 (秒) |
  401. | `tids` | 対象スレッドの ID 配列 |
  402. | `f184s` | 強制 184 (匿名) 対象スレッド ID 配列 |
  403. ログイン時には `uid` フィールド (ユーザー識別子) も追加されるが、未ログインのゲスト視聴では含まれない。
  404. ---
  405. ## 認証・セッション管理
  406. ### セッションクッキー
  407. 主な認証・配信用クッキー:
  408. | クッキー名 | ドメイン | 説明 |
  409. |------------|----------|------|
  410. | `nicosid` | `.nicovideo.jp` | セッションID |
  411. | `user_session` | `.nicovideo.jp` | ユーザーセッション (ログイン時) |
  412. | `domand_bid` | `.nicovideo.jp` | Domand ブラウザ ID (アクセス権限 API 初回呼び出し時に発行, HttpOnly, Secure) |
  413. ### 広告・トラッキング系クッキー
  414. ヘッダー入札や行動計測のために多数の 3rd party クッキーが書き込まれます (主要なもの):
  415. | クッキー名 | 提供元 |
  416. |------------|--------|
  417. | `_ga`, `_ga_*` | Google Analytics 4 (複数測定ID) |
  418. | `_gcl_au`, `__gads`, `__gpi`, `__eoi` | Google Ads / Ad Manager |
  419. | `_yjsu_yjad`, `_ly_su` | LINEヤフー |
  420. | `_tt_enable_cookie`, `_ttp`, `ttcsid*` | TikTok Pixel |
  421. | `_twpid` | Twitter (X) Pixel |
  422. | `_clck` | Microsoft Clarity |
  423. | `pbjs_sharedId` | Prebid.js Shared ID |
  424. | `_pubcid` | PubCommon ID |
  425. | `panoramaId` | LiveRamp Panorama |
  426. | `cto_bidid`, `cto_bundle` | Criteo |
  427. | `mgniSession` | Magnite (Rubicon) |
  428. | `_cc_id` | Lotame |
  429. ### LocalStorage
  430. ```javascript
  431. // コメント設定 (NG ユーザー等)
  432. localStorage['@nvweb-packages/comments:userng:v2']
  433. // 動画レンダラー設定 (ラウドネス情報を含む)
  434. localStorage['@nvweb-packages/video-renderer']
  435. // 視聴ページの UI 状態 (コメントリスト展開状態など)
  436. localStorage['nvpc:watch']
  437. // 視聴セッションのタブ間共有
  438. localStorage['nvpc:watch:tab-sessions']
  439. // イベント計測テスト
  440. localStorage['@nvweb-packages/watch-events:TEST_KEY']
  441. // 共通ヘッダーの掲出順制御
  442. localStorage['common-header-wktk-premium-lead-frames']
  443. localStorage['common-header-header-top-priority-period']
  444. // Magnite/Rubicon セッション
  445. localStorage['mgniSession']
  446. ```
  447. ### x-access-right-key JWT
  448. 動画配信APIで使用される JWT (`HS512`) ペイロード。実体に基づく正確なフィールド名:
  449. ```json
  450. {
  451. "jti": "6a0b4c0112fdc",
  452. "exp": 1779125849.0374729633331298828125,
  453. "typ": "Access-Right-Key",
  454. "vid": "sm9",
  455. "rid": "nicovideo-sm9",
  456. "fid": 6,
  457. "uid": "6-e3XFe1aMwH_1779125249007",
  458. "d": 320,
  459. "v": ["video-h264-360p", "video-h264-360p-lowest"],
  460. "a": ["audio-aac-128kbps", "audio-aac-64kbps"],
  461. "s": false,
  462. "sh": false
  463. }
  464. ```
  465. | フィールド | 説明 |
  466. |----------|------|
  467. | `jti` | JWT ID |
  468. | `exp` | 有効期限 (浮動小数 Unix エポック秒) |
  469. | `typ` | トークン種別 (`Access-Right-Key`) |
  470. | `vid` | 動画 ID |
  471. | `rid` | リソース ID (`nicovideo-{vid}` 形式) |
  472. | `fid` | フロントエンド ID (PC Web は `6`) |
  473. | `uid` | ユーザー識別子 (`{fid}-{actionTrackId}` 形式、未ログインでもセッション値) |
  474. | `d` | 動画長 (秒) |
  475. | `v` | 許可された動画品質ラベル配列 |
  476. | `a` | 許可された音声品質ラベル配列 |
  477. | `s` | (用途不明、観測値は `false`) |
  478. | `sh` | (用途不明、観測値は `false`) |
  479. ---
  480. ## 動画ギフト(投げ銭)システム
  481. `api.nicoad.nicovideo.jp/v1/nage_video/{id}/gift/effects` で取得可能。エフェクトアセットは `ir.cdn.nimg.jp/res/nage/common_effect/{effect_name}/asset_{effect_name}.json` で配信されます。主なエフェクト:
  482. `videogift_nicoru`, `videogift_kansha`, `videogift_8888`, `videogift_kami`, `videogift_kusa`, `videogift_upotsu`, `videogift_beer`, `videogift_mochi`, `videogift_makaron1`, `videogift_makaron2`, `videogift_ajisai_momo`, `videogift_xmaspresent`, `videogift_snow1`, `videogift_nengajyo2026`, `videogift_halloween_pumpkin4`, `videogift_matsuri`, `videogift_sticker`, `videogift_banner`, `videogift_bouquet`, `videogift_hoshiimono`, `videogift_premium_logo`, `videogift_premium_logo2`, `videogift_15kinen_densetsu`, `videogift_15kinen_card`, `videogift_fukidashi`, `videogift_saikou`, `videogift_kotonoha_gacha_daijoubu`, `videogift_yukari_omedetou`, `viddeogift_akari_a_moyashishamo` (typo そのまま), `videogift_nyanko_boss`, `videogift_nyanko_maneki`, `videogift_shunen_17_omedeto`.
  483. ---
  484. ## 開発に役立つ情報
  485. ### フロントエンド識別子
  486. | ヘッダー | 値 | 説明 |
  487. |---------|-----|------|
  488. | `x-frontend-id` | `6` | フロントエンドID (PC Web) |
  489. | `x-frontend-version` | `0` | フロントエンドバージョン |
  490. | `x-request-with` | `nicovideo` | リクエスト元識別 |
  491. | `x-niconico-language` | `ja-jp` | 言語 |
  492. | `x-client-os-type` | `others` | OS 種別 (コメントAPI で使用) |
  493. ### アクセス権限取得フロー
  494. 1. ページロード時に埋め込みデータから初期情報を取得 (Remix の `__remixContext`)。
  495. 2. `x-access-right-key` ヘッダー付きでアクセス権限 API を呼ぶ。最初は `?actionTrackId={id}` のみで `outputs` を全候補列挙し `201` を受領、`contentUrl` (実体URL) を取得。
  496. 3. レスポンスの `contentUrl` から HLS マスタープレイリスト (`variants/*.m3u8`) を取得。
  497. 4. プレイヤーが品質ごとの media playlist と AES-128 鍵を取得し、CMAF セグメントを順次ダウンロード。
  498. 5. 再生中は同じエンドポイントを `&__retry=0` 付きで再 POST し、`heartbeat` パラメータで状態 (再生時間, パフォーマンス計測, AI コメント可視性等) を送信。レスポンスは `200`。
  499. ### ストーリーボード (サムネイルシート)
  500. ```
  501. https://asset.domand.nicovideo.jp/{storyboard_bid}/storyboard/{track}/storyboard/
  502. ├── storyboard.json # メタデータ
  503. ├── 0001.jpg # サムネイル画像
  504. ├── 0002.jpg
  505. └── ...
  506. ```
  507. ### 広告配信スタック
  508. ニコニコ動画は多数の SSP/エクスチェンジを **Prebid.js** で同時に叩くヘッダー入札構成です:
  509. - **自社広告**: `ads.nicovideo.jp` (バナー), `ads.nicovideo.jp/api/video/getAd.json.php` (プリロール動画)
  510. - **Google**: Google Ad Manager / AdSense (`pagead2.googlesyndication.com`, `googleads.g.doubleclick.net`)
  511. - **Amazon**: TAM/UAM (`web-banner.ads.aps.amazon-adsystem.com`)
  512. - **Rubicon (Magnite)**: `fastlane.rubiconproject.com`, `prebid-server.rubiconproject.com`
  513. - **Index Exchange**: `htlb.casalemedia.com`
  514. - **OpenX**: `rtb.openx.net`
  515. - **PubMatic**: `hbopenbid.pubmatic.com`
  516. - **AppNexus (Xandr)**: `ib.adnxs.com`
  517. - **Media.net**: `prebid.media.net`
  518. - **Criteo**: `cto_*` クッキー経由
  519. - **MicroAd**: `s-rtb-pb.send.microad.jp`
  520. - **AdMatrix (AMoAd)**: `ad.as.amanad.adtdp.com`
  521. - **Fluct**: `hb.adingo.jp`
  522. - **United (ad-stir)**: `ad.ad-stir.com`
  523. - **CCI sociaDM**: `d.socdm.com`
  524. - **LINE Ads Platform**: `pb.ladsp.com`
  525. - **Yahoo!/LINE Impact**: `y.one.impact-ad.jp`
  526. - **ID プロバイダ**: LiveRamp (`api.rlcdn.com`), PubCommon, Prebid Shared ID
  527. ### 計測スタック
  528. - Google Analytics 4 (`G-FS29H4ZGX2`, `G-5LM4HED1NJ` 等)
  529. - Google Tag Manager (`GTM-PN8LFCT`, `GTM-KXT7G5G`)
  530. - 多数の Google Ads コンバージョン ID (`AW-11471143586`, `AW-11060698458`, `AW-469855517`, `AW-471708133`, `AW-691017027`, `AW-561674311`, `AW-607644388`, `AW-17911115346`, `AW-663701876`)
  531. - Yahoo! コンバージョン (`apm.yahoo.co.jp`)
  532. - TikTok Pixel (`analytics.tiktok.com`)
  533. - Twitter (X) Pixel (`static.ads-twitter.com`)
  534. - LINEヤフー LytagAd (`tag.flvcdn.net`)
  535. - Microsoft Clarity (`_clck`)
  536. ---
  537. *調査日: 2026年5月19日*
  538. *調査対象: https://www.nicovideo.jp/, https://www.nicovideo.jp/video_top, https://www.nicovideo.jp/watch/sm9*