YouTube埋め込みを自動化
目次
YouTubeのリンクを自動で埋め込みに変換するようにした。
例
以下Claudeによる解説
Astro ブログに高パフォーマンスな YouTube 埋め込みを実装した
Building a High Performance YouTube Embed in Astro を参考に実装した。基本的な考え方は元記事に詳しいので、ここでは本ブログの構成に合わせて変えた部分を中心に書く。
やったこと
YouTube の URL を記事にそのまま貼るだけで、サムネイル+再生ボタンの埋め込みに自動変換されるようにした。
アーキテクチャ
remark プラグインとして実装(src/plugins/youtube.mjs)
段落にベタ書きした YouTube URL を検出し、ビルド時に HTML へ変換する。
<!-- こう書くだけ -->https://www.youtube.com/watch?v=XXXXXXXXXXXlink 型ノードを走査するため、GFM のオートリンクが有効な .md でも MDX でも動作する。
remark-link-card-plus との衝突回避
両プラグインとも「段落の中の単独 URL」を処理対象にするため、プラグインの実行順が重要になる。
remarkPlugins: [ remarkYoutube, // ← 先に YouTube URL を html ノードに変換 [remarkLinkCard, { cache: true }], // ← html ノードはスキップされる]サムネイルのビルド時ダウンロード(元記事にない機能)
元記事は実行時に YouTube CDN からサムネイルを取得する。本実装ではビルド時に public/yt-thumbs/{videoId}.jpg へ保存し、外部リクエストをゼロにした。
maxresdefault.jpg → 取得できなければ → hqdefault.jpg同じ動画が複数記事に登場しても 1 回しかダウンロードしない(existsSync によるキャッシュ)。
生成物はコミット不要なので .gitignore に追加している。
public/yt-thumbs/ファサードパターン(共通)
元記事と同様、初期表示はサムネイル+再生ボタンのみ。クリック時に初めて <iframe> を挿入する。
// BlogPost.astro に追加したスクリプトdocument.addEventListener('click', function (e) { const btn = e.target.closest('.yt-play'); if (!btn) return; const embed = btn.closest('.yt-embed'); embed.innerHTML = '<iframe src="' + btn.dataset.src + '" ...></iframe>';});YouTube の JS(約 450 KB)をユーザーが再生ボタンを押すまで読み込まないため、ページの初期ロードに影響しない。
ファイル構成
| ファイル | 役割 |
|---|---|
src/utils/youtube.ts | URL パース・サムネイル取得ユーティリティ(コンポーネント用) |
src/plugins/youtube.mjs | remark プラグイン本体 |
src/styles/global.css | .yt-embed のスタイル |
src/layouts/BlogPost.astro | クリックハンドラー |