skills/shc-distill/SKILL.md
萃取網路文章、訪談、演講、影片、podcast、電子書(PDF/epub) 的學習重點精華,整理成結構化 markdown 筆記並儲存。當來源為訪談影片或 podcast 時,會自動擷取完整字幕並存為三個 SRT 字幕檔:英文(*.en.srt)、繁體中文(*.zh-tw.srt)、中英雙語(*.en&cht.srt)。當來源為大型內容(如電子書 PDF/epub,超過 50 頁)時,自動分段處理並用子代理並行萃取各段,最後產出分段筆記與彙總筆記。當使用者提供 URL 或本地檔案路徑並要求萃取重點、整理筆記、提取學習精華、summarize key takeaways 時觸發。Use when user shares a URL or local file path and wants to extract insights, distill key takeaways, summarize learnings, or create study notes from articles, interviews, talks, videos, podcasts, essays, blog posts, or books (PDF/epub). When the source is an interview video or podcast, automatically extracts and saves three SRT subtitle files: English (*.en.srt), Traditional Chinese (*.zh-tw.srt), and bilingual (*.en&cht.srt). When the source is a large document (e.g., book PDF/epub over 50 pages), automatically segments content and processes each segment in parallel using subagents, producing per-segment notes and a consolidated summary.
npx skillsauth add chen4hao/shc-skills skills/shc-distillInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
重複檢查(Preflight):在任何下載或處理之前,先確認此來源是否已被 distill 過。
.md 檔案是否包含該 URL 或檔案路徑:
Grep pattern="{URL或檔案路徑}" path="/Users/chen4hao/Workspace/aiProjects/infoAggr" glob="*.md"
.md 檔所在目錄,確認 .md 和 .srt 檔案是否完整存在。
取得內容:根據來源類型取得內容:
download.py 會同時輸出影片 metadata(Title、Channel、Upload date、Duration、Description),這是影片類來源的唯一 metadata 來源。file:// 路徑或絕對路徑):使用 Read 工具讀取 PDF(每次最多 20 頁)。先讀取前 20 頁判斷全文結構(目錄、章節數、總頁數),再決定是否進入「大型內容分段處理」流程(見下方規則)。--list 掃描結構,再用 --all 提取所有章節為獨立 .txt 檔。重要:因為子代理無法存取 /tmp/,epub 必須直接提取到專案輸出目錄下的 _tmp_extract/ 子目錄:
uv run python3 $SCRIPTS/epub_extract.py "{epub路徑}" "{專案輸出目錄}/_tmp_extract" --list
uv run python3 $SCRIPTS/epub_extract.py "{epub路徑}" "{專案輸出目錄}/_tmp_extract" --all
提取後用 Read 工具讀取各 .txt 檔。強烈建議先跑 read_plan.py 自動產生安全的 offset/limit 批次(中文密度會自動降到 ~35 行):uv run python3 $SCRIPTS/read_plan.py {txt路徑} [--start N --end M],輸出可直接複製成 Read 呼叫。或讓子代理直接讀取。再根據章節數量決定是否進入「大型內容分段處理」流程。完成後清理 _tmp_extract/ 目錄。x.com 或 twitter.com 的貼文(格式如 https://x.com/{user}/status/{id}),因 X 平台封鎖爬取,WebFetch 通常會失敗(402 錯誤)。此時依序嘗試以下替代方案:
https://twitter-thread.com/t/{status_id},例如 https://x.com/bcherny/status/2007179832300581177 → https://twitter-thread.com/t/2007179832300581177
<meta name="description"> 裡,但 WebFetch 的小模型對長內容會主動壓縮/改寫(實測會回傳條列摘要,並用 [Full thread continues...] 省略後半,即使 prompt 明確要求 verbatim 也無效)。正確作法:用 Bash 執行 curl -sL "https://twitter-thread.com/t/{status_id}",再用 Read 工具讀取 persisted-output 檔,從 meta description 取得無損的全文。https://publish.twitter.com/oembed?url={原始URL} 取得基本推文內容大型內容分段處理(條件步驟):若內容超過 50 頁(PDF/epub 書籍),進入分段處理流程(見下方「大型內容分段處理規則」)。此步驟會取代步驟 3-6,改為並行萃取各分段並產出彙總筆記。
字幕擷取(條件步驟):若來源是影片或 podcast 的訪談/對話內容,執行字幕擷取流程(見下方「字幕擷取規則」)。預設產出三個 SRT 字幕檔:.en.srt(英文)、.zh-tw.srt(繁體中文)、.en&cht.srt(中英雙語)。完整流程:下載 → 去重 → 翻譯補全 → 合併 → 驗證。例外:純中文來源(Bilibili 等中國平台、或 Whisper 偵測為 zh)預設只產 .zh-tw.srt 單檔,跳過 ZH→EN 翻譯 pipeline(見下方「影音與字幕擷取規則 → 純中文來源特例」)。例外:多 P playlist(如 Bilibili anthology >3 P)走「多 P 分段流程」,每個分 P 獨立處理(見下方「多 P playlist 特例」)。
適用性評估:通讀全文後,先判斷每個輸出區塊是否有足夠素材(見下方「區塊適用性判斷」)。
深度萃取:根據下方的輸出格式,對每個適用區塊進行深度分析並萃取內容精華。
輸出結果:依序輸出所有適用區塊,省略不適用的區塊。
儲存檔案:將完整輸出儲存為 markdown 檔案(見下方儲存規則)。若步驟 3 有產生 SRT 字幕檔,在輸出末尾附上字幕檔路徑。
本步驟在來源為大型內容時執行。一般網頁文章、短影片跳過此步驟。
凡符合任一條件即進入分段處理流程:
是否屬於以下任一種類?
├─ 本地 PDF/epub 書籍,且總頁數 > 50 頁 → 進入
├─ 多 P playlist 影片,且 P 數 > 3 → 進入(每個 P 一段)
├─ 單一長訪談/演講,且 STT 後原文總行數 > 2000 行 → 進入(按時間切 30-60 分鐘/段)
├─ 單一長文章/文件,且總字元 > 60000 字 → 進入
└─ 以上皆非 → 跳過,走一般流程
核心原則:任何單次丟進主 context 會超過 ~30K tokens 原文的來源都該走分段流程——主代理只做 assembly 與跨段精選,不吞原文。2026-04-11 樊登 11 本書 distill 教訓:把 3157 行中文 TXT 全讀進主 context 是反模式,應派子代理分章處理。
PDF 檔案:
epub 檔案:
$SCRIPTS/epub_extract.py --list 掃描結構,獲得章節清單和各章大小$SCRIPTS/epub_extract.py --all 提取所有章節為獨立 .txt 檔(存到 {專案輸出目錄}/_tmp_extract/,因為子代理無法存取 /tmp/)PDF 檔案:
epub 檔案:
🔴 Checkpoint A — 分段大小門檻(啟動前必做)
對每個規劃中的分段執行 wc -l 或目視檔案大小:
違反此規則的後果(實證):Seg10 三章共 158 行,派子代理 → rate limit 失敗 → 內容遺失 → 主代理仍需自行讀檔重做,總耗時加倍。
model: "sonnet" — 使用 sonnet 模型節省成本mode: "dontAsk" — 避免子代理卡在權限確認(用於 Read 等工具)run_in_background: true — 背景執行,並行處理dontAsk 也可能被 sandbox 拒絕),因此子代理只負責分析與回傳完整筆記內容,由主代理統一用 Write 工具寫入所有分段筆記。這避免子代理浪費時間在被拒的寫入嘗試上(每個節省 30-60 秒)。🔴 共用模板檔案機制(防止 prompt 退化)
手動為每個子代理重複寫完整模板,會從第 2-3 個開始自然退化(「格式同 Ch1」——但子代理看不到 Ch1)。因此必須使用共用模板檔案:
_distill_template.md{專案輸出目錄}/_distill_template.md 獲得完整格式要求」cleanup_epub_txt.py 會一併清理此檔案(或手動刪除)共用模板檔案內容(_distill_template.md):
# 書籍章節萃取格式模板
所有輸出必須使用繁體中文(zh-TW),包括任何開頭和結尾文字。原文引用保留原文語言。
直接以 `# ` 標題開頭,不要有任何前言文字(如「以下是筆記…」「所有章節已讀取…」)。結尾停在最後一個 `</details>` 標籤後,不要有任何後語(如「萃取完成,請主代理寫入…」)。
**重要:不要嘗試用 Write 工具或 Bash 寫入檔案(會被 sandbox 拒絕)。請將完整筆記內容直接作為你的回覆輸出,由主代理負責寫入。**
## H1 格式(assemble 依此辨識章節)
**H1 必須為固定格式**:`# Ch{N}: {Title}`(N=阿拉伯數字、Title=英文原章名,例如 `# Ch8: Greater Fools`、Prologue 用 `# Ch0: Prologue`)。第二行起再放完整書名/副標。禁止自由發揮。
## 完整格式結構
# Ch{N}: {章節英文原名}
## {書名} — {章節中文意譯}
> **作者**:{作者}
> **來源**:《{書名}》{章節}
> **內容類型**:書籍章節
> **核心論點**:{一句話概括本章最重要的論點}
---
## Key Takeaway(依重要性排序)
1. **{簡短標題}**
{2-3 句深度說明:這個觀點為什麼重要?對讀者的啟發是什麼?}
(最多 10 個)
---
## Call to Action(依可操作性排序)← 條件區塊,素材不足完全省略
1. **{具體行動標題}**
- **做什麼**:{明確的執行步驟}
- **為什麼**:{預期效果或潛力}
---
## Mistakes & Lessons Learned ← 條件區塊,需有作者明確承認的錯誤或失敗教訓。素材不足完全省略
1. **{錯誤標題}**
{錯誤的具體經過:在什麼情境下、做了什麼決定、造成什麼後果}
**教訓**:{從這個錯誤中學到的具體原則或行為改變}
---
## Unique Secret ← 條件區塊,需有與主流觀點明確不同的看法。素材不足完全省略
1. **{洞見標題}**
- 🔸 主流觀點:{大部分人相信的 X}
- 🔹 講者洞見:{但講者發現事實是 Y}
- 💡 為何重要:{這個差異帶來的影響}
---
## Best Practice ← 條件區塊,需有講者/作者的第一手經驗。素材不足完全省略
1. **{實踐標題}**
{講者/作者的具體做法描述,包含背景脈絡}
---
## Fun Story ← 條件區塊,需有具體的故事或軼事。素材不足完全省略
1. **{故事標題}**
{故事內容簡述,保留趣味性}
---
## Key Quote(依易記性排序)
1. > "{原文引用}"
>
> — {講者/作者名稱}
**中譯**:{繁體中文翻譯}
**為何重要**:{一句話說明此引用的意義}
(最多 10 個)
---
## One Page Infograph Outline
### 📌 {主標題}
**{副標題:一句話核心訊息}**
**區塊 1:{主題}**
- {重點 1}
- {重點 2}
(3-5 個區塊)
> 💬 金句:"{最具代表性的一句話}"
---
## 📖 折疊閱讀版
<details>
<summary><b>Key Takeaway</b>(N 條)</summary>
1. **標題** — 一行摘要
...
</details>
(每個已輸出的 section 各一個 details 區塊,每條一行摘要)
## 區塊適用性規則
- 條件區塊(Call to Action、Mistakes、Unique Secret、Best Practice、Fun Story)素材不足(少於 2 個有品質的項目)就**完全省略**,不要輸出區塊標題
- **嚴禁硬擠**:不要為了湊數而把不相關的內容塞進區塊
- Mistakes 區塊:不只戲劇性失敗,「做了X才發現Y」也算合格素材
- 引用歸屬:作者引用他人的話不要歸為作者本人的觀點
子代理 prompt 範本(使用共用模板檔案時):
你是學習萃取專家。請為《{書名}》{章節名稱}撰寫萃取筆記。
**步驟**:
1. 用 Read 工具讀取 `{專案輸出目錄}/_distill_template.md` 獲得完整格式要求
2. 用 Read 工具讀取 `{專案輸出目錄}/{txt檔名}` 整個檔案(不設 limit)
3. 根據格式模板和內容撰寫完整萃取筆記
書籍資訊(填入模板的變數):
- 書名:{書名}
- 章節:Ch{N}: {英文章節名}
- 中文意譯:{章節中文意譯}
- 作者:{作者} — {一句話背景}
不要嘗試寫入檔案。將完整筆記直接作為回覆輸出。
$SCRIPTS/assemble_book_notes.py 從 task .output 目錄一次性產出所有章節檔案,避免每次手寫解析腳本:
uv run python3 $SCRIPTS/assemble_book_notes.py "{tasks_dir}" "{專案輸出目錄}" "{年份}-{月份}-{書名}" --use-h1
必須加 --use-h1:從子代理輸出的 H1 # Ch{N}: {Title} 讀取正確章節號和標題。不加此旗標時,腳本用 epub txt 檔序號(ch005=0),幾乎所有書都會產生章節編號偏移。所有分段筆記完成並寫入後,在主 context 中:
{年份}-{月份}-{書名}-Ch{N}-{章節名稱}.md{年份}-{月份}-{書名}-彙總.mdmode: "dontAsk" 也可能被 sandbox 拒絕,實測 6/6 全部失敗的情況屢見不鮮)。子代理只負責分析與回傳,所有檔案寫入由主代理執行。子代理 prompt 中必須明確說明「不要嘗試寫入檔案」。epub_extract.py --all 必須直接輸出到專案輸出目錄(如 /Users/chen4hao/Workspace/aiProjects/infoAggr/{作者}/)。嚴禁先提取到 /tmp 再複製——這會觸發 cp glob sandbox 警告和額外權限提示。每個區塊在輸出前必須先評估內容是否有足夠素材支撐。區塊分為兩類:
必要區塊(所有內容類型都必須輸出):
條件區塊(僅在內容中有明確相關素材時才輸出,以下為輸出順序):
判斷規則:
本步驟僅在來源為影片(YouTube 等)或 podcast 的訪談/對話內容時執行。純文字文章跳過此步驟。
最終目標:
*.en.srt — 純英文字幕*.zh-tw.srt — 純繁體中文字幕*.en&cht.srt — 中英雙語字幕(每條字幕兩行:英文在上、繁體中文在下)若來源為純中文內容(判斷依據見下),預設只產出一個 .zh-tw.srt 檔,跳過整個 ZH→EN 翻譯 pipeline。使用者明確要求英文版才補做翻譯。
判斷純中文來源的依據(任一成立即視為純中文):
bilibili.com、b23.tv)ximalaya.com、lizhi.fm、qingting.fm、xiaoyuzhoufm.com)zh理由:EN 翻譯 pipeline(split_batches → 11 個翻譯子代理並行 → extract → combine → merge)對純中文來源零價值——使用者讀中文筆記,英文 SRT 不會被看,卻耗用 ~14 分鐘 + 大量 API 呼叫。2026-04-11 樊登 11 本書 distill 的實測教訓。
輸出調整:
.zh-tw.clean.srt 重命名為最終 .zh-tw.srt.zh-tw.srt 一個字幕檔yt-dlp 對 Bilibili BV URL 預設會下載整個 anthology(多 P 影片)。若 download.py 輸出出現「Downloading playlist: ...」與「Downloading item X of N」,代表這是多 P 來源。
判斷邏輯:
多 P 分段流程(N > 3):
$SCRIPTS/multi_part_handler.py stt 對所有分 P 批次執行 whisper{prefix}-p01.zh-tw.srt、{prefix}-p02.zh-tw.srt ... -p{N}.zh-tw.srt(每個分 P 獨立),不產生單一合併 SRT{prefix}-p01.mp4 ... -p{N}.mp4,統一存到 download/,用 copy_files.py --multi-part 或 multi_part_handler.py copy 批次複製preflight 快速檢測:
# 只抓 playlist 規模與標題,不拉完整 format JSON(前者 ~100 bytes,後者 ~50 KB)
yt-dlp --cookies-from-browser chrome --flat-playlist --playlist-end 1 \
-O "n_entries=%(playlist_count|1)s|title=%(title)s|duration=%(duration)s" "$URL"
若 n_entries > 3,先告知使用者「偵測到 N P playlist」再繼續(不需要等使用者回覆,直接繼續;僅告知)。
注意:一般非多 P 嫌疑的 URL 不需要跑此 preflight——download.py 內建的 --dump-single-json preflight 會在 stdout 印 Downloading playlist 等資訊,足以判斷。只有已知 Bilibili BV URL 或其他多 P 嫌疑源才需要此外部 preflight。
URL 是否為影片/podcast?
├─ 否 → 跳過,繼續適用性評估
└─ 是 → 內容是否為訪談/對話/演講?
├─ 否(純音樂、短片) → 跳過
└─ 是 → 執行下載 + 字幕擷取
判斷影片/podcast 的依據:
youtube.com、youtu.be、podcasts.apple.com、open.spotify.com、podcasts.google.com為避免權限系統和安全啟發式檢查阻擋,執行 Bash 指令時遵守以下規則:
腳本目錄:所有 Python 腳本已預先存在於 /Users/chen4hao/Workspace/aiProjects/shc-skills/skills/shc-distill/scripts/(以下簡稱 $SCRIPTS)。不需要用 Write 工具建立腳本,直接用 Bash 執行即可。
多 P 影片專用腳本:處理 Bilibili playlist 等多 P 來源一律用 $SCRIPTS/multi_part_handler.py,不要自寫 inline driver:
# 對所有 {TEMP}/{BVID}_p*.mp4 批次執行 Whisper STT(中文)
uv run python3 $SCRIPTS/multi_part_handler.py stt "{TEMP}" "{BVID}" --language zh
# 批次複製 MP4 到 download/,命名為 {prefix}-p01.mp4 ~ -p{N}.mp4
uv run python3 $SCRIPTS/multi_part_handler.py copy "{TEMP}" "{DOWNLOAD_DIR}" "{prefix}" "{BVID}"
# 批次複製 .zh-tw.clean.srt 到專案目錄,命名為 {prefix}-p01.zh-tw.srt ~ -p{N}.zh-tw.srt
uv run python3 $SCRIPTS/multi_part_handler.py copy-srt "{TEMP}" "{PROJECT_DIR}" "{prefix}" "{BVID}"
python3 -c '...' 和 heredoc——會觸發安全啟發式警告。&&、||、;、|)——每個工具呼叫應獨立發出。2>&1、2>/dev/null、> file)。cd——一律使用絕對路徑。grep——改用內建 Grep 工具。/tmp/distill-{VIDEO_ID}/(例如 /tmp/distill-xzQJWLWiYYE/)。從 URL 提取影片 ID(YouTube 的 v= 參數值)。若無法提取,使用 URL 的 MD5 hash 前 8 位。嚴禁使用固定的 /tmp/distill-subs/——會被並行會話覆蓋。cat、head、tail 命令。子代理(bypassPermissions 模式)不受此限。YouTube 自動字幕 clean 後常達 15-20k tokens,一次 Read 會爆 10k token 限制。一律用 offset + limit 分塊讀取:
limit=500 行(每條字幕約 4 行,即約 125 條/次)limit=300 行(中文 token 密度是英文 3-5 倍)主代理接收多個子代理翻譯結果統一寫入時,嚴禁在單一訊息中平行發出 ≥3 個 Write 呼叫——注意力滑落會導致漏填 content 參數(已有慘痛前例)。正確做法:
content 參數的字串長度非零```)或 HTML entity(>),寫入前必須人工剝除,否則會污染 SRT 格式核心策略:字幕優先,影音按需。 先嘗試只下載字幕和 metadata,若成功取得字幕檔則跳過影音下載。只有在完全無法取得任何字幕時,才下載完整影音檔(後續用 Whisper STT 產生字幕)。
不下載中文自動字幕(原因:步驟 C 一律從英文翻譯為中文,中文自動字幕不會被使用,且下載中文字幕常觸發 YouTube 429 限流導致整個下載中斷)。
用 Bash 執行下載($SCRIPTS = /Users/chen4hao/Workspace/aiProjects/shc-skills/skills/shc-distill/scripts):
uv run python3 $SCRIPTS/download.py "/tmp/distill-{VIDEO_ID}" "$URL"
⚠️ Bilibili BV URL 特別提醒:Bilibili 的 BV... 網址若為多 P anthology,yt-dlp 預設會下載全部 P(已知問題)。download.py 目前未加 --no-playlist,因此多 P 影片會產出 {BVID}_p1.mp4、{BVID}_p2.mp4、... 等多檔;stdout 會印 Downloading playlist: {name} 和 Downloading item X of N。看到這兩行時代表是多 P 來源——走「多 P playlist 特例」流程(見上方),用 multi_part_handler.py 處理後續。
判斷後續流程:download.py 的 stdout 已包含所有判斷資訊(Title、Channel、Upload date、Duration、Description、SUBS_AVAILABLE),不需要額外 ls 確認。根據 SUBS_AVAILABLE 判斷:
YES:有字幕,繼續步驟 B(去重清理)。無影音檔需要處理。NO:無字幕但有影音/音訊檔,跳過步驟 B,改用 whisper_stt_long.py 產生字幕:# 長音訊首選(自動分段 + 合併 + OpenCC 繁轉)
uv run python3 $SCRIPTS/whisper_stt_long.py "/tmp/distill-{VIDEO_ID}/{VIDEO_ID}.{ext}" "/tmp/distill-{VIDEO_ID}" --language {語言代碼}
此腳本是長音訊的正確入口,自動處理:
ffprobe 偵測時長:>30 分鐘自動分段(--segment-minutes 預設 45)ffmpeg -c copy 零重編碼切段(避免 mlx_whisper 的 subprocess timeout 問題)--condition-on-previous-text 的幻覺傳遞--language zh)自動用 OpenCC s2twp 繁轉,產出 {basename}.zh-tw.clean.srt長音訊(>30 min)必須背景執行:用 run_in_background: true 發 Bash 呼叫,系統會在完成後自動通知;嚴禁輪詢。
短音訊(<30 min)也可以用此腳本(走 single-shot 模式),或退回舊版 whisper_stt.py(內建 Step 2.5 幻覺清理但 subprocess timeout 寫死 600s)。
STT 完成後字元頻次預檢(見 feedback_batch_preflight_before_subagents.md):
awk '{print length}' {txt_file} | sort -rn | uniq -c | head -5
若最頻行長 ≤3 且佔比 >50%,該段大機率是 Whisper 幻覺區,需額外處理。清理完成後直接跳到步驟 C。
等待期間的生產性動作:Whisper 背景執行時(長音訊約 3-10 分鐘),主代理不要閒置等通知。立刻:
{VIDEO_ID}.info.json 前 5 行取得 title、upload_date、uploader、description(不需要讀 30+ 行,metadata 在開頭即可)N = ceil(total_lines / 550),同訊息並行發 N 個 Read)VTT vs SRT:
--convert-subs "srt"會自動將 VTT 轉為 SRT。若 yt-dlp 因中途錯誤而只產出.vtt檔,不需要額外用 ffmpeg 轉檔——步驟 B 的 dedup.py 已能直接處理 VTT 和 SRT 兩種格式。
YouTube 自動字幕使用漸進式顯示(progressive display),造成兩種重複:(1) 條目間重複——後面的條目包含前面的文字;(2) 條目內重複——同一條目的文字自身有重複片段。用 Python 腳本進行四階段清理:Phase 1 條目間去重、Phase 2 條目內去重、Phase 3 新文字提取、Phase 4 重新切割為自然語句字幕。同時解碼 HTML 實體(> → >)並移除 >> 講者標記。
重要:dedup.py 同時支援 VTT 和 SRT 輸入格式,不需要事先用 ffmpeg 或其他工具轉檔。直接對 yt-dlp 下載的檔案執行即可。
用 Bash 執行去重腳本:
uv run python3 $SCRIPTS/dedup.py "/tmp/distill-{VIDEO_ID}"
執行後,清理過的檔案存為 *.clean.srt。確認至少有一個英文 .clean.srt 檔。
核心策略:以原文字幕為主軌(master track),翻譯產生另一語言的字幕。
YouTube 不同語言的自動字幕各自獨立分段,條目數量和時間切分都不同,直接合併必然導致中英文錯位。因此一律使用清理後的原文字幕作為唯一來源,透過翻譯產生對應的另一語言字幕。
| 已取得 | 翻譯方向 | split_batches.py LANG 參數 | combine_zh.py TARGET_LANG | merge.py --master |
|--------|----------|------|------|------|
| 英文 .clean.srt 存在 | EN → ZH(翻譯為中文) | en(預設) | zh(預設) | en(預設) |
| 僅中文 .zh-tw.clean.srt | ZH → EN(翻譯為英文) | zh | en | zh |
| 都沒有 | 標記失敗,繼續萃取流程 | — | — | — |
字幕翻譯會嚴重污染主 context window,因此必須委派給子代理處理。使用 sonnet 模型以節省成本並加速。
重要:子代理的檔案路徑規則
子代理即使設定 bypassPermissions 也無法存取 /tmp/ 路徑,且 Write 工具極不穩定(即使 dontAsk 也可能被 sandbox 拒絕)。因此翻譯子代理採用回傳策略:
extract_translated_batches.py 從 JSONL task output 一次性提取所有翻譯批次檔(自動 dedup + 驗證)/tmp/distill-{VIDEO_ID}/ 中清理後的英文 SRT 複製到專案輸出目錄流程:
# EN→ZH 流程(英文原文,預設):
uv run python3 $SCRIPTS/split_batches.py "/tmp/distill-{VIDEO_ID}/{英文clean檔名}" "{專案輸出目錄}" "{VIDEO_ID}"
# ZH→EN 流程(中文原文):
uv run python3 $SCRIPTS/split_batches.py "/tmp/distill-{VIDEO_ID}/{中文clean檔名}" "{專案輸出目錄}" "{VIDEO_ID}" 8 zh
腳本同時產出:
{VIDEO_ID}_{LANG}_batch_{N}.srt — 各批次 SRT 檔{VIDEO_ID}_prompt_batch_{N}.txt — 各批次的完整子代理 prompt(含條目數、檔案路徑、翻譯規則、輸出格式,已自動依翻譯方向切換語言對){VIDEO_ID}_agent_config.json — Agent 啟動設定(含每個 batch 的 agent_prompt 和 description){VIDEO_ID}_agent_config.jsonbatches 陣列中的每個 batch,發一個 Agent call:
description: batch 的 description 欄位prompt: batch 的 agent_prompt 欄位(meta-prompt,指示子代理讀取對應的 prompt 檔案)model: agent_settings.model(sonnet)mode: agent_settings.mode(dontAsk)run_in_background: agent_settings.run_in_background(true)ls 檢查——啟動子代理後繼續撰寫萃取筆記等非依賴任務,或直接等待通知)extract_translated_batches.py 一個指令完成提取 + 驗證 + 抽樣:uv run python3 $SCRIPTS/extract_translated_batches.py "{tasks_dir}" "{專案輸出目錄}" "{VIDEO_ID}" "{TARGET_LANG}"
{tasks_dir}:從任一 task-notification 的 <output-file> 路徑取得父目錄{TARGET_LANG}:EN→ZH 流程用 zh(預設),ZH→EN 流程用 en.output JSONL → 按 VIDEO_ID 過濾 → 識別批次/gap 編號 → 從所有 assistant 訊息提取 SRT 條目(去重、清理 code fence)→ 合併 gap 條目 → 寫入批次檔 → 驗證條目數 → 抽樣顯示首尾uv run 路徑,零權限確認/tmp/distill-{VIDEO_ID}/):# EN→ZH 流程(預設):
uv run python3 $SCRIPTS/combine_zh.py "{專案輸出目錄}" "/tmp/distill-{VIDEO_ID}" "{VIDEO_ID}"
# ZH→EN 流程:
uv run python3 $SCRIPTS/combine_zh.py "{專案輸出目錄}" "/tmp/distill-{VIDEO_ID}" "{VIDEO_ID}" "en" "/tmp/distill-{VIDEO_ID}/{中文clean檔名}"
驗證規則:若 EN 和 ZH 條目數差距 > 5 條,需找出丟失最多條目的批次並重新翻譯該批次。差距 ≤ 5 條則由 merge.py 的時間戳對齊兜底。
翻譯規則(已寫入子代理 prompt 中):
嚴禁:在主 context 中逐批翻譯。嚴禁跳過翻譯步驟。
本步驟產出三個字幕檔:純英文、純中文、中英雙語。
用 Bash 執行合併腳本,產出三個版本的 SRT:
# EN→ZH 流程(預設,英文為主軌):
uv run python3 $SCRIPTS/merge.py "/tmp/distill-{VIDEO_ID}"
# ZH→EN 流程(中文為主軌,保留所有原文條目):
uv run python3 $SCRIPTS/merge.py "/tmp/distill-{VIDEO_ID}" --master zh
產出的三個檔案格式:
en.srt(純英文):
1
00:00:01,000 --> 00:00:04,500
Hello, welcome to today's interview.
zh-tw.srt(純中文):
1
00:00:01,000 --> 00:00:04,500
你好,歡迎來到今天的訪談。
bilingual.srt(中英雙語,英文在上):
1
00:00:01,000 --> 00:00:04,500
Hello, welcome to today's interview.
你好,歡迎來到今天的訪談。
重要:所有字幕檔的主檔名必須相同(例如主檔名為 2026-03-Interview-with-Sam-Altman,則產出 .en.srt、.zh-tw.srt、.en&cht.srt)。影音檔也使用相同主檔名,但存放在統一的影音目錄。
重要:因為雙語字幕的檔名含 &(.en&cht.srt),直接在 Bash 中使用 cp 會觸發安全啟發式警告。因此所有複製操作統一寫成 Python 腳本執行。
影音檔存放規則:所有影音檔統一存放在 /Users/chen4hao/Workspace/aiProjects/infoAggr/download/,不與筆記放在同一目錄。若步驟 A 未下載影音檔(因為成功取得字幕),則跳過影音複製。
用 Bash 執行複製腳本:
uv run python3 $SCRIPTS/copy_files.py "/tmp/distill-{VIDEO_ID}" "{儲存目錄}" "/Users/chen4hao/Workspace/aiProjects/infoAggr/download" "{檔案名稱前綴}"
驗證要點(用 head 和 tail 命令抽查 *.en&cht.srt 開頭、中段、結尾各 10 條):
HH:MM:SS,mmm(逗號分隔毫秒)產出三個 SRT 字幕檔,與 markdown 筆記存放在相同目錄下。影音檔(若有下載)統一存放在 /Users/chen4hao/Workspace/aiProjects/infoAggr/download/。
範例:
/Users/chen4hao/Workspace/aiProjects/infoAggr/Lex-Fridman/
├── 2026-03-Interview-with-Sam-Altman.md ← 萃取筆記
├── 2026-03-Interview-with-Sam-Altman.en.srt ← 英文字幕
├── 2026-03-Interview-with-Sam-Altman.zh-tw.srt ← 繁體中文字幕
└── 2026-03-Interview-with-Sam-Altman.en&cht.srt ← 中英雙語字幕(en 在上)
/Users/chen4hao/Workspace/aiProjects/infoAggr/download/
└── 2026-03-Interview-with-Sam-Altman.mp4 ← 影片檔(僅在無字幕時才下載)
檔案命名規則:所有檔案共用相同主檔名,字幕副檔名分別為
.en.srt、.zh-tw.srt、.en&cht.srt。影音檔副檔名依實際格式而定(.mp4為影片、.m4a為音訊),統一放在download/目錄。 影音下載條件:只有在步驟 A 無法取得任何字幕時,才會下載影音檔(供 Whisper STT 使用)。
分級降級(必須按順序嘗試,禁止直接跳到最低級):
.en.srt + .zh-tw.srt + .en&cht.srt)。影音檔僅在無字幕時下載(存放於 download/)> 字幕擷取:未成功 — {原因}嚴禁:因為中文字幕下載失敗就直接放棄雙語目標。必須走子代理翻譯補全流程。
時序要求:必須在所有翻譯子代理確認完成且字幕檔已成功合併並複製到最終位置之後才執行清理。
清理範圍:
/tmp/distill-{VIDEO_ID}/ 整個暫存目錄{VIDEO_ID}_en_batch_*.srt、{VIDEO_ID}_zh_batch_*.srt)用 Bash 執行清理腳本:
uv run python3 $SCRIPTS/cleanup.py "/tmp/distill-{VIDEO_ID}" "{專案輸出目錄}" "{VIDEO_ID}"
將完整的萃取結果儲存為 markdown 檔案,遵循以下慣例:
/Users/chen4hao/Workspace/aiProjects/infoAggr/{作者或來源名稱}/{檔案名稱}.mdMatt-Shumer;中文直接使用,例如 簡立峰){年份}-{月份}-{簡短標題}.md,例如 2026-02-Something-Big-is-Happening.mduv run python3 $SCRIPTS/ensure_dir.py "{目錄路徑}" 建立(避免 mkdir 觸發權限提問)# {文章/演講標題}
> **作者**:{作者全名} — {一句話背景介紹,如職稱或代表作}
> **發布日期**:{YYYY-MM-DD 或 YYYY-MM}
> **來源**:[原文連結]({URL})
> **內容類型**:{文章 / 訪談 / 演講 / 影片 / 報告}
> **核心論點**:{一句話概括全文最重要的論點}
> **影音檔**:{若有下載影音檔,列出完整路徑(位於 download/ 目錄);若無則省略此行}
> **字幕檔**:{若有產生 SRT 字幕檔,列出三個檔名:*.en.srt、*.zh-tw.srt、*.en&cht.srt;若無則省略此行}
---
## Key Takeaway(依重要性排序)
1. **{簡短標題}**
{2-3 句深度說明:這個觀點為什麼重要?對讀者的啟發是什麼?}
2. **{簡短標題}**
{說明}
---
## Call to Action(依可操作性排序)
1. **{具體行動標題}**
- **做什麼**:{明確的執行步驟}
- **為什麼**:{預期效果或潛力}
---
## Mistakes & Lessons Learned(重大錯誤與教訓)
1. **{錯誤標題}**
{錯誤的具體經過:在什麼情境下、做了什麼決定、造成什麼後果}
**教訓**:{從這個錯誤中學到的具體原則或行為改變}
---
## Unique Secret(與眾不同的洞見)
1. **{洞見標題}**
- 🔸 主流觀點:{大部分人相信的 X}
- 🔹 講者洞見:{但講者發現事實是 Y}
- 💡 為何重要:{這個差異帶來的影響}
---
## Best Practice(第一手經驗)
1. **{實踐標題}**
{講者/作者的具體做法描述,包含背景脈絡}
---
## Fun Story(有趣故事)
1. **{故事標題}**
{故事內容簡述,保留趣味性}
---
## Key Quote(依易記性排序)
1. > "{原文引用}"
>
> — {講者/作者名稱}
**中譯**:{繁體中文翻譯}
**為何重要**:{一句話說明此引用的意義}
2. > "{原文引用}"
...
---
## One Page Infograph Outline
### 📌 {主標題}
**{副標題:一句話核心訊息}**
**區塊 1:{主題}**
- {重點 1}
- {重點 2}
**區塊 2:{主題}**
- {重點 1}
- {重點 2}
**區塊 3:{主題}**
- {重點 1}
- {重點 2}
> 💬 金句:"{最具代表性的一句話}"
在完整筆記末尾,附加一個以 <details> 標籤包裝的折疊版本:
--- 與正文分隔## 📖 折疊閱讀版<details> 區塊<summary> 格式:**Section 名稱**(N 條)範例:
---
## 📖 折疊閱讀版
<details>
<summary><b>Key Takeaway</b>(5 條)</summary>
1. **標題** — 一行摘要
2. **標題** — 一行摘要
...
</details>
<details>
<summary><b>Call to Action</b>(N 條)</summary>
1. **行動標題** — 一行摘要
...
</details>
<details>
<summary><b>Mistakes & Lessons Learned</b>(N 條)</summary>
1. **錯誤標題** — 一行摘要 + 教訓
...
</details>
<details>
<summary><b>Unique Secret</b>(N 條)</summary>
1. **洞見標題** — 一行摘要
...
</details>
<details>
<summary><b>Best Practice</b>(N 條)</summary>
1. **實踐標題** — 一行摘要
...
</details>
<details>
<summary><b>Fun Story</b>(N 條)</summary>
1. **故事標題** — 一行摘要
...
</details>
<details>
<summary><b>Key Quote</b>(3 條)</summary>
1. "引用片段..." — 講者名稱
2. "引用片段..." — 講者名稱
...
</details>
請先輸出內容的背景摘要(作者、日期、核心論點),然後依序完成以下所有適用的輸出區塊:
以下是常見的錯誤模式,務必避免:
作者/講者在文章中引用他人的話時,不要把被引用者的觀點歸為作者本人的觀點。Key Quote 區塊中必須正確標註說話者。如果作者說「正如 Paul Graham 所言:...」,這是 Paul Graham 的話,不是作者的話。
Key Takeaway 不是段落摘要。每個 takeaway 必須回答「為什麼這很重要?」和「這改變了什麼?」。如果一個 takeaway 可以套用在任何類似主題的文章上,那就太泛了——需要更具體。
Call to Action、Best Practice、Unique Secret、Fun Story、Mistakes & Lessons Learned 是條件性區塊。不是每篇文章都有這五種內容。在輸出前先問自己:「原文中真的有明確的第一手實踐經驗嗎?」如果沒有,就不要硬生出 Best Practice 區塊。「原文中真的有作者親身承認的錯誤嗎?」如果沒有,就不要硬生出 Mistakes & Lessons Learned 區塊。寧可少輸出,也不要捏造。
影片/podcast 的字幕擷取可能因平台限制而失敗。如果 WebFetch 無法取得字幕,應改用可取得的文字內容(如文章描述、評論區摘要),並在筆記開頭註明「字幕無法擷取,以下基於可取得的文字內容」。不要因為字幕失敗就整個流程失敗。
所有輸出使用繁體中文(zh-TW)。原文引用保留原語言,並附上繁體中文翻譯。
development
撰寫與執行測試。Use when the user wants to write tests, add test coverage, or run existing tests for specific code.
development
技術債掃描。Use when the user wants to scan for technical debt, code smells, or quality issues in the codebase.
development
Code Review。Use when the user asks to review code changes, check code quality, or wants a thorough review before committing/merging.
development
安全重構。Use when the user wants to refactor code safely with a plan-first approach.