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
Respuesta rápida
Instala LangChain
Este tutorial usa la división actual de paquetes de LangChain JS - las primitivas del núcleo, la integración con OpenAI y los text splitters viven cada uno en su propio paquete:
npm install langchain @langchain/core @langchain/openai @langchain/textsplittersObtén la transcripción
Consigue una clave desde el panel (100 créditos gratis, sin tarjeta), y luego llama al endpoint de transcripción desde un route handler de 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 es la transcripción completa en texto plano y word_count es su longitud - útil para decidir si saltarte por completo el paso de fragmentación en un video corto.
Divide la transcripción en fragmentos
Una transcripción larga puede superar fácilmente lo cómodo de enviar a un LLM en un solo prompt, así que divídela primero. RecursiveCharacterTextSplitter intenta cortar por párrafo, luego por oración, luego por palabra, en ese orden, para que los fragmentos sigan siendo legibles en vez de cortar a mitad de una oración:
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 conserva un poco de contexto del final de un fragmento al inicio del siguiente, para que una oración partida en el límite no se pierda en ninguno de los dos.
Resume cada fragmento
ChatPromptTemplate + un modelo + StringOutputParser encadenados (el lenguaje de expresión de LangChain, LCEL) es la forma actual y estable de construir una cadena - cada fragmento obtiene su propio resumen corto en paralelo:
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 }))
);Ejecutarlos en paralelo con Promise.all importa para la latencia: una transcripción de 10 fragmentos resumida uno por uno tarda 10 veces más que resumir los 10 a la vez.
Combina los resúmenes de los fragmentos en uno solo
Los resúmenes de los fragmentos ya son lo bastante cortos para caber juntos en un solo prompt, así que una segunda cadena los combina en el resultado final:
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 });Esta estructura de dos pasadas (resumir fragmentos, luego resumir los resúmenes) es lo que hace por dentro el propio patrón map-reduce de LangChain - escrito aquí explícitamente en vez de usar una cadena auxiliar heredada, ya que las APIs de las cadenas de resumen han cambiado entre versiones de LangChain y las primitivas LCEL simples son una base más estable sobre la cual construir.
Por qué obtener la transcripción de una API en vez de scrapearla tú mismo
El paso de obtener la transcripción de arriba es la única parte de este pipeline que se vuelve genuinamente más difícil en producción - las librerías de scraping autoalojadas suelen bloquearse al desplegarse en un servidor en la nube. Una API de Transcripciones de YouTube alojada está construida específicamente para mantener ese paso funcionando, para que el resto de este pipeline no tenga que preocuparse por eso.
La referencia completa de endpoints, autenticación y límites de velocidad está en la documentación de la API. Consigue una clave con 100 créditos gratis desde el panel para probar esto de principio a fin.
Preguntas frecuentes del resumidor con LangChain
¿También necesito fragmentar videos cortos?
No necesariamente - primero revisa word_count en la respuesta de la transcripción. La transcripción de un video de 10 minutos suele estar muy por debajo de lo que aguanta un solo prompt de un LLM moderno, así que puedes ir directo a una sola llamada de resumen y saltarte por completo los pasos de fragmentación/combinación.
¿Por qué RecursiveCharacterTextSplitter en vez de un corte fijo por caracteres?
Un corte fijo corta donde caiga el conteo de caracteres, posiblemente a mitad de una oración o palabra. RecursiveCharacterTextSplitter intenta primero los saltos de párrafo, luego oraciones, luego palabras, y solo recurre a un corte duro si no le queda otra - así los fragmentos siguen siendo coherentes para que el modelo los resuma.
¿Puedo usar un proveedor de LLM distinto a OpenAI?
Sí - las clases de modelo de chat de LangChain comparten la misma interfaz, así que cambiar ChatOpenAI por la integración de LangChain de otro proveedor (Anthropic, Google, etc.) no cambia nada más en el pipeline.
¿Por qué encadenar un prompt, un modelo y un output parser en vez de usar LLMChain?
LLMChain es la API más antigua de LangChain para construir cadenas. El estilo encadenado/LCEL (prompt.pipe(model).pipe(parser)) es el patrón recomendado actualmente - se compone de forma más predecible y es sobre lo que se construye la documentación más reciente de LangChain.
¿Cuánto cuesta ejecutar esto?
Dos costos: las llamadas al LLM (una por fragmento, más una para combinar - facturadas por tu proveedor de modelo), y 1 crédito por cada obtención de transcripción desde la API. 100 créditos gratis cubren el lado de la obtención mientras pruebas.
¿Qué pasa si el video no tiene ninguna transcripción?
El endpoint de transcripción devuelve un código de error claro (TRANSCRIPT_DISABLED o TRANSCRIPT_NOT_FOUND) en vez de una cadena vacía - revisa success: false antes de pasarle nada al text splitter, ya que resumir una transcripción vacía desperdicia una llamada al LLM para nada.
Relacionado
- 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 frente a TranscriptAPI
- GetYouTubeTranscript frente a youtubetotranscript.com
- GetYouTubeTranscript frente a youtube-transcript.io
- GetYouTubeTranscript vs NoteGPT