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

簡単な回答

ホスト型APIで文字起こしを取得し、LangChainのtext splitterでチャンクに分割し、各チャンックを要約してから、それらの要約を1つの最終要約にまとめる - 5分の動画だけでなく3時間の動画でも機能し続ける、同じmap-reduceパターンです。
01

LangChainをインストール

このチュートリアルは現在のLangChain JSのパッケージ分割を使います - コアプリミティブ、OpenAI連携、text splitterはそれぞれ独自のパッケージにあります:

npm install langchain @langchain/core @langchain/openai @langchain/textsplitters
02

文字起こしを取得する

ダッシュボードからキーを取得し(100無料クレジット、カード不要)、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は完全なプレーンテキストの文字起こしで、word_countはその長さです - 短い動画ではチャンク分割のステップを完全にスキップするかどうかの判断に使えます。

03

文字起こしをチャンクに分割する

長い文字起こしは、1つのプロンプトでLLMに送るのに快適な量を簡単に超えてしまうので、まず分割します。RecursiveCharacterTextSplitterは、段落、次に文、次に単語の順で区切ろうとするため、文の途中で切れることなくチャンクが読みやすいまま保たれます:

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は、あるチャンクの終わりの文脈を少しだけ次のチャンクの始めにも残すので、境界で分かれた文がどちらのチャンクからも失われません。

04

各チャンックを要約する

ChatPromptTemplate + モデル + StringOutputParserをパイプでつなぐ方法(LangChainの表現言語、LCEL)が、チェーンを構築する現在の安定した方法です - 各チャンクは並行してそれぞれ短い要約を得ます:

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 }))
);

Promise.allで並行実行することはレイテンシにとって重要です:10個のチャンクの文字起こしを1つずつ要約すると、10個すべてを同時に要約するのに比べて10倍の時間がかかります。

05

チャンクの要約を1つにまとめる

チャンクの要約は今や1つのプロンプトに一緒に収まるほど短いので、2つ目のチェーンでそれらを最終結果にまとめます:

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 });

この2段階の構造(まずチャンクを要約し、次に要約を要約する)は、LangChain自体のmap-reduceパターンが内部で行っていることそのものです - 古い形式のヘルパーチェーンを使う代わりにここで明示的に書いているのは、要約チェーンのヘルパーAPIがLangChainのバージョン間で変わってきたため、シンプルなLCELプリミティブの方が構築する土台として安定しているからです。

06

自分でスクレイピングする代わりにAPIから文字起こしを取得する理由

上記の文字起こし取得ステップは、このパイプラインの中で本番環境になると本当に難しくなる唯一の部分です - 自前でホストするスクレイピングライブラリは、クラウドサーバーにデプロイした途端にブロックされることがよくあります。ホスト型のYouTube文字起こしAPIは、まさにこのステップを機能させ続けるために作られており、パイプラインの残りの部分はそれを気にする必要がありません。

完全なエンドポイントリファレンス、認証、レート制限はAPIドキュメントにあります。これを最初から最後まで試すには、ダッシュボードから100無料クレジット付きのキーを取得してください。

LangChain要約ツールのFAQ

Q01

短い動画もチャンクに分割する必要がありますか?

必ずしもそうではありません - まず文字起こしレスポンスのword_countを確認してください。10分の動画の文字起こしは通常、最新のLLMの単一プロンプトが扱える量を十分下回るので、チャンク分割・結合のステップを完全に飛ばして1回の要約呼び出しに直接進めます。

Q02

固定文字数での分割ではなくRecursiveCharacterTextSplitterを使う理由は?

固定分割は文字数がちょうど来たところで切ってしまい、文や単語の途中になる可能性があります。RecursiveCharacterTextSplitterはまず段落の区切り、次に文、次に単語を試し、どうしても仕方ない場合にのみ強制的に切ります - そのためチャンクはモデルが要約するのに一貫性を保ちます。

Q03

OpenAI以外のLLMプロバイダーを使えますか?

はい - LangChainのチャットモデルクラスは同じインターフェースを共有しているため、ChatOpenAIを別のプロバイダーのLangChain連携(Anthropic、Googleなど)に差し替えても、パイプラインの他の部分は変わりません。

Q04

LLMChainを使う代わりにプロンプト、モデル、出力パーサーをパイプでつなぐのはなぜですか?

LLMChainはLangChainの古いチェーン構築APIです。パイプ/LCELスタイル(prompt.pipe(model).pipe(parser))が現在推奨されているパターンで、より予測可能に組み合わせられ、LangChainの新しいドキュメントもこれを基に構築されています。

Q05

これを実行するコストはどのくらいですか?

コストは2つあります:LLM呼び出し(チャンクごとに1回、さらに結合に1回 - モデルプロバイダーが課金)と、APIからの文字起こし取得ごとに1クレジットです。テスト中の取得側は100無料クレジットでカバーされます。

Q06

動画に文字起こしが全くない場合はどうなりますか?

文字起こしエンドポイントは空の文字列ではなく、明確なエラーコード(TRANSCRIPT_DISABLEDまたはTRANSCRIPT_NOT_FOUND)を返します - text splitterに何かを渡す前にsuccess: falseを確認してください。空の文字起こしを要約するとLLM呼び出しが無駄になります。

関連記事