How to get the chapter list from a downloaded youtube video
- Step 1Download with chapters embedded — Use
yt-dlp --embed-chapters <url>(MP4 or MKV). Without--embed-chapters, the chapters live only in the description text and won't be in the file's metadata — there'd be nothing for this tool to read. - Step 2Drop the downloaded file — Drag the resulting
.mp4or.mkvonto the tool. One file per run. Free tier handles up to 1 GB; a long video may need Pro (10 GB) or higher. - Step 3FFmpeg.wasm reads the embedded chapters — JAD runs
ffmpeg -i <file> -c copy -t 0 -f null -, parsing the container's chapter atoms without decoding the video. Quick even on a multi-hour download. - Step 4Each chapter becomes an object — The creator's
00:00 Intro-style markers become{ start, end, title }with times in seconds and titles verbatim (ornullif not embedded). - Step 5Download the JSON — Saves as
<filename>-chapters.jsonin the standard{ chapters: [...] }shape. - Step 6Rebuild the YouTube description timestamps — Map each chapter to
MM:SS Title. Ensure the first line reads00:00 …(YouTube's hard requirement) and you have at least three chapters each ≥ 10 seconds long, then paste into the description.
YouTube chapter rules vs what this tool gives you
The tool gives you raw seconds + titles; YouTube's description format has formatting rules you apply yourself.
| YouTube requirement | What this tool returns | What you do | Notes |
|---|---|---|---|
First timestamp must be 00:00 | start: 0 on the first chapter | Format as 00:00 | If the first start isn't 0, YouTube won't enable chapters |
| Minimum 3 chapters | Full array, however many | Check chapters.length >= 3 | Fewer than 3 → YouTube ignores the timestamps |
| Each chapter ≥ 10 seconds | end - start per chapter | Validate before pasting | Sub-10s segments break YouTube detection |
Format MM:SS Title or HH:MM:SS Title | start in seconds + title | Format seconds → timecode | You write the formatter (cookbook shows it) |
Will the download have embedded chapters?
Only --embed-chapters writes them into the file metadata.
| Download method | Chapters in file? | Titles? | Result here |
|---|---|---|---|
yt-dlp --embed-chapters | Yes | Yes | Full named chapter array |
yt-dlp (no flag) | No | n/a | Empty [] — chapters were only in the description |
| Browser-extension / site downloader | Usually no | n/a | Often empty [] |
| Re-encode that dropped metadata | No | n/a | Empty [] — re-download with the flag |
Cookbook
Real downloaded-video JSON and the YouTube description rebuild. Times in seconds; titles verbatim or null.
A yt-dlp download with the creator's chapters
--embed-chapters wrote the creator's description timestamps into the MP4. You get them straight back.
Input: tutorial.mp4 (yt-dlp --embed-chapters)
Output: tutorial-chapters.json
{
"chapters": [
{ "start": 0, "end": 42.0, "title": "Intro" },
{ "start": 42.0, "end": 360.0, "title": "Setup" },
{ "start": 360.0, "end": 905.0, "title": "Walkthrough" },
{ "start": 905.0, "end": 980.5, "title": "Wrap-up" }
]
}Rebuilding the 00:00 description timestamps
Format each start to MM:SS and prepend to the title. YouTube needs the first line at 00:00, 3+ chapters, each ≥ 10s.
const { chapters } = require('./tutorial-chapters.json');
const mmss = s => `${String(Math.floor(s/60)).padStart(2,'0')}:${String(Math.floor(s%60)).padStart(2,'0')}`;
console.log(chapters.map(c => `${mmss(c.start)} ${c.title ?? 'Chapter'}`).join('\n'));
// →
00:00 Intro
00:42 Setup
06:00 Walkthrough
15:05 Wrap-upA download with no embedded chapters
Downloaded without --embed-chapters, so the chapters stayed in the description text only. The file has none.
Input: clip.mp4 (yt-dlp, no flag)
Output: clip-chapters.json
{
"chapters": []
}
→ Re-download with --embed-chapters, or copy the
timestamps from the original description manually.Validating YouTube's chapter rules before pasting
Catch the common failures — first chapter not at 0, fewer than 3 chapters, or a sub-10-second segment — in code.
const { chapters } = require('./tutorial-chapters.json');
const ok = chapters.length >= 3
&& chapters[0].start === 0
&& chapters.every(c => (c.end - c.start) >= 10);
console.log(ok ? 'YouTube will enable chapters' : 'Fix: 00:00 start, 3+ chapters, each >=10s');Re-timing chapters after trimming the intro
If you cut N seconds off the front in a re-edit, shift every start by N and drop anything now before 0.
const { chapters } = require('./tutorial-chapters.json');
const cut = 42; // removed the 42s intro
const shifted = chapters
.map(c => ({ ...c, start: c.start - cut, end: c.end - cut }))
.filter(c => c.end > 0)
.map((c, i) => i === 0 ? { ...c, start: 0 } : c);
console.log(JSON.stringify(shifted, null, 2));Edge cases and what actually happens
Downloaded without --embed-chapters
Empty arrayReturns { "chapters": [] }. Without that flag, yt-dlp leaves the chapters in the description text only — they're never written to the file's metadata. Re-download with --embed-chapters, or copy the timestamps from the original description by hand.
First chapter doesn't start at 0
YouTube will rejectIf the embedded first chapter's start isn't 0, YouTube won't enable chapters when you paste the rebuilt description. The cookbook's re-time example forces the first start to 00:00; do that before pasting.
Fewer than 3 chapters
YouTube will rejectYouTube requires at least 3 chapters. A video the creator gave only 1–2 markers will read back as a 1–2 item array — valid JSON, but YouTube won't show chapters. There's nothing to fix in extraction; add markers at the source.
A chapter shorter than 10 seconds
YouTube will rejectYouTube needs each chapter ≥ 10 seconds. A sub-10s segment (end - start < 10) disables chapter detection for the whole video. Validate with the cookbook check before pasting.
Title has non-ASCII / emoji
PreservedCreator titles like 第1章 or Intro 🎬 round-trip verbatim as UTF-8 in the JSON, so they paste back into the description intact in a UTF-8 context.
You dropped a YouTube URL, not a file
Not supportedThis tool reads a downloaded file's metadata — it doesn't fetch from youtube.com. Download first (yt-dlp), then drop the resulting MP4/MKV here.
Re-encode stripped the chapters
Empty arrayIf you re-encoded the download (e.g. through a converter that didn't carry metadata), the chapters can be lost and the array comes back empty. Re-download the original with --embed-chapters to recover them.
Very long video (multi-hour)
SupportedHeader-only parsing reads chapters in seconds regardless of runtime. Free tier caps the file at 1 GB; a long 1080p/4K download may need Pro (10 GB) or higher.
You want to write the description back automatically
Read-onlyThis tool gives you the chapter JSON; it doesn't post to YouTube or edit the file. Use the JSON to generate the MM:SS Title text and paste it into Studio yourself.
Frequently asked questions
Can I paste a YouTube URL?
No. This tool reads chapter metadata from a file already on your machine. Download the video first — yt-dlp --embed-chapters <url> — then drop the resulting MP4 or MKV here.
Why did I get an empty array from my download?
You almost certainly downloaded without --embed-chapters, so the chapters stayed in the description text and never reached the file's metadata. Re-download with the flag, or copy the timestamps from the original description manually.
How do I rebuild the description timestamps?
Map each chapter's start (seconds) to MM:SS and prepend it to the title. Make sure the first line is 00:00, there are at least 3 chapters, and each is ≥ 10 seconds. The cookbook shows the exact formatter and a validator.
What are YouTube's chapter rules again?
First timestamp must be 00:00; at least 3 chapters; each chapter ≥ 10 seconds; format MM:SS Title (or HH:MM:SS Title). If any rule fails, YouTube silently doesn't enable chapters. The tool gives you the data; you apply the rules.
Will non-English titles survive?
Yes. Titles read as UTF-8 and write verbatim, so 第1章 or Intro 🎬 come back intact and paste correctly into a UTF-8 description.
Is the downloaded file uploaded anywhere?
No. FFmpeg.wasm runs in the browser and only reads the container header. The bytes stay on your machine — nothing is re-uploaded to JAD or to YouTube.
What does the JSON look like?
{ "chapters": [{ "start": <seconds>, "end": <seconds>, "title": <string or null> }] }, saved as <filename>-chapters.json. Start/end are floating-point seconds; titles are verbatim or null.
Can I re-time chapters after editing the video?
Yes, in your own code: subtract the seconds you trimmed from each start/end, drop anything now before 0, and force the first chapter to 00:00. The cookbook has a ready-made example.
Does it re-encode the download?
No — it reads metadata only (-c copy -t 0). Your downloaded file is untouched and nothing is transcoded.
Can it post the chapters back to YouTube?
No. It's read-only and offline. Generate the MM:SS Title text from the JSON and paste it into YouTube Studio's description field yourself.
How large a download can I process?
Free 1 GB, Pro 10 GB, Pro-media 100 GB, Developer 100 GB — by file size, not duration. Header-only reading keeps even long 4K downloads fast.
My re-encoded copy lost its chapters — can I recover them?
Not from the re-encoded file if the converter dropped the metadata. Re-download the original with --embed-chapters; chapters can't be reconstructed by re-processing a copy that no longer has them.
Privacy first
Every JAD Video tool runs entirely in your browser via WebCodecs and FFmpeg (WebAssembly). Your video files never leave your device — verified by zero outbound network requests during processing.