用LangGraph协调多阶段AI管道,将YouTube视频自动转为结构化Markdown文章,含转录/规划/写作/SEO优化四个独立阶段,配合Gemini Flash-Lite和Llama 70B模型分工。
Meta Description: How I built VtoB, a full-stack AI application that converts YouTube videos into structured, SEO-ready Markdown articles using LangGraph, Gemini, Groq, and FastAPI.
Writing a good technical article from a long YouTube video is a surprisingly repetitive workflow:
watch → take notes → organize → write → edit → optimize.
I built VtoB to automate that workflow.
The idea is simple: paste a YouTube URL and get a structured Markdown article generated through a multi-stage AI pipeline.
Multi-stage generation: VtoB separates transcription, planning, writing, and SEO refinement into independent pipeline stages.
LangGraph orchestration: The backend uses a StateGraph to pass shared state between processing nodes.
Model specialization: Gemini 3.1 Flash-Lite handles structure and refinement, while Llama 3.3 70B handles long-form drafting.
Full-stack workflow: A Next.js frontend communicates with a FastAPI backend and renders the final Markdown with copy and download actions.
The system has two main layers:
Next.js 16 Frontend
|
| POST /generate
v
FastAPI Backend
|
v
LangGraph StateGraph
|
+--> Fetch Transcript
|
+--> Generate Outline
|
+--> Write Draft
|
+--> SEO Refine
|
v
Final Markdown
The frontend uses Next.js 16.3.1, React 19, TypeScript, Tailwind CSS 4, Motion, GSAP, OGL, and react-markdown. The backend is built with FastAPI, LangGraph, LangChain, Gemini, Groq, Pydantic, and youtube-transcript-api. ([GitHub][2])

The main design decision was to avoid treating the entire task as one giant LLM prompt.
Instead, VtoB models the workflow as a graph with four explicit nodes:
START
|
v
Fetch Transcript
|
v
Generate Outline
|
v
Write Draft
|
v
SEO Refine
|
v
END
The graph is compiled with LangGraph's StateGraph, and each node reads from and writes to a shared BlogState. ([GitHub][1])
class BlogState(TypedDict):
video_url: str
video_id: str
transcript: Optional[str]
outline: Optional[str]
blog_draft: Optional[str]
seo_blog: Optional[str]
This makes each stage independently understandable and easier to modify.
Stage 1: Extracting the Transcript
The first node extracts the YouTube video ID from either a normal YouTube URL or a youtu.be URL.
api = YouTubeTranscriptApi()
transcript_list = api.fetch(video_id)
transcript_text = " ".join(
[item.text for item in transcript_list]
)
The transcript is then stored in the graph state for the next stage. An empty transcript raises an error instead of allowing the pipeline to continue with invalid input. ([GitHub][3])
Stage 2: Turning a Transcript into an Outline
A transcript is not automatically a good article.
Spoken content contains repetition, tangents, and loosely connected ideas, so VtoB first sends the transcript to Gemini 3.1 Flash-Lite for structural planning.
The prompt specifically asks the model to:
Reorganize the spoken content into a coherent narrative
Target technical developers
Create Markdown heading hierarchy
Attach factual notes to each section
This means the writing model doesn't have to figure out the article structure and the prose simultaneously. ([GitHub][1])
Raw Transcript
|
v
Gemini 3.1 Flash-Lite
|
v
Structured Outline
Stage 3: Writing the Article
Once the structure exists, VtoB sends the outline plus a transcript excerpt to Llama 3.3 70B through Groq.
The implementation deliberately limits the transcript context to the first 8,000 characters as a token-safety buffer.
transcript_excerpt = state["transcript"][:8000]
The writer is instructed to produce GitHub-Flavored Markdown, maintain proper heading structure, use Markdown code blocks, and avoid referring to the source material as a "video" inside the generated article. ([GitHub][1])
Transcript
|
+----> Outline
|
v
Llama 3.3 70B
|
v
Technical Draft
The important architectural idea here is model specialization:
Gemini plans. Llama writes.
Stage 4: SEO Refinement
The final node takes the generated draft and sends it back to Gemini 3.1 Flash-Lite for formatting and SEO refinement.
The formatter enforces things such as:
# Title
> Meta Description
## Key Takeaways
## Section
### Subsection
It also ensures consistent paragraph spacing and Markdown structure. ([GitHub][1])
This gives the pipeline a final quality-control stage rather than returning the first generated draft directly.
The entire pipeline is exposed through a single endpoint:
POST /generate
Content-Type: application/json
{
"video_url": "https://www.youtube.com/watch?v=..."
}
The backend returns the intermediate and final artifacts:
{
"video_id": "...",
"transcript": "...",
"outline": "...",
"blog_draft": "...",
"seo_blog": "..."
}
That is useful during development because the system exposes more than just the final answer. You can inspect each stage independently and see where generation quality changes. ([GitHub][1])
Building the Frontend
The frontend keeps the interaction deliberately simple.
The user enters a YouTube URL and is redirected to the generation page with the URL passed as a query parameter.
The generation page then calls:
fetch("http://127.0.0.1:8000/generate", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ video_url: videoUrl }),
});
The UI also generates the YouTube thumbnail directly from the extracted video ID and displays the final response as rendered Markdown. ([GitHub][3])

The generated article isn't just displayed on screen.
The frontend supports:
Copying the final Markdown to the clipboard
Downloading the article as a .md file
Rendering the Markdown directly in the browser
The downloaded filename is generated from the article title, making the output immediately usable in another editor or publishing workflow. ([GitHub][3])
The current backend dependency set confirms FastAPI, LangChain, LangGraph, Gemini integration, Groq integration, Pydantic, and youtube-transcript-api.
The interesting part of this project wasn't generating text with an LLM.
It was designing the pipeline around the LLM.
A single prompt can generate an article, but separating the workflow into:
Extraction
↓
Planning
↓
Generation
↓
Refinement
makes the system easier to reason about, debug, and extend.
For example, the outline model can be replaced without touching the writing node. The SEO stage can be modified independently. The frontend can inspect intermediate outputs without changing the graph itself.
That separation is what makes VtoB feel more like an actual application than a wrapper around an LLM API.
Some natural extensions would be:
Support for videos without available captions using an audio transcription model
Better long-video handling through transcript chunking and hierarchical summarization
Persistent job tracking for asynchronous generation
User accounts and article history
Direct publishing integrations for platforms such as Dev.to
Evaluation of generated articles against the source transcript for factual consistency
VtoB started with a simple idea: turn a YouTube URL into a usable technical article.
The implementation ended up being a small exercise in AI system design:
YouTube
↓
Transcript
↓
Gemini
↓
Outline
↓
Llama
↓
Draft
↓
Gemini
↓
SEO Markdown
The biggest takeaway for me was that useful AI applications are rarely just about the model.
They are about how you structure the work around the model.