內容
把 YouTube 影片變成一篇可發佈的文章
拉取帶時間戳的轉錄,整理成可讀的段落,用你控制的模型列大綱並寫初稿,再把結果留在 LiveDoc 裡等編輯 review。
複製 prompt
把方括號裡的欄位替換掉,然後貼到 Claude Code、Codex 或任何能存取終端機的 AI。它會安裝 Felo skill、在花額度前詢問,並執行這套工作流程。
把這支影片變成一篇可發布的文章:[YouTube URL 或影片 ID]。 讀者:[讀者]。語氣:[媒體風格]。目標長度:[800–1200 字],語言:[語言]。 來源處理:保留影片標題、頻道和 URL。引用最多只取短片段,並附時間戳。 輸出: 1. 工作標題。 2. 導言。 3. 由短段落組成的章節。 4. 兩到三條附時間戳的引文。 5. 影片沒有涵蓋的內容。 6. 包含影片和所有連結頁面的來源清單。 規則: - 不要重現完整逐字稿。要總結並簡短引用。 - 影片中的每個事實主張都需要時間戳;連結頁面中的主張需要 URL。 - 無法核實的內容標示為「未核實」。 - 在消耗額度取得逐字稿或擷取頁面前先詢問。 - 不要發布、排程或傳送任何內容。 - 將結果寫入 ./video-article.md,並在對話中總結。
複製的內容也包含安裝步驟和安全規則。
你會得到什麼
一次執行的範例輸出,不是即時生成。
一場 40 分鐘代理演講到底說了什麼
導言
示範很令人印象深刻,但有用的是失敗處理。
大家引用最多的說法
> 「代理並沒有變聰明。我們只是不再讓它無預算重試。」 — [12:40]
影片沒有涵蓋的內容
每個成功任務的成本,以及檢索到的來源出錯時會發生什麼。
來源
- 影片:https://www.youtube.com/watch?v=...
- 連結的基準:https://example.com/benchmark
實際呼叫
給開發者:同一套工作流程的可複製程式碼,依執行順序排列。
展開實際 API 呼叫
拉取帶時間戳的轉錄
用 YouTube Subtitling 依目標語言拉取字幕,保留每行的開始時間和時長。
article.ts const BASE = "https://openapi.felo.ai"; const headers = { Authorization: `Bearer ${process.env.FELO_API_KEY}`, "Content-Type": "application/json", }; async function felo<T>(path: string, body?: unknown): Promise<T> { const res = await fetch(`${BASE}${path}`, { method: body ? "POST" : "GET", headers, body: body ? JSON.stringify(body) : undefined, }); if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`); return res.json() as Promise<T>; } type Transcript = { data: { title: string; contents: { text: string; start: number; duration: number }[]; }; }; export async function fetchTranscript(videoId: string, language = "en") { const query = new URLSearchParams({ video_code: videoId, language, with_time: "true", }); const { data } = await felo<Transcript>(`/v2/youtube/subtitling?${query}`); if (data.contents.length === 0) throw new Error("This video has no subtitles"); return data; }範例輸出
{ "title": "How we rebuilt onboarding", "contents": [ { "text": "Welcome back to the channel.", "start": 0.32, "duration": 4.1 } ] }整理成可讀的段落
依主題把轉錄切塊,去掉口頭填充詞,但保留時間戳。
article.ts const toClock = (seconds: number) => { const minutes = Math.floor(seconds / 60); const rest = Math.floor(seconds % 60); return `${String(minutes).padStart(2, "0")}:${String(rest).padStart(2, "0")}`; }; export function toBlocks( contents: Transcript["data"]["contents"], window = 60, ) { const grouped = new Map<number, string[]>(); for (const line of contents) { const bucket = Math.floor(line.start / window) * window; grouped.set(bucket, [...(grouped.get(bucket) ?? []), line.text.trim()]); } return [...grouped] .map(([start, lines]) => `[${toClock(start)}] ${lines.join(" ")}`) .join("\n\n"); }範例輸出
[00:00] Welcome back to the channel. Today we are talking about onboarding. [01:00] The first thing we changed was the welcome screen.
抓取影片提到的來源
用 Web Fetch 讀取影片裡點名的頁面,補上連結和事實。
article.ts type ExtractData = { data: { content: string } }; export async function fetchSources(urls: string[]) { return Promise.all( urls.slice(0, 5).map(async (url) => { const page = await felo<ExtractData>("/v2/web/extract", { url, output_format: "markdown", with_readability: true, }); return { url, content: page.data.content }; }), ); }範例輸出
[ { "url": "https://example.com/reference", "content": "# Reference\n\nExtracted page text…" } ]列大綱再寫初稿
用模型 API 先寫大綱,再依大綱寫文章,短引並標註時間戳。
article.ts const MODEL_API = "https://openapi.felo.ai/api/v1"; type Completion = { choices: { message: { content: string } }[]; usage: { prompt_tokens: number; completion_tokens: number; total_tokens: number }; }; async function complete(model: string, prompt: string): Promise<Completion> { const res = await fetch(`${MODEL_API}/chat/completions`, { method: "POST", headers, body: JSON.stringify({ model, messages: [{ role: "user", content: prompt }] }), }); if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`); return res.json() as Promise<Completion>; } export async function draftArticle(title: string, transcript: string) { const outline = await complete( "claude-haiku-5-5", "Outline a short article from this transcript. Return only headings.\n\n" + transcript, ); const article = await complete( "claude-sonnet-5-5", `Write the article "${title}" from the transcript. Follow the outline and keep [mm:ss] on direct quotes.\n\nOutline:\n${outline.choices[0].message.content}\n\nTranscript:\n${transcript}`, ); return { outline: outline.choices[0].message.content, article: article.choices[0].message.content, usage: article.usage, }; }範例輸出
{ "outline": "1. The problem\n2. What changed\n3. What we learned", "article": "## The problem\n\nWhen we…", "usage": { "prompt_tokens": 4120, "completion_tokens": 640, "total_tokens": 4760 } }放進 LiveDoc 等 review
把初稿和時間戳引語存進 LiveDoc,交給編輯修改和批准。
article.ts type LiveDocData = { data: { short_id: string } }; type ResourceData = { data: { id: string } }; export async function saveDraft( title: string, result: { outline: string; article: string }, ) { const doc = await felo<LiveDocData>("/v2/livedocs", { name: `Article draft: ${title}`, description: "Draft generated from a video transcript", }); await felo<ResourceData>(`/v2/livedocs/${doc.data.short_id}/resources/doc`, { title: "Draft", content: result.article, }); await felo<ResourceData>(`/v2/livedocs/${doc.data.short_id}/resources/doc`, { title: "Outline", content: result.outline, }); return doc.data.short_id; }範例輸出
{ "short_id": "PvyKouzJirXjFdst4uKRK3" }
包含什麼
- 帶時間戳的 YouTube 轉錄
- 影片提到的頁面,轉成 Markdown
- 由你的模型 API 產生的大綱和初稿
- 保存初稿、供編輯 review 的 LiveDoc
不做什麼
- 不能直接複製完整轉錄,只能短引並改寫
- 影片需要已有字幕
- 轉載前必須確認版權和引用範圍
- 模型只負責大綱和草稿,最終判斷在編輯
- 不自動發佈或翻譯成其他語言
常見問題
影片需要字幕嗎?
需要。工作流程從字幕開始;沒有字幕時會停下,而不是猜影片說了什麼。
可以把 Podcast 變成文章嗎?
這套工作流程針對 YouTube;Podcast 需要先準備轉錄,再走同樣的寫作規則。
可以寫成其他語言嗎?
可以。指定目標語言;引語保留原文,需要時附翻譯。
文章是誰寫的?
你貼上 prompt 的 AI agent 寫初稿,Felo 提供轉錄、頁面和 review 工作區。
可以轉載完整轉錄嗎?
不可以。工作流程只做新文章和短引,不複製完整轉錄。
一次要花多少?
轉錄和頁面擷取按用量計費;目前費率在價格頁面,prompt 會先請求確認。
相關工作流程
改成你的版本
同一套配方,依你實際的交付方式調整。
只做時間戳引語
不寫整篇,只輸出可核對的引語清單,適合二次創作。
先寫 newsletter 版本
把文章改成更短、更口語的 newsletter 版本。
批量處理一個頻道
對每個影片重複同一套步驟,並各自保存 LiveDoc。
繼續深入
這套配方背後的參考頁面,以及下一步可以看什麼。