youtube-scan
YouTubeをトピック(検索)、チャンネル(アップロード一覧)、またはURL(メタデータ)で動画をスキャンできます。タイトル、再生回数、チャンネル名、アップロード日時を返します。`--rich auto`オプションにより、スコアが高い結果に対して自動的にトリミングされたトランスクリプトスニペットをインラインで表示できます。詳細な分析には`/ro:video-summarize`と組み合わせて使用してください。
description の原文を見る
Scan YouTube for videos by topic (search), channel (uploads feed), or URL (metadata). Returns titles, view counts, channel, upload date. Optionally auto-inlines a trimmed transcript snippet for high-signal hits via `--rich auto`. Pair with `/ro:video-summarize` for a full deep dive.
SKILL.md 本文
YouTube スキャン
3つのモードが、引数から自動検出されます:
- トピック検索 —
"AI agents"または"MCP servers"→yt-dlp "ytsearchN:<q>" - チャンネルフィード —
https://www.youtube.com/@<handle>またはチャンネルURL → アップロードRSS - 動画URL —
https://www.youtube.com/watch?v=...またはhttps://youtu.be/...→ 単一動画メタデータ
デフォルトではトランスクリプトは取得されません。これは発見段階であり、内容吸収ではないためです。--rich auto を使用すると、スキルは「これは重要かもしれない」というヒューリスティック(以下を参照)に一致したヒットのサブセットについて、トリミングされたトランスクリプトスニペットを引き出します。完全なトランスクリプト + スライド + LLM要約については、選んだURLを /ro:video-summarize にパイプします。
使用方法
/ro:youtube-scan "AI agents" # トピック検索、過去7日間、ビュー数上位15件
/ro:youtube-scan "MCP servers" --since 24h # 最新投稿
/ro:youtube-scan "vibe coding" --limit 30 --min-views 10000
/ro:youtube-scan https://www.youtube.com/@simonwillison # チャンネルの最新動画
/ro:youtube-scan https://www.youtube.com/watch?v=XXXX # 単一動画メタデータ
/ro:youtube-scan "MCP" --rich auto # 高シグナルヒット用インライントランスクリプト
/ro:youtube-scan https://youtu.be/XXXX --rich all # 単一動画にトランスクリプトを強制
デフォルト設定
- ウィンドウ:
7d - リミット:
15 - 最小ビュー数: なし(
--min-viewsで低シグナル投稿を除外するよう設定可能) - リッチモード:
off(トランスクリプト取得なし) - リッチ閾値:
30000ビュー/日速度(--rich auto時)。view_count / max(age_days, 1)として計算されます。最近のバイラルヒットを捕捉し、生のビュー数閾値を超えるエバーグリーンコンテンツ(古い音楽動画、研究ストリーム)を除外します。 - リッチキーワード:
mcp,agent,claude,anthropic,openai,protocol,spec,sdk(--rich auto時) - リッチ期間範囲: 3~60分。短い = ショート動画;長い = 論文を先読みしないことの多いストリーム。
- リッチチャンネルデニーリスト: 完全一致(大文字小文字を区別しない、チャンネル全体マッチ):
tool, lou zeffer, jimtv, cosmic hippo, chill music lab, freecodecamp.org, tech with tim。サブストリング(大文字小文字を区別しない):lofi, chillstep, chill music, sleep music, ambient music。初期検証スキャンを支配していたノイズクラス(バンドTOOL、コーディング音楽チャンネル、複数時間の研究ストリーム)を排除します。
モード: トピック検索
yt-dlp "ytsearch${LIMIT}:${QUERY}" \
--dump-json --skip-download --no-write-subs \
--match-filter "upload_date>=$(date -v-${SINCE} +%Y%m%d)" \
2>/dev/null
各JSON行には title, webpage_url, channel, view_count, upload_date, duration, description が含まれます。
--flat-playlist は使用しないでください。 これは upload_date を削除し、リッチモードで使用される速度ヒューリスティックを壊し、--match-filter を静かに無効にします(フィルタリングする日付がない)。フルメタデータモードは動画あたり約1.5秒かかるのに対し、フラットモードは約0.2秒ですが、これは発見時スキャンとして許容できるコストです。
ランキングヒューリスティック: views / (days_since_upload + 2) — HNの年齢減衰に似ていますが、ビュー数加重です。
モード: チャンネルフィード
チャンネルリスト用に yt-dlp より無料RSSエンドポイントを優先 — 認証なし、レート制限なし:
# @ハンドルが与えられた場合、まず yt-dlp 経由で channel_id に解決
CHANNEL_ID=$(yt-dlp --print channel_id "$URL" --playlist-items 0 2>/dev/null | head -1)
curl -s "https://www.youtube.com/feeds/videos.xml?channel_id=${CHANNEL_ID}"
Atom XML。Python で解析(名前空間 http://www.w3.org/2005/Atom および http://search.yahoo.com/mrss/(メディアメタデータ用))。各 <entry> には <title>, <link href="...">, <published>, <media:statistics views="..."> があります。
モード: 単一動画URL
yt-dlp --dump-json --no-download "$URL"
完全なメタデータブロブを返します。抽出: title, uploader, view_count, like_count, upload_date, duration, description, tags。
リッチモード — インライントランスクリプトスニペット
新規コンテンツを含む可能性が高いヒットのサブセット用の軽量トランスクリプト取得。LLMは実行しません。キャプションを取得してトリミングするだけです。これは高シグナルトークの「タイトルだけ見た、本質を見落とした」ギャップを埋めます(カンファレンス基調講演、発表、権威あるオーサーの説明)。
トリガーヒューリスティック(--rich auto)
動画がすべてのハードフィルタ AND 少なくとも1つのシグナルトリガーを通過した場合のみ、トランスクリプトスニペットを取得します。
ハードフィルタ(すべて通過する必要があります):
- チャンネルがデニーリストにない(完全一致 OR サブストリング一致;上記デフォルトを参照)
- 期間が3~60分
upload_dateが解析可能(速度計算に必要)
シグナルトリガー(1つあれば十分):
views_per_day >= ${RICH_THRESHOLD:-30000}— 最新性加重。view_count / max(age_days, 1)として計算。2日間で800kビューのFireshipショート(400k/日)はトリガー;20年前の700M総ビューの音楽動画(≈10k/日)はしません。- タイトル(大文字小文字区別なし)に
${RICH_KEYWORDS:-mcp,agent,claude,anthropic,openai,protocol,spec,sdk}のいずれかが含まれる
呼び出しごとにオーバーライド:
--rich-threshold N(ビュー/日、生のビューではなく)--rich-keywords "a,b,c"--rich-min-duration S/--rich-max-duration S(秒)--rich-channel-deny "a,b,c"(デフォルトデニーリストに追加; 置換しない)
すべてを強制(すべてのハードフィルタとトリガーをバイパス)する場合は --rich all を使用。強制オフの場合は --rich off(デフォルト)。
キャプション取得
TMP=$(mktemp -d)
yt-dlp \
--write-auto-sub --skip-download \
--sub-lang en --sub-format vtt \
-o "$TMP/cap" \
"$URL" 2>/dev/null
英語自動字幕が存在しない場合、グレースフルスキップ(エントリはタイトルのみのままで、[no captions] フラグ付き)。
VTT → プレーンテキスト → トリミング
python3 - "$TMP/cap.en.vtt" <<'PY'
import sys, re, pathlib
vtt = pathlib.Path(sys.argv[1]).read_text(errors="ignore")
# WEBVTT ヘッダ + キュータイミング行を削除、キャプションテキストのみ保持
lines = [l for l in vtt.splitlines()
if l.strip() and "-->" not in l and not l.startswith(("WEBVTT", "Kind:", "Language:", "NOTE"))]
# yt-dlp が挿入するHTMLライクタグを削除(<c>, <00:00:00.000>)
text = re.sub(r"<[^>]+>", "", "\n".join(lines))
# 連続重複行を除外(自動キャプション転がりオーバーラップ)
out, prev = [], None
for l in text.splitlines():
s = l.strip()
if s and s != prev:
out.append(s); prev = s
joined = " ".join(out)
# 約1000単語にトリミング(最初の1000はほとんどのトークの導入/論文をカバー)
words = joined.split()
print(" ".join(words[:1000]))
PY
出力: 約1000単語の読みやすいテキスト。30分のトークの場合、導入 + 最初の3分の1であり、通常は論文と新規用語を含みます。
リッチスニペット付き出力形式
トリガーされた動画の下に、スニペット付き > ブロックとマーカーを追加します。ダウンストリーム消費者は自動トリガーされたことを知ります:
1. <Title> (<N> views · <M> days ago · <channel>)
https://www.youtube.com/watch?v=<id>
<description から簡潔な説明、1行>
📜 [transcript snippet, auto-rich, ~1000 words]
> <snippet text...>
トリガーされ ない 動画の場合、出力は変わりません。スキャンはリーンに保ちます。
トリガーされても スキップする場合
期間外3~60分とデニーリストチャンネルは、事後スキップではなくハードフィルタで事前に拒否されます(トリガーヒューリスティックを参照)。トリガー後、残りのスキップ理由のみ:
- 英語自動キャプション利用不可
- キャプション取得エラー(ジオブロック、レート制限)
各場合、エントリに [transcript skipped: <reason>] を付加して進みます。
出力
# YouTube: "<query>" (window: <since>, mode: <search|channel|url>)
1. <Title> (<N> views · <M> days ago · <channel>)
https://www.youtube.com/watch?v=<id>
<description から簡潔な説明、1行>
2. ...
単一URL モードの場合、以下を出力:
# Video: <title>
Channel: <channel>
Uploaded: <date> (<N days ago>)
Views: <count>
Likes: <count>
Duration: <mm:ss>
<description, first 5 lines>
発見モード(トレンドスキャン用)
/ro:trend-scan --discover で呼ばれた場合、トピックがありません。その場合、いくつかの 特定の シードを順序で実行 — AI, coding, new tool のような一般的な単語は、音楽動画、lofi ストリーム、バンド TOOL を引く。代わりに、エージェント/AI ツーリング枠の絞り込みフレーズを使用:
ytsearch15:AI agents
ytsearch15:MCP
ytsearch15:claude code
ytsearch15:anthropic
ytsearch15:new AI tool
ytsearch15:AI keynote
各シードは --flat-playlist なしでフェッチされるため upload_date が存在(速度計算に必須)。--match-filter "upload_date>=$SINCE" 句はフェッチ時に適用される必要があります。フラットプレイリストモード下では操作不可です。
--since ウィンドウにフィルタ、webpage_url で重複排除、ビュー数でソート。上位20件を返します。
呼び出し元が --rich auto を渡した場合(トレンドスキャンはデフォルトで発見モードでこれを行う)、上位20件の各々にリッチヒューリスティックを適用し、マッチのためのトランスクリプトスニペットをインライン化します。v2ヒューリスティック(速度ベース + キーワード + ハードフィルタ)により、実際のニュースクラスタがある場合(例えば Anthropic アナウンスウィーク)の典型的な生成は発見スキャンあたり38動画トリガー、静かな週は02。
依存関係
yt-dlp(video-summarizeスキルインストール、またはbrew install yt-dlpから)curl(チャンネルRSS用)
エラーハンドリング
- 検索用yt-dlpが失敗 — YouTubeはスクレイピング防御を時々回転させます。
--extractor-args "youtube:player_client=web"にフォールバックするか--no-check-formatsを試します。 - チャンネルフィードが404を返す — チャンネルハンドル → ID解決が失敗。ユーザーに正規チャンネルURLを求めます。
- トレンディングフィード(
youtube.com/feed/trending)は 2026-04以降壊れている(ホームページへリダイレクト)。発見モードで信頼しないでください;代わりにシード検索を使用します。 - リッチモードキャプション取得失敗 は一部動画で — 非致命的;エントリは
[transcript skipped: <reason>]付加されたスキャンに留まります。1つの悪い動画が残りをブロックしないようにしてください。
関連項目
video-summarize— ダウンストリーム: 動画を選ぶ、トランスクリプト + スライド + LLM要約を取得。hn-scan,reddit-scan,x-scan— 兄弟ソーススキャナ。trend-scan— アップストリーム: すべてのソーススキャナを並列に編成。llm-wiki/.claude/skills/ingest-youtube— 動画をヴォルトに保持したい場合。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- RonanCodes
- ライセンス
- MIT
- 最終更新
- 2026/5/12
Source: https://github.com/RonanCodes/ronan-skills / ライセンス: MIT