foxygit / ytmdl Log in
commits tags

/c/README.md · 4.13 KB

raw

ytmdl (C)

A terminal UI for downloading audio from YouTube / YouTube Music video, playlist, and album URLs, written in C with ncurses. All the actual extraction/downloading is done by shelling out to yt-dlp — this program is the queue, the TUI, and the orchestration around it.

Requirements

  • gcc (or another C11 compiler) and make
  • ncursesw development headers (libncursesw5-dev / ncurses-devel depending on distro)
  • pthread (part of glibc on Linux)
  • yt-dlp on your PATH — needs to be reasonably

    recent, since YouTube changes frequently break older releases. An outdated version can fail to resolve any playlist and surface confusing errors (e.g. "YouTube Music is not directly supported" or zero entries found) even though the URL itself is fine — it's the extractor being too old to parse YouTube's current page format, not an actual YouTube Music limitation. Update with yt-dlp -U or pip install -U yt-dlp. ./start.sh (from the repo root) automatically prefers the copy kept up to date in ../.venv/bin over an older system package, if present.

  • ffmpeg on your PATH (yt-dlp uses it for audio extraction,

    thumbnail embedding, and metadata tagging)

  • A Nerd Font in your terminal — the queue status column

    and the folder browser use Nerd Font glyphs; without one they'll show as missing-glyph boxes

  • A terminal with color support for the best look (color-coded status icons/progress

    bars, focus-highlighted panel borders); the UI still works without it, just flatter

Build

make

Produces a single ytmdl binary in this directory.

Run

./ytmdl

or from the repo root: ./start.sh (builds if needed, then runs it).

Paste a video, playlist, or album URL into the URL field and press Enter. Playlists and albums are expanded into individual tracks, each downloaded and tagged separately, with up to 2 downloads running concurrently.

Options

./ytmdl [-o output_dir] [-f audio_format]
  • -o — where files are saved (default ~/Music/ytmdl)
  • -f — output audio format: mp3, m4a, flac, opus, wav, vorbis (default mp3)

Keybindings

Global (work no matter what has focus):

  • Ctrl+O — open a folder browser to change the download directory
    • Up/Down — move selection, Enter/Right — open the highlighted folder,

      Backspace/Left — go to the parent folder, s — select the currently browsed folder, Esc — cancel

  • Ctrl+F — toggle "create a folder per playlist/album" (on by default; named after the

    playlist/album title; single videos are never nested)

  • Ctrl+N — clear finished: remove every successfully completed row from the queue

    (errored rows stay, so you can still see what failed and retry with r)

  • Ctrl+Q — quit
  • Tab — switch focus between the URL field and the queue table

URL field focused:

  • Enter — submit the URL

Queue table focused:

  • Up/Down — move the selected row
  • d / Delete — remove the selected row (not while it's actively downloading)
  • r — retry a row that errored

Architecture

  • queue.c/.h — thread-safe queue of QueueItems (id, url, title, subfolder, status,

    progress), a fixed-capacity array behind a mutex so worker threads can hold stable ids across UI-driven removals.

  • downloader.c/.h — spawns yt-dlp via fork/exec, parsing structured

    --print-template output (unit-separator-delimited fields) to resolve playlists, and --newline progress lines to track download percent/speed/eta.

  • app.c/.h — app state, settings (output dir, audio format, playlist-folder toggle), a

    small fixed pool of worker threads pulling from a work queue, and the actions the UI calls into (submit URL, clear finished, remove/retry).

  • ui.c/.h, input_field.c/.h, dirpicker.c/.h — ncurses rendering and input handling.
  • icons.h — Nerd Font glyph codepoints, written as \uXXXX escapes.

There is no equivalent of Textual's command palette in this version — every action has a direct, always-available keybinding instead.