#!/bin/bash # Scrape YouTube comments into searchable .md and .json files. # Usage: ytcomments [output_dir] # url - YouTube video URL # output_dir - where to save (default: current directory) # # Output files are named after the video title, sorted by like count. # Search with: rg -i "keyword" file.md die() { printf '%s\n' "$1" >&2; exit 1; } [ -z "$1" ] && die "Usage: ytcomments [output-dir]" command -v yt-dlp >/dev/null || die "yt-dlp not found" command -v jq >/dev/null || die "jq not found" url="$1" outdir="${2:-.}" tmpdir=$(mktemp -d) trap 'rm -rf "$tmpdir"' EXIT printf 'Scraping comments from: %s\n' "$url" yt-dlp --skip-download --write-comments \ -o "$tmpdir/%(title)s.%(ext)s" "$url" 2>&1 | tail -1 infofile=$(find "$tmpdir" -name '*.info.json' | head -1) [ -f "$infofile" ] || die "Failed to download comments" title=$(jq -r '.title' "$infofile" | tr '/' '-' | tr -d '\n') count=$(jq '.comments | length' "$infofile") printf 'Found %s comments for: %s\n' "$count" "$title" # Markdown — sorted by likes, most popular first jq -r ' .comments | sort_by(-.like_count) | .[] | "## \(.author) (\(.like_count) likes)\n\(.text)\n\n---\n" ' "$infofile" > "$outdir/$title.md" # JSON — clean array sorted by likes jq '[.comments | sort_by(-.like_count) | .[] | { author, text, likes: .like_count, replies: (.reply_count // 0), time: .timestamp }]' "$infofile" > "$outdir/$title.json" printf 'Saved:\n %s/%s.md\n %s/%s.json\n' "$outdir" "$title" "$outdir" "$title" printf 'Search with: rg -i "keyword" "%s/%s.md"\n' "$outdir" "$title"