つぶやきにYouTube埋め込み再生機能を実装した

概要

つぶやき(タイムライン上のノート)のテキストにYouTube URLが含まれていた場合、埋め込み再生プレーヤーを自動で表示する機能を追加した。管理画面(投稿画面)ではテキスト入力中にリアルタイムでプレビューが表示される。

背景と目的

これまで、つぶやきにYouTubeのURLを貼り付けても、単なるテキストとして表示されるだけだった。閲覧者がYouTubeの動画を視聴するには、URLをコピーしてブラウザで開く必要があった。

この機能により、つぶやきの中にYouTube動画を直接埋め込み、その場で再生できるようになった。

実装内容

対応するYouTube URLの形式

以下の形式のURLを自動検出する:

変更したファイル

公開ページ側(src/components/TimelineItem.astro):

管理画面側(src/pages/admin/timeline/index.astro):

セキュリティ対策

  1. ビデオIDの厳密な検証: ビデオIDは英数字・ハイフン・アンダースコアのみの11文字に制限し、不正な文字列の注入を防止する
  2. プライバシー保護モード: youtube-nocookie.comを使用し、YouTubeのトラッキングCookieが設定されないようにする
  3. DOM操作の安全性: 管理画面のプレビュー生成ではinnerHTMLを使用せず、document.createElement()でDOM要素を生成する

sandbox属性に関する知見

初期実装ではiframesandbox="allow-scripts allow-same-origin allow-presentation"を設定していた。しかしYouTubeプレーヤーはこの制限下では「エラー153 動画プレーヤーの設定エラー」となり正常に動作しなかった。YouTube埋め込みはクロスオリジンであるため、ブラウザの同一オリジンポリシーにより既に隔離されている。youtube-nocookie.comによるプライバシー保護と、ビデオIDの厳密な検証の2層で安全性を確保する方針に変更した。

技術的な補足

レスポンシブな動画埋め込み

iframeを直接配置すると、画面幅が変わったときにアスペクト比が崩れる。これを防ぐため、親要素にpadding-bottom: 56.25%を指定し、iframeposition: absoluteで配置するテクニックを使用した。56.25%9 ÷ 16 × 100で算出される16:9のアスペクト比である。

重複の排除

同じ動画URLがテキスト内に複数回記述されていた場合、Setを使って重複を排除し、1つの埋め込みプレーヤーのみを表示する。