t-log

YouTube埋め込みを自動化

目次

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=XXXXXXXXXXX

link 型ノードを走査するため、GFM のオートリンクが有効な .md でも MDX でも動作する。

両プラグインとも「段落の中の単独 URL」を処理対象にするため、プラグインの実行順が重要になる。

astro.config.mjs
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.tsURL パース・サムネイル取得ユーティリティ(コンポーネント用)
src/plugins/youtube.mjsremark プラグイン本体
src/styles/global.css.yt-embed のスタイル
src/layouts/BlogPost.astroクリックハンドラー