Build an AI YouTube Video Summarizer with LangChain and Next.js
A working YouTube summarizer built with LangChain and Next.js: fetch the transcript, chunk it with a text splitter, summarize each chunk, then combine the results into one final summary - full code for every step.
00:08:00 · SEP 26, 2026
Trả lời nhanh
Cài đặt LangChain
Hướng dẫn này dùng cách chia gói hiện tại của LangChain JS - các thành phần lõi, tích hợp OpenAI, và text splitter mỗi thứ nằm trong gói riêng của nó:
npm install langchain @langchain/core @langchain/openai @langchain/textsplittersLấy bản chép lời
Lấy một khóa từ trang quản trị (100 tín dụng miễn phí, không cần thẻ), rồi gọi endpoint chép lời từ một route handler của Next.js:
// app/api/summarize/route.ts
import { NextResponse } from 'next/server';
async function fetchTranscript(videoId: string) {
const res = await fetch(
`https://getyoutubetranscript.com/api/v1/transcript?v=${videoId}`,
{ headers: { Authorization: `Bearer ${process.env.GETYOUTUBETRANSCRIPT_API_KEY}` } }
);
const json = await res.json();
if (!json.success) throw new Error(json.message);
// json.data.transcript is the full plain-text transcript,
// json.data.word_count is its length in words.
return json.data as { transcript: string; word_count: number; title: string };
}transcript là toàn bộ bản chép lời dạng văn bản thuần và word_count là độ dài của nó - hữu ích để quyết định có nên bỏ qua hoàn toàn bước chia nhỏ với video ngắn hay không.
Chia bản chép lời thành các phần
Một bản chép lời dài có thể dễ dàng vượt quá mức thoải mái để gửi cho LLM trong một prompt duy nhất, nên hãy chia nhỏ trước. RecursiveCharacterTextSplitter cố gắng ngắt tại đoạn văn, rồi câu, rồi từ, theo thứ tự đó, để các phần vẫn dễ đọc thay vì cắt giữa câu:
import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 4000,
chunkOverlap: 200,
});
const chunks = await splitter.splitText(transcript);
// A 20-minute video is usually 1-2 chunks; a 2-hour one might be 8-10.chunkOverlap giữ lại một ít ngữ cảnh từ cuối một phần sang đầu phần tiếp theo, để một câu bị chia tại ranh giới không bị mất ở cả hai phần.
Tóm tắt từng phần
ChatPromptTemplate + một model + StringOutputParser được nối với nhau (ngôn ngữ biểu thức của LangChain, LCEL) là cách hiện tại, ổn định để xây dựng một chain - mỗi phần nhận được bản tóm tắt ngắn riêng, chạy song song:
import { ChatOpenAI } from '@langchain/openai';
import { ChatPromptTemplate } from '@langchain/core/prompts';
import { StringOutputParser } from '@langchain/core/output_parsers';
const model = new ChatOpenAI({ model: 'gpt-4.1-mini', temperature: 0 });
const chunkPrompt = ChatPromptTemplate.fromTemplate(
'Summarize this part of a video transcript in 3-4 sentences, keeping any concrete facts, numbers, or names:\n\n{chunk}'
);
const chunkChain = chunkPrompt.pipe(model).pipe(new StringOutputParser());
const chunkSummaries = await Promise.all(
chunks.map((chunk) => chunkChain.invoke({ chunk }))
);Chạy song song với Promise.all quan trọng đối với độ trễ: một bản chép lời gồm 10 phần được tóm tắt lần lượt sẽ mất thời gian gấp 10 lần so với tóm tắt cả 10 phần cùng lúc.
Gộp các bản tóm tắt phần lại thành một
Các bản tóm tắt phần giờ đã đủ ngắn để cùng vừa trong một prompt, nên một chain thứ hai sẽ gộp chúng thành kết quả cuối cùng:
const finalPrompt = ChatPromptTemplate.fromTemplate(
'These are summaries of consecutive parts of the same video transcript, titled "{title}".\n' +
'Combine them into one coherent summary (a short paragraph, then 3-5 key takeaways as bullet points):\n\n{summaries}'
);
const finalChain = finalPrompt.pipe(model).pipe(new StringOutputParser());
const summary = await finalChain.invoke({
title,
summaries: chunkSummaries.join('\n\n'),
});
return NextResponse.json({ summary });Cấu trúc hai bước này (tóm tắt các phần, rồi tóm tắt các bản tóm tắt) chính xác là những gì mô hình map-reduce riêng của LangChain làm bên dưới - được viết tường minh ở đây thay vì dùng một chain hỗ trợ cũ, vì các API của summarization chain hỗ trợ đã thay đổi qua các phiên bản LangChain, và các thành phần LCEL thuần là nền tảng ổn định hơn để xây dựng.
Vì sao lấy bản chép lời từ API thay vì tự scrape
Bước lấy bản chép lời ở trên là phần duy nhất của pipeline này thực sự trở nên khó khăn hơn trong môi trường production - các thư viện scraping tự lưu trữ thường bị chặn ngay khi triển khai lên server cloud. Một API Chép Lời YouTube được lưu trữ được xây dựng riêng để giữ cho bước đó luôn hoạt động, để phần còn lại của pipeline này không cần phải bận tâm.
Tài liệu tham khảo endpoint đầy đủ, xác thực, và giới hạn tốc độ có trong tài liệu API. Lấy một khóa với 100 tín dụng miễn phí từ trang quản trị để thử nghiệm toàn bộ quy trình.
Câu hỏi thường gặp về công cụ tóm tắt LangChain
Tôi có cần chia nhỏ cả video ngắn không?
Không nhất thiết - hãy kiểm tra word_count trong phản hồi bản chép lời trước. Bản chép lời của video 10 phút thường thấp hơn nhiều so với những gì một prompt LLM hiện đại có thể chứa, vì vậy bạn có thể đi thẳng đến một lần gọi tóm tắt duy nhất và bỏ qua hoàn toàn các bước chia nhỏ/gộp.
Tại sao dùng RecursiveCharacterTextSplitter thay vì chia theo số ký tự cố định?
Chia cố định cắt ở bất cứ đâu số ký tự rơi vào, có thể giữa câu hoặc giữa từ. RecursiveCharacterTextSplitter thử ngắt đoạn văn trước, rồi câu, rồi từ, chỉ dùng cách cắt cứng khi không còn lựa chọn nào khác - nhờ vậy các phần vẫn mạch lạc để model tóm tắt.
Tôi có thể dùng nhà cung cấp LLM khác thay vì OpenAI không?
Có - các lớp chat model của LangChain dùng chung một giao diện, nên thay ChatOpenAI bằng tích hợp LangChain của nhà cung cấp khác (Anthropic, Google, v.v.) không làm thay đổi gì khác trong pipeline.
Tại sao nối prompt, model và output parser thay vì dùng LLMChain?
LLMChain là API xây dựng chain cũ hơn của LangChain. Kiểu nối/LCEL (prompt.pipe(model).pipe(parser)) là mô hình được khuyến nghị hiện tại - nó kết hợp dễ dự đoán hơn và là nền tảng mà tài liệu mới hơn của LangChain xây dựng dựa trên đó.
Chạy cái này tốn bao nhiêu?
Có hai loại chi phí: các lệnh gọi LLM (một cho mỗi phần, cộng một để gộp - do nhà cung cấp model của bạn tính phí), và 1 tín dụng cho mỗi lần lấy bản chép lời từ API. 100 tín dụng miễn phí đủ để trang trải phần lấy dữ liệu trong khi thử nghiệm.
Điều gì xảy ra nếu video hoàn toàn không có bản chép lời?
Endpoint chép lời trả về một mã lỗi rõ ràng (TRANSCRIPT_DISABLED hoặc TRANSCRIPT_NOT_FOUND) thay vì một chuỗi rỗng - hãy kiểm tra success: false trước khi đưa bất cứ thứ gì cho text splitter, vì tóm tắt một bản chép lời rỗng sẽ lãng phí một lệnh gọi LLM vô ích.
Liên quan
- YouTube API Quota Exceeded: Causes and Fixes
- YouTube Transcript API Rate Limit: What It Is and How to Handle 429s
- YouTube Transcript MCP Server: Setup Guide for Claude and Other AI Tools
- YouTube Transcripts in n8n: HTTP Request Workflow Guide
- Migrating from Supadata: A Field Guide
- How to Get YouTube Transcripts in Python
- Migrating from TranscriptAPI.com: A Field Guide
- GetYouTubeTranscript so với TranscriptAPI
- GetYouTubeTranscript so với youtubetotranscript.com
- GetYouTubeTranscript so với youtube-transcript.io
- GetYouTubeTranscript vs NoteGPT