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
Réponse rapide
Installer LangChain
Ce tutoriel utilise la répartition actuelle des paquets LangChain JS - les primitives du cœur, l'intégration OpenAI et les text splitters vivent chacun dans leur propre paquet :
npm install langchain @langchain/core @langchain/openai @langchain/textsplittersRécupérer la transcription
Obtenez une clé depuis le tableau de bord (100 crédits gratuits, sans carte), puis appelez le endpoint de transcription depuis un route handler 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 est la transcription complète en texte brut et word_count sa longueur - utile pour décider si l'étape de découpage est même nécessaire sur une vidéo courte.
Découper la transcription en morceaux
Une longue transcription peut facilement dépasser ce qu'il est confortable d'envoyer à un LLM en un seul prompt, découpez-la donc d'abord. RecursiveCharacterTextSplitter essaie de couper au niveau du paragraphe, puis de la phrase, puis du mot, dans cet ordre, pour que les morceaux restent lisibles plutôt que coupés en plein milieu d'une phrase :
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 conserve un peu de contexte de la fin d'un morceau au début du suivant, pour qu'une phrase coupée à la frontière ne soit perdue ni pour l'un ni pour l'autre.
Résumer chaque morceau
ChatPromptTemplate + un modèle + StringOutputParser enchaînés (le langage d'expression de LangChain, LCEL) est la façon actuelle et stable de construire une chaîne - chaque morceau reçoit son propre résumé court, en parallèle :
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 }))
);Les exécuter en parallèle avec Promise.all compte pour la latence : une transcription de 10 morceaux résumée un par un prend 10 fois plus de temps que de les résumer tous en même temps.
Combiner les résumés des morceaux en un seul
Les résumés des morceaux sont maintenant assez courts pour tenir ensemble dans un seul prompt, donc une seconde chaîne les combine dans le résultat 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 });Cette structure en deux passes (résumer les morceaux, puis résumer les résumés) est exactement ce que fait en coulisses le propre schéma map-reduce de LangChain - écrit ici explicitement plutôt que d'utiliser une chaîne utilitaire historique, car les API des chaînes de résumé ont changé d'une version de LangChain à l'autre, et les primitives LCEL simples sont une base plus stable sur laquelle construire.
Pourquoi récupérer la transcription via une API plutôt que de la scraper soi-même
L'étape de récupération de la transcription ci-dessus est la seule partie de ce pipeline qui devient vraiment plus difficile en production - les bibliothèques de scraping auto-hébergées se font souvent bloquer une fois déployées sur un serveur cloud. Une API de Transcriptions YouTube hébergée est conçue spécifiquement pour que cette étape continue de fonctionner, sans que le reste du pipeline ait à s'en soucier.
La référence complète des endpoints, l'authentification et les limites de débit sont dans la documentation de l'API. Obtenez une clé avec 100 crédits gratuits depuis le tableau de bord pour tester ça de bout en bout.
FAQ du résumeur LangChain
Dois-je aussi découper les vidéos courtes en morceaux ?
Pas nécessairement - vérifiez d'abord word_count dans la réponse de transcription. La transcription d'une vidéo de 10 minutes tient généralement largement dans un seul prompt d'un LLM moderne, vous pouvez donc passer directement à un seul appel de résumé et sauter entièrement les étapes de découpage/combinaison.
Pourquoi RecursiveCharacterTextSplitter plutôt qu'un découpage fixe par caractères ?
Un découpage fixe coupe où tombe le compte de caractères, potentiellement en plein milieu d'une phrase ou d'un mot. RecursiveCharacterTextSplitter essaie d'abord les sauts de paragraphe, puis les phrases, puis les mots, ne recourant à une coupe brute qu'en dernier recours - les morceaux restent donc cohérents pour que le modèle les résume.
Puis-je utiliser un autre fournisseur de LLM qu'OpenAI ?
Oui - les classes de chat model de LangChain partagent la même interface, donc remplacer ChatOpenAI par l'intégration LangChain d'un autre fournisseur (Anthropic, Google, etc.) ne change rien d'autre dans le pipeline.
Pourquoi enchaîner un prompt, un modèle et un output parser plutôt que d'utiliser LLMChain ?
LLMChain est l'ancienne API de construction de chaînes de LangChain. Le style enchaîné/LCEL (prompt.pipe(model).pipe(parser)) est le modèle actuellement recommandé - il se compose de façon plus prévisible et c'est sur cela que se base la documentation la plus récente de LangChain.
Combien coûte l'exécution de tout ça ?
Deux coûts : les appels au LLM (un par morceau, plus un pour combiner - facturés par votre fournisseur de modèle), et 1 crédit par récupération de transcription via l'API. 100 crédits gratuits couvrent le côté récupération pendant les tests.
Que se passe-t-il si la vidéo n'a aucune transcription ?
Le endpoint de transcription renvoie un code d'erreur clair (TRANSCRIPT_DISABLED ou TRANSCRIPT_NOT_FOUND) plutôt qu'une chaîne vide - vérifiez success: false avant de transmettre quoi que ce soit au text splitter, car résumer une transcription vide gaspille un appel LLM pour rien.
À lire aussi
- 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 vs TranscriptAPI
- GetYouTubeTranscript vs youtubetotranscript.com
- GetYouTubeTranscript vs youtube-transcript.io
- GetYouTubeTranscript vs NoteGPT