TL;DR
Qiitaニュースのメールで、毎週水曜ごろに「先週いいねが多かった投稿ベスト20」が届きます。
この20記事をNotebookLMで1本ずつ独立した「音声概要」にして、通勤や家事の間に耳で流し読みできるようにしました。
NotebookLMの操作は、スキルにしてClaude(Claude in Chrome)に任せています。「ソースを1件だけ選ぶ」操作が意外と難しく、そこを解決するのに一番苦労しました。
「全ソースまとめて1本」ではなく「1ソース=1本」にするのがポイントです。
まとめて作ると20記事が1本の雑なダイジェストになり、どの話がどの記事のものか分からなくなります。
全体の流れ
① Qiitaニュースのメール
↓ 20記事を開いてURLを集める
② NotebookLM のノートに 20URL をソースとして追加
↓ /notebooklm-audio (Claudeに丸投げ)
③ 各ソースごとに「音声概要」を1本ずつ生成(20本)
↓
④ Studio の並び順どおりに元記事を開く(気になった回をすぐ読める)
① 20記事のURLを集める
ランキングメールのリンクを20個開いて、タブのURLをまとめてコピーします。
ここで自作のChrome拡張Copy All Tab URLs(全タブURLコピー)を使っています(宣伝です)。
開いているタブのURLを1クリックで改行区切りにしてコピーできるので、そのままNotebookLMに貼れます。
メール内のリンクをそのままコピペしないでください。
Qiitaニュースのリンクは配信サービスのトラッキングURL(us.list-manage.com/...?e=...)になっていて、e= は受信者ごとの識別子です。
記事やSNSに貼ると、自分の購読情報を公開することになります。
一度開いて、リダイレクト後の https://qiita.com/<user>/items/<id> を使いましょう。タブを開いてから拡張でコピーすれば、自然とこのURLになります。
② NotebookLMにソースとして追加
- NotebookLMで新しいノートを作る
- 「ソースを追加」→「ウェブサイト」に、①でコピーした20行をまとめて貼り付ける
- ソースが20件並べば準備OK
2026年夏ごろから notebook.google.com(Gemini Notebook 表記)でも開くようになりましたが、中身は同じです。
③ Claudeに各ソースの音声概要を作らせる
手作業でやると、次の操作を20回繰り返すことになります。
- ソースを全解除
- 1件だけチェック
- Studio の「音声解説」を開く
- 形式を「概要」に変更(デフォルトは「詳細」)
- 生成
やっていられないので、Claude in Chrome 用のスキル notebooklm-audio にしました。
ノートを開いた状態で /notebooklm-audio と打つだけです。
ハマりどころ
以下はすべて実際に踏んだ問題で、対策はスキルに書いてあります。
1. .click() ではソースが選択されない
JSで input.click() すると、見た目のチェックは付くのに、NotebookLM 内部の選択状態が更新されません。
その結果、検証では「1件選択」で合格するのに、生成は全ソースが混ざった状態で走ります。これで20本分の生成を2回無駄にしました。
対策は、実際のクリックと同じイベント列をすべて発火させることです。
const fullClick = (el) => {
const r = el.getBoundingClientRect();
const base = { bubbles: true, cancelable: true, composed: true, view: window,
clientX: r.left + r.width / 2, clientY: r.top + r.height / 2,
button: 0, buttons: 1 };
const p = { ...base, pointerId: 1, pointerType: 'mouse', isPrimary: true };
el.dispatchEvent(new PointerEvent('pointerover', p));
el.dispatchEvent(new PointerEvent('pointerenter', p));
el.dispatchEvent(new MouseEvent('mouseover', base));
el.dispatchEvent(new PointerEvent('pointerdown', p));
el.dispatchEvent(new MouseEvent('mousedown', base));
el.focus?.();
el.dispatchEvent(new PointerEvent('pointerup', { ...p, buttons: 0 }));
el.dispatchEvent(new MouseEvent('mouseup', { ...base, buttons: 0 }));
el.dispatchEvent(new MouseEvent('click', { ...base, buttons: 0 }));
};
2. 選択数の確認は「N 個のソース」表示で行う
input.checked の値は当てになりません。生成に実際に使われる選択数は、チャット欄の下にある「N 個のソース」(.selected-num)の表示です。
さらに、生成ダイアログ内の「1 件のソース」表示でも確認してから「生成」を押します。
3. 1本目だけは完成まで待つ
音声生成には1日あたりの上限(私の環境では約20本)があります。
そのため、1本目を作ったら完成まで待ち、Studio に「○:○○ · 概要 · 1 件のソース」と出たのを確認してから残り19本を流します。
ここで「2 件のソース」などになっていたら、すぐに止めます。生成枠を無駄にしないための確認です。
4. 状況確認で Studio のカードをクリックしない
「できたかな?」とカードをクリックすると、それだけで余分に1本生成され、生成枠を1回分使ってしまいます。
状況の確認は、DOM のテキストを読むだけにしています。
5. 投入ログが正常でも全部できたとは限らない
20本投入してログはすべて正常だったのに、2本だけ Studio に現れなかったことがありました。
最後に「完成数=投入数」を必ず突き合わせ、足りなければ内容から未生成のソースを特定して再投入します。
6. Studio の並び順は投入順と一致しない
音声概要は並行で生成されるので、Studio の並び(新しいものが上)と投入順は一致しません。
しかも音声のタイトルはAIが付けた見出しなので、元記事のタイトルとも一致しません。
そこで Claude に、内容をもとに「どの音声がどの記事か」を照合した対応表を作らせています。
④ 元記事をStudio順に開く
最後に、対応表の順(Studio の上から)で元の Qiita 記事をタブで開かせます。
「この回はおもしろかったから元記事を読もう」と思ったときに、すぐ読めて便利です。
Claude in Chrome の navigate は、tabId を省略するとグループ先頭のタブ(作業中の NotebookLM)を上書きします。
私も1回やってしまったので、新しいタブを作ってIDを控え、必ずそのIDを指定して開くようにしています。
実測
| 項目 | 実測(20ソース) |
|---|---|
| 1本目の生成 | 約4〜5分 |
| 残り19本の投入 | 約4〜6分 |
| 全20本の完成 | 投入完了後さらに約8〜20分 |
| 混在ソースの音声 | 0本(対策後) |
放置しておけば、30分前後で20本そろいます。
スキル本体
ヘルパー関数(nlmGenerateOne() など)と手順・禁止事項をまとめた SKILL.md を Gist に置きました。
NotebookLM の UI が変わると動かなくなることがあるので、自分の環境で1本目の様子を見ながら使ってください。
今後やりたいこと
①のURL集めも Claude に任せられそうです。
Gmail コネクタでランキングメールを読むと、「先週いいねが多かった投稿ベスト20」の20件分のタイトルとリンクをメール本文からそのまま取れます。外部ページの「ブラウザで表示」を開く必要もありません。
残る課題は、リンクがトラッキングURLであることだけです。
タブで開いてリダイレクト後の Qiita URL を読む処理(拡張でやっていることと同じ)をスキルに足せば、メールを開いて一言頼むだけで①〜④まで通せるはずです。できたら追記します。
おわりに・注意
- 生成した音声は個人の学習用に使っていて、再配布はしていません。
- NotebookLM の DOM を直接操作しているので、UI 変更で動かなくなることがあります(実際に何度も直しています)。
- 生成上限は時期やアカウントで変わる可能性があります。
耳で聴くと、普段なら開かないジャンルの記事も意外と頭に入ってきます。よければ試してみてください。