Skip to main content

Local-first YouTube AI CLI: download, transcribe (captions -> whisper), embed in LanceDB, discover subscriptions, and summarize/highlight/Q&A.

Project description

yt-mem-ai — YouTube AI CLI

Install

# zero-install run (recommended)
uvx yt-mem-ai --help

# or bootstrap uv + warm the cache
curl -LsSf https://raw.githubusercontent.com/dasein108/yt-mem-ai/main/install.sh | sh

The desktop UI lives in a separate repo: yt-mem-ai-desktop. It depends on this yt-mem-ai package and runs its own local REST API.

Download YouTube audio, transcribe (captions → faster-whisper fallback), store everything in an embedded LanceDB with per-chunk embeddings, discover subscription uploads, and search your library semantically. Summaries, highlights, and Q&A are produced by Claude Code skills, not an API.

Setup

uv sync --extra dev
cp .env.example .env   # fill WEBSHARE_* + YT_COOKIES_BROWSER; pick embedding backend

Config (.env): YT_STORE_PATH (LanceDB dir), YT_EMBEDDING_BACKEND=local|openai, YT_EMBEDDING_MODEL, YT_CHUNK_TARGET_S, OPENAI_API_KEY (openai backend), WEBSHARE_PROXY_*, YT_COOKIES_BROWSER.

Proxy / VLESS: YT_USE_WEBSHARE defaults off. If you already run a system-level proxy/VPN (VLESS/Xray etc.), leave it off — traffic rides that tunnel. Stacking the Webshare proxy on top breaks the authenticated subscription feed (its CONNECT tunnel returns 405). Only set YT_USE_WEBSHARE=true if you have no other proxy and YouTube rate-limits your raw IP. Discover tuning: YT_DISCOVER_FEED_LIMIT (newest-N cap, default 60), YT_DISCOVER_OVERLAP_S (incremental overlap, default 3600), YT_DISCOVER_TIMEOUT_S.

Commands

yt-ai fetch <url>            # download + transcribe + embed + store one video
yt-ai fetch <url> --captions-only  # captions only: no audio download / no whisper (fails if none)
yt-ai transcript <url>       # same pipeline
yt-ai discover               # new subscription uploads (--after/--deep/--min-duration/--json); incremental by default
yt-ai fetch-pending          # batch-fetch pending 'discovered' videos (since --since, default today; --limit)
yt-ai list                   # list stored videos (--status/--since/--json)
yt-ai show <video_id>        # metadata + transcript (--json)
yt-ai status                 # counts by status
yt-ai search "<query>"       # semantic search (--hybrid/--fts/--vector, -k N)
yt-ai save-summary <id> "<summary>" --highlights '<json>' --qa '<json>'  # persist a summary (used by skills)
yt-ai like <video_id>        # mark liked (feeds recommendations)
yt-ai dislike <video_id>     # mark disliked
yt-ai recommend              # rank your unrated fetched videos by taste (--limit/--json)
yt-ai compile                 # deep-linked highlights doc, budget-bounded (--since/--max-minutes/--json/--out)
yt-ai supercut                 # video reel of highlights, re-downloaded + labeled (--since/--max-minutes/--out/--keep-clips)

Rate & recommend

Like/dislike videos you've fetched (yt-ai like <id> / dislike <id>), then yt-ai recommend ranks your other fetched-but-unrated videos by similarity to what you liked (minus what you disliked), using their transcript embeddings. Before you've liked anything, it falls back to most-recently-published.

Daily routine

yt-ai discover               # find new subscription uploads → 'discovered'
yt-ai fetch-pending          # download+transcribe+embed today's batch (robust, skips failures)
# then in Claude Code:
/daily-digest                # per-video summaries + digests/YYYY-MM-DD.md
yt-ai compile                # compile the day's highlights into a deep-linked markdown you can click into

yt-ai discover is incremental: it pulls the newest feed entries (one flat call, capped by YT_DISCOVER_FEED_LIMIT), stamps each with an approximate timestamp (yt-dlp youtubetab:approximate_date), and keeps only those newer than the last run's stored high-water mark minus a 1h overlap (YT_DISCOVER_OVERLAP_S) — so hour-rounded dates never miss a boundary video, and already-processed videos (is_seen) are filtered out. Pass --after YYYY-MM-DD to override the cutoff manually. Full per-video metadata (description, tags, exact time) is fetched later at ingest, not during discover.

yt-ai compile builds compilations/<DATE>.md: each highlight from the day's summarized videos becomes a deep link (watch?v=ID&t=<start>s) that jumps straight to its moment, newest-video-first and budget-bounded by --max-minutes (default 20). Fast — no downloading, just the same compile_highlights selection rendered as markdown.

yt-ai supercut renders that same highlight selection as an actual video reel instead of a doc: it re-downloads each highlight's section (720p, yt-dlp --download-sections), burns a label onto each clip (title/timestamp), and concats them into one mp4 — so it needs network access and a local ffmpeg, and is much slower than compile. Output is supercuts/<since-or-today>.mp4 plus a sidecar supercuts/<...>.mp4.refs.md listing each rendered clip's source link (and any clips skipped because their download/render failed). Use compile for a quick clickable digest; use supercut when you want a shareable video.

Single video on demand: yt-ai fetch <url> then the /summarize-video skill.

Logging

The CLI writes structured JSON events to logs/common.jsonl (via obs.log_event/blog) — one object per line, {ts, source, level, event, msg, ...ctx}. Override the path with YT_LOG_FILE; it's gitignored. Inspect with jq:

jq -c 'select(.level=="error")' logs/common.jsonl   # every error
tail -f logs/common.jsonl | jq -c '{ts,event,msg}'  # live tail, compact

Tests

uv run pytest -q                       # offline unit tests (fake embedder)
YT_RUN_INTEGRATION=1 uv run pytest -q  # + real sentence-transformers integration

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yt_mem_ai-0.1.0.tar.gz (298.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

yt_mem_ai-0.1.0-py3-none-any.whl (30.0 kB view details)

Uploaded Python 3

File details

Details for the file yt_mem_ai-0.1.0.tar.gz.

File metadata

  • Download URL: yt_mem_ai-0.1.0.tar.gz
  • Upload date:
  • Size: 298.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for yt_mem_ai-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b2ddca4518a5d5a82ad1e2439db20b232ad0e3e8a92b869958bc72561ea811cb
MD5 61d1b45887633e1c625d52e5a31666da
BLAKE2b-256 d920ebf2718c4e1b7f84200fa1f4ed48ac711483b14401ac1c0f846d4cc7fe4d

See more details on using hashes here.

Provenance

The following attestation bundles were made for yt_mem_ai-0.1.0.tar.gz:

Publisher: publish-pypi.yml on dasein108/yt-mem-ai

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yt_mem_ai-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: yt_mem_ai-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 30.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for yt_mem_ai-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c8e60f0e5055acf3241fec45cc8671b02fb7bcfe37f762d897f4e5c8bd6bcfc3
MD5 961f03bc1ecc9c471be3200370579cac
BLAKE2b-256 facd917b4b3f32fddaab8d9f12658f6d25a21f66fe10260436b449124ee9d8bd

See more details on using hashes here.

Provenance

The following attestation bundles were made for yt_mem_ai-0.1.0-py3-none-any.whl:

Publisher: publish-pypi.yml on dasein108/yt-mem-ai

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page