Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
YouTubeのチャット欄の配置変更 / Changing the layout of the...
Search
Atom
June 28, 2026
Programming
2
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
YouTubeのチャット欄の配置変更 / Changing the layout of the YouTube chat field
chrome拡張機能:
https://github.com/yAtomtom/youtube-chat-rearranger
Atom
June 28, 2026
More Decks by Atom
See All by Atom
文献紹介 / Structure-based Knowledge Tracing: An Influence Propagation View
roraidolaurent
0
120
文献紹介 / Knowledge Tracing with GNN
roraidolaurent
0
110
文献紹介 / Non-Intrusive Parametric Reduced Order Models withHigh-Dimensional Inputs via Gradient-Free Active Subspace
roraidolaurent
0
69
ニューラルネットワークのベイズ推論 / Bayesian inference of neural networks
roraidolaurent
2
2.9k
Graph Convolutional Networks
roraidolaurent
0
260
文献紹介 / A Probabilistic Annotation Model for Crowdsourcing Coreference
roraidolaurent
0
95
文献紹介Deep Temporal-Recurrent-Replicated-Softmax for Topical Trends over Time
roraidolaurent
0
140
文献紹介/ Bayesian Learning for Neural Dependency Parsing
roraidolaurent
0
140
Scalable Bayesian Learning of Recurrent Neural Networks for Language Modeling
roraidolaurent
1
180
Other Decks in Programming
See All in Programming
The ROI of Quarkus for Spring Boot Applications
hollycummins
0
140
The NotImplementedError Problem in Ruby
koic
1
940
さぁV100、メモリをお食べ・・・
nilpe
0
150
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
260
肥大化するレガシーコードに立ち向かうためのインターフェース分離と依存の逆転 / JJUG CCC 2026 Spring
hirokunimaeta
0
620
「なぜそう決めたのか」を残し続ける仕組み ― Notion AI カスタムエージェント × Slack連携による設計判断の自動記録 - NIKKEI Tech Talk #47
niftycorp
PRO
0
230
その問い、本当に正しいですか?AI時代のエンジニアに必要な哲学と認知科学 / ai-philosophy-cognitive-science
minodriven
13
6.3k
はてなアカウント基盤 State of the Union
cockscomb
1
730
依存関係から依存物へ―Dependencyという言葉の歴史をひも解く
j_lee
0
140
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
300
Inside Stream API
skrb
1
780
軽量Java基盤の設計 DIコンテナに頼らない、長期保守と1秒起動の実現 JJUG CCC 2026 Spring
macha64
0
580
Featured
See All Featured
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.3k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1k
A designer walks into a library…
pauljervisheath
211
24k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.7k
The SEO identity crisis: Don't let AI make you average
varn
0
500
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
480
So, you think you're a good person
axbom
PRO
2
2.1k
Documentation Writing (for coders)
carmenintech
77
5.4k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
1.1k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.3k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
780
Transcript
YouTube のチャット欄の配置を変更してみた WQHD での複窓のためのchrome 拡張機能 吉澤亜斗武 1
内容 背景 YouTube のレイアウト Chrome 拡張機能の作成の基本 チャット欄の配置を変更する まとめ 付録 2
背景 3
YouTube での複数の動画を視聴 フルHD の場合 4
YouTube での複数の動画を視聴 (WQHD) 新しいモニターを買ったら... 5
YouTube はページ幅が1000px を境にレイアウトが変わります 横並びで複窓(2 窓)にする時WQHD ではチャット欄が動画プレイヤー横にくるための 動画プレイヤーのサイズが小さくなります 画面幅 1 窓辺りの幅
チャット欄の位置 動画プレイヤーの横幅 フルHD 1920 960 動画プレイヤーの下 945 WQHD 2560 1280 動画プレイヤーの横 791 6
目的 WQHD での複窓の際に動画プレイヤーをフルHD の複窓表示より大きくしたい チャット欄はニコニコ風に表示する別拡張機能 の関係でDOM 自体は削除したく ない → チャット欄の配置を変更するchrome
拡張機能を作ろう 1 1: Flow Chat for YouTube Live 7
成果物 chrome 拡張機能: https://github.com/yAtomtom/youtube-chat-rearranger 動画が幅に対して真ん中に表示されます. 8
YouTube のレイアウト 9
基本構成 <ytd-watch-flexy> <div id="full-bleed-container" class="style-scope ytd-watch-flexy"> ... </div> <div id="columns"
class="style-scope ytd-watch-flexy"> <div id="primary" class="style-scope ytd-watch-flexy"> ... </div> <div id="secondary" class="style-scope ytd-watch-flexy"> ... </div> </div> </ytd-watch-flexy> 10
two columns layout full-bleed-container は表示されずに2 カラム表示になる primary, secondary は幅の上限やマージンが存在する 11
single column layout secondary は表示されずにfull-bleed-container とprimary で1 カラム表示になる full-bleed-container は幅の上限やマージンがなくシアターモードでも使用される
12
戦略候補: DOM 移動 vs CSS 変更 チャット欄( #secondary ) を動画下に持ってくる方法は大きく2
通り 観点 DOM 移動 CSS 変更(CSS Grid ) やり方 secondary を primary の子へ移動 #columns にGrid を当て見た目だけ再配置 DOM 構造 変わる 不変( display: contents で透明化) iframe チャット 再挿入で壊れる( about:blank ) 影響なし 仕様変更への強さ 弱い( src の自前再構築が必要) 強い → DOM 移動には iframe が壊れる落とし穴がある.本稿では DOM 移動を試みた後 CSS Grid で見た目だけ変える方法を紹介する 13
拡張機能の作り方 14
manifest.json の例 manifest.json を含むプロジェクトフォルダを chrome://extensions/ から読み込めばよ い { "name": "YouTube
Chat Rearranger", "version": "1.2", "manifest_version": 3, "description": "ライブ・アーカイブでYouTubeチャット欄をbelow(説明欄,コメント欄)と横並びにします", "permissions": ["storage"], "action": { "default_title": "YouTube Layout Modifier", "default_popup": "popup.html" }, "content_scripts": [ { "matches": ["*://www.youtube.com/watch*"], "js": ["content.bundle.js"], "css": ["styles/layout.css"], "run_at": "document_end" } ] } 15
manifest.json のkey の例 manifest_version マニフェスト ファイル形式のバージョン. 使用できるkey やブラウザによって対応状況が違う content_scripts URL
がマッチしている場合にjs やCSS を読み込む (今回は js にバンドル、 css にレイアウト定義 styles/layout.css を指定) run_at: document_end でDOM 構築直後に読み込む action ツールバーの拡張機能アイコンに外観や動作を定義 参考 https://developer.chrome.com/docs/extensions/reference/manifest https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/manifest.json 16
チャット欄の配置を変更する 17
まずは DOM 移動を試す 18
コード例(DOM 移動・試行) const player = document.getElementById('player'); const below = document.getElementById('below');
const secondary = document.getElementById('secondary'); // 新しいレイアウト用ラッパー const layout = document.createElement('div') // layout に below, secondary を移動 layout.appendChild(below); layout.appendChild(secondary); // layout を player の直後に挿入 const parent = player.parentNode; // primary parent.insertBefore(layout, player.nextSibling); 19
DOM 移動するとチャット欄が表示されない. . . 20
なぜ壊れるか: iframe.contentWindow.location.href チャット欄は iframe ( #chatframe ) 。DOM 移動で再挿入されると navigable
が作り直さ れるのが原因. HTML(Living Standard) の仕様上、再挿入された iframe は src 属性を持たないと contentWindow.location.href が about:blank になる(中身が空に) . <iframe id="chatframe" class="style-scope ytd-live-chat-frame"> #document(about:blank) <html><head></head><body></body></html> </iframe> 切り離し時のchild navigable の削除 挿入時のiframe attribute の処理 21
回避策(src 再構築)と、その限界 壊れた iframe の src を自前で再構築すれば一応直せる( live_chat?v=... を設定す るなど)
. しかしこの方針は脆い: アーカイブでは live_chat_replay?continuation=... とパラメータが変わり、トー クン抽出が必要 YouTube 側の仕様変更に追従し続ける必要がある そもそも iframe を再挿入したことが問題の根源 → DOM を動かさなければ iframe は壊れない.見た目だけ CSS で変えればよい. 22
採用案: DOM を動かさず CSS Grid で再配置 #columns に .ytcr-active を付け、
#primary / #primary-inner を display: contents で“ 透明化” すると、子の #below / #secondary が直接 grid item になる (DOM は不動) . #columns.ytcr-active { display: grid !important; grid-template-columns: 2fr 1fr; grid-template-areas: "player player" "below secondary"; } /* primary を透明化して子を grid item に昇格 */ #columns.ytcr-active > #primary, #columns.ytcr-active #primary-inner { display: contents !important; } #columns.ytcr-active #player { grid-area: player; } #columns.ytcr-active #below { grid-area: below; } #columns.ytcr-active > #secondary { grid-area: secondary; } 23
表示OK 24
まとめ 目的: WQHD の複窓で動画を大きくしたい。ただしチャット欄の DOM は残した い DOM 移動だと iframe
( #chatframe ) が再挿入で about:blank になりチャットが壊 れる → DOM を動かさず CSS Grid ( display: contents )で見た目だけ再配置して回避 25
付録 26
1. continuation ライブ配信ではGET を常に連続して叩くことでチャットを取得しているが アーカイブ動画ではcontinuation というトークンを基に一定間隔で効率的に取得 リプレイ表示ボタンを押すと、YouTube 本体がこのトークンを使ってチャットをまと め取得する(DOM 移動時は自前で取得し直す必要がある)
. GET のレスポンスbody (抜粋): "continuationContents": { "liveChatContinuation": { "continuations": [ { "liveChatReplayContinuationData": { "timeUntilLastMessageMsec": 5000, "continuation": "op2w0wR8Gl5DaWtxSndvWVZVT...." } }, ... ], "actions": [...] } } 27
2. DOM 変更によるバグの例 シークバーを動かすと薄暗い映像が部分的に表示 28
とりあえずhtml をみてみる <div class="ytp-storyboard-framepreview" data-layer="4" style=""> <div class="ytp-storyboard-framepreview-timestamp">1:09:48</div> <div class="ytp-storyboard-framepreview-img"
style=" width: 697.084px; height: 393px; margin: 0px 1px 0px 0px; background: url('https://i.ytimg.com/sb/KU0qH-UmXfg/storyboard3_L3/M46.jpg?sqp=xxx&sigh=yyy') -1396px -393px / 2094px 1179px; "> </div> </div> 29
storyboard スプライト画像の一つで、複数の画像を1 つの画像ファイルにまとめて管理し、 必要な部分を切り出して表示するもの. 30
拡大してあげる const player = document.querySelector('div.style-scope.ytd-player'); const previewImg = document.querySelector('.ytp-storyboard-framepreview-img'); //
拡大率計算 const scaleX = player.clientWidth / previewImg.clientWidth; const scaleY = player.clientHeight / previewImg.clientHeight; // transform で拡大(左上基準で拡大) previewImg.style.transformOrigin = 'top left'; previewImg.style.transform = `scale(${scaleX}, ${scaleY})`; 31
余談: scrubbing-thumbnail シークバー下部では5×5 のstoryboard を最大100 枚使い2500 のシーク箇所を表示. 動画は最大12 時間(43200 秒)
なので約17 秒間隔でシーク箇所を表示することが可能. 32