Nội dung
Biến video YouTube thành bài viết có thể xuất bản
Lấy bản ghi có timestamp, chia thành đoạn dễ đọc, lập dàn ý và bản nháp bằng model bạn kiểm soát, rồi để kết quả trong LiveDoc chờ biên tập.
Sao chép prompt
Thay các trường trong ngoặc vuông rồi dán vào Claude Code, Codex hoặc AI có quyền truy cập terminal. Nó cài skill Felo, hỏi trước khi dùng credit và chạy quy trình.
Chuyển video này thành bài viết có thể công bố: [URL YouTube hoặc ID video]. Độc giả: [người đọc]. Giọng điệu: [phong cách ấn phẩm]. Độ dài mục tiêu: [800–1200 từ] bằng [ngôn ngữ]. Xử lý nguồn: giữ tiêu đề, kênh và URL video. Chỉ trích đoạn ngắn, kèm mốc thời gian. Tạo: 1. Tiêu đề tạm. 2. Đoạn mở đầu. 3. Các mục với đoạn ngắn. 4. Hai hoặc ba trích dẫn có mốc thời gian. 5. Những gì video không bao phủ. 6. Danh sách nguồn gồm video và các trang được liên kết. Quy tắc: - Không sao chép toàn bộ bản ghi. Tóm tắt và trích ngắn. - Mọi nhận định thực tế từ video cần mốc thời gian; nhận định từ trang liên kết cần URL. - Ghi “Chưa xác minh” cho mọi điều bạn không kiểm chứng được. - Hỏi trước khi tiêu tín dụng cho bản ghi hoặc trích xuất trang. - Không công bố, lên lịch hay gửi gì. - Ghi kết quả vào ./video-article.md và tóm tắt trong chat.
Bản sao cũng gồm các bước cài đặt và quy tắc an toàn.
Bạn nhận được gì
Kết quả mẫu của một lần chạy. Không phải tạo trực tiếp.
Bài nói 40 phút về agent thực sự nói gì
Đoạn mở
Bản demo ấn tượng; phần hữu ích là xử lý lỗi.
Tuyên bố mọi người trích
> “Agent không thông minh hơn. Chúng ta chỉ ngừng cho nó thử lại mà không có ngân sách.” — [12:40]
Video không đề cập
Chi phí mỗi nhiệm vụ thành công và điều gì xảy ra khi nguồn truy xuất sai.
Nguồn
- Video: https://www.youtube.com/watch?v=...
- Benchmark liên kết: https://example.com/benchmark
Các lệnh gọi chính xác
Dành cho lập trình viên: cùng quy trình dưới dạng mã, theo thứ tự chạy.
Hiện lệnh gọi API thật
Lấy bản ghi có timestamp
Dùng YouTube Subtitling lấy phụ đề ngôn ngữ đích, giữ thời điểm bắt đầu và độ dài mỗi dòng.
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; }Kết quả mẫu
{ "title": "How we rebuilt onboarding", "contents": [ { "text": "Welcome back to the channel.", "start": 0.32, "duration": 4.1 } ] }Chia thành đoạn dễ đọc
Chia theo chủ đề, bỏ từ đệm và giữ timestamp.
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"); }Kết quả mẫu
[00:00] Welcome back to the channel. Today we are talking about onboarding. [01:00] The first thing we changed was the welcome screen.
Lấy nguồn được nhắc
Dùng Web Fetch đọc các trang được nêu trong video và thêm liên kết, dữ kiện.
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 }; }), ); }Kết quả mẫu
[ { "url": "https://example.com/reference", "content": "# Reference\n\nExtracted page text…" } ]Lập dàn ý rồi viết bản nháp
Xin dàn ý từ Model API trước, rồi viết bài theo dàn ý với trích ngắn và timestamp.
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, }; }Kết quả mẫu
{ "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 } }Để trong LiveDoc chờ biên tập
Lưu bản nháp và trích dẫn vào LiveDoc, chuyển cho biên tập viên sửa và duyệt.
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; }Kết quả mẫu
{ "short_id": "PvyKouzJirXjFdst4uKRK3" }
Bao gồm
- Bản ghi YouTube có timestamp
- Trang được video nhắc đến ở dạng Markdown
- Dàn ý và bản nháp từ Model API
- LiveDoc với bản nháp để biên tập
Không làm gì
- Không chép toàn bộ bản ghi; chỉ trích ngắn và viết lại
- Video cần có phụ đề
- Kiểm tra quyền và giới hạn trích dẫn trước khi xuất bản
- Model làm dàn ý và bản nháp; quyết định cuối thuộc biên tập viên
- Không tự xuất bản hay dịch
Câu hỏi
Video có cần phụ đề không?
Có. Quy trình bắt đầu từ phụ đề; nếu thiếu, nó dừng thay vì đoán điều đã nói.
Có biến podcast thành bài được không?
Quy trình này dành cho YouTube. Với podcast, tạo bản ghi trước rồi dùng cùng quy tắc viết.
Có thể viết bằng ngôn ngữ khác không?
Có. Nêu ngôn ngữ đích; trích dẫn giữ nguyên bản gốc kèm bản dịch khi cần.
Ai viết bài?
Agent AI nơi bạn dán prompt viết bản nháp; Felo cung cấp bản ghi, trang và không gian biên tập.
Có được đăng lại toàn bộ bản ghi không?
Không. Quy trình tạo bài mới với trích ngắn và không sao chép toàn bộ bản ghi.
Một lần chạy tốn bao nhiêu?
Bản ghi và trích xuất trang tính theo mức dùng; giá hiện tại ở trang giá và prompt hỏi duyệt trước khi chi.
Quy trình liên quan
Xuất bản bản tin AI hằng ngày mà nhóm bạn thực sự đọc
Lấy bản tóm tắt tin có nguồn, thêm thảo luận của người thực hành trên X, lấy một bản ghi video, dựng bản tin Markdown và lưu vào LiveDoc.
Mở quy trìnhVăn phòngBiến trang nghiên cứu thành bài thuyết trình
Trích xuất trang, lưu làm bối cảnh LiveDoc, để PPT Task API dựng deck và hỏi cho đến khi có liên kết hoàn chỉnh.
Mở quy trìnhHỗ trợTrả lời câu hỏi hỗ trợ từ tài liệu của chính bạn
Tạo LiveDoc, tải trung tâm trợ giúp và runbook nội bộ, lấy các đoạn trả lời ticket và để model chỉ trả lời từ bằng chứng đó.
Mở quy trìnhTùy biến
Cùng công thức, điều chỉnh theo cách bạn thực sự triển khai.
Chỉ trích dẫn có timestamp
Không viết bài; giao danh sách trích dẫn kiểm tra được để tái sử dụng.
Bản newsletter trước
Rút bài thành bản ngắn, trò chuyện hơn cho newsletter.
Xử lý kênh theo lô
Lặp các bước cho từng video và lưu LiveDoc riêng.
Đi tiếp
Các trang tham chiếu đằng sau công thức và nơi đi tiếp.