10

Some YouTube content creators split their videos into chapters. A subset of them kindly offer the list of chapters titles on description video, with their starting timestamp. Sometimes they decide not to show them.

How can I get the list of chapters titles?

1

3 Answers 3

8

One-liner to do this using yt-dlp (better alternative to youtube-dl) and jq JSON processor:

yt-dlp --dump-json  videoIDorURL | jq --raw-output ".chapters[].title"

To get starting timestamps:

 | jq --raw-output ".chapters[].start_time" | awk '{printf("%d:%02d:%02d\n",($1/60/60%24),($1/60%60),($1%60))}'

With paste and process substitution you can combine both. This is a function you could add to your .bashrc/.zshrc:

function get_chapters_times() {
  paste <(yt-dlp --dump-json $1 | jq --raw-output ".chapters[].start_time" | awk '{printf("%d:%02d:%02d\n",($1/60/60%24),($1/60%60),($1%60))}') <(yt-dlp --dump-json $1 | jq --raw-output ".chapters[].title")
}

Will return:

$ get_chapters_times https://youtu.be/DxL2HoqLbyA
0:00:00 Intro
0:02:15 History
0:04:16 Ideal Engine
0:09:48 Entropy
0:11:03 Energy Spread
0:14:49 Air Conditioning
0:17:26 Life on Earth
0:19:35 The Past Hypothesis
0:21:43 Hawking Radiation
0:23:31 Heat Death of the Universe
0:24:52 Conclusion

Use yt-dlp --split-chapters to download each chapter.

0
0

In python, you can do this:

import datetime
import yt_dlp

ydl = yt_dlp.YoutubeDL({'dumpjson':True } )
dnwl_setting = False
with ydl:
    result = ydl.extract_info( ytdl_variables.video_url,
    download=dnwl_setting  )

for chpt in result['chapters'] :
    str_start_time = chpt['start_time']
    str_start_time_cnv = str(datetime.timedelta(seconds=str_start_time) ) 
    
    str_title = chpt['title']
    
    # for youtube timecodes
    print ( f"time = {str_start_time_cnv} | title = {str_title } ")
-1

Here's a fancier one-liner inspired by Pablo's answer that does away with process substitution and having to define functions

yt-dlp videoURL --dump-json | jq -r ".chapters[] | {start_time, title}" | awk -v count="2" '++count==4{$0=sprintf("  \"start\":%d:%02d:%02d",($2/60/60%24),($2/60%60),($2%60));count=0} 1' | awk -F '":' '{print $2}' | gsed -r -e '/^\s*$/d' -e 's/^ "|"$//g' | paste -d " "  - -

The awk and gsed could probably be merged into each other at the cost of more complexity.

If using yt-dlp, you may also benefit from --embed-chapters (alias: --add-chapters) argument.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .