概要
つぶやき(タイムライン上のノート)のテキストにYouTube URLが含まれていた場合、埋め込み再生プレーヤーを自動で表示する機能を追加した。管理画面(投稿画面)ではテキスト入力中にリアルタイムでプレビューが表示される。
背景と目的
これまで、つぶやきにYouTubeのURLを貼り付けても、単なるテキストとして表示されるだけだった。閲覧者がYouTubeの動画を視聴するには、URLをコピーしてブラウザで開く必要があった。
この機能により、つぶやきの中にYouTube動画を直接埋め込み、その場で再生できるようになった。
実装内容
対応するYouTube URLの形式
以下の形式のURLを自動検出する:
https://www.youtube.com/watch?v=VIDEO_IDhttps://youtube.com/watch?v=VIDEO_IDhttps://youtu.be/VIDEO_IDhttps://www.youtube.com/embed/VIDEO_IDhttps://www.youtube.com/shorts/VIDEO_ID
変更したファイル
公開ページ側(src/components/TimelineItem.astro):
extractYouTubeVideoIds()関数を追加し、テキストからビデオIDを抽出する- ビデオIDが見つかった場合、つぶやきの枠下に
iframeで埋め込みプレーヤーを表示する - レスポンシブ対応のため、
padding-bottom: 56.25%(16:9比率)のCSSテクニックを使用する
管理画面側(src/pages/admin/timeline/index.astro):
- テキストエリアの
inputイベントでYouTube URLをリアルタイム検出する - 検出されたURLの埋め込みプレビューを投稿フォーム内に表示する
- 投稿完了時にプレビューをクリアする
セキュリティ対策
- ビデオIDの厳密な検証: ビデオIDは英数字・ハイフン・アンダースコアのみの11文字に制限し、不正な文字列の注入を防止する
- プライバシー保護モード:
youtube-nocookie.comを使用し、YouTubeのトラッキングCookieが設定されないようにする - DOM操作の安全性: 管理画面のプレビュー生成では
innerHTMLを使用せず、document.createElement()でDOM要素を生成する
sandbox属性に関する知見
初期実装ではiframeにsandbox="allow-scripts allow-same-origin allow-presentation"を設定していた。しかしYouTubeプレーヤーはこの制限下では「エラー153 動画プレーヤーの設定エラー」となり正常に動作しなかった。YouTube埋め込みはクロスオリジンであるため、ブラウザの同一オリジンポリシーにより既に隔離されている。youtube-nocookie.comによるプライバシー保護と、ビデオIDの厳密な検証の2層で安全性を確保する方針に変更した。
技術的な補足
レスポンシブな動画埋め込み
iframeを直接配置すると、画面幅が変わったときにアスペクト比が崩れる。これを防ぐため、親要素にpadding-bottom: 56.25%を指定し、iframeをposition: absoluteで配置するテクニックを使用した。56.25%は9 ÷ 16 × 100で算出される16:9のアスペクト比である。
重複の排除
同じ動画URLがテキスト内に複数回記述されていた場合、Setを使って重複を排除し、1つの埋め込みプレーヤーのみを表示する。