Skip to content
Fel-2Public

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

74 Commits

Folders and files

Repository files navigation

vidi

A terminal UI for YouTube, Twitch, Kick and PeerTube, written in Rust.

██╗░░██╗██╗██████╗░██╗
██║░░██║██║██╔══██╗██║
╚██╗██╔╝██║██║░░██║██║
░████╔╝░██║██║░░██║██║
░╚██╔╝░░██║██████╔╝██║
░░╚═╝░░░╚═╝╚═════╝░╚═╝

Features

YouTube

  • ⚡ Fast metadata via the Innertube API (no yt-dlp subprocess for lists; yt-dlp remains as fallback)
  • 🔥 Trending videos
  • 🔍 Search with history
  • 📡 Subscription feed (parallel fetch, sorted by upload time, instant cached startup with background refresh)
  • 📋 Browse subscribed channels (Videos / Shorts / Streams / Playlists)
  • ➕ Subscribe to channels directly from Explore Channels
  • 📥 Import subscriptions from NewPipe JSON, OPML or YouTube Takeout CSV (Miscellaneous → Import Subscriptions)
  • ⏭ Play-next queue (Tab to queue from any list, YouTube → Queue to play)
  • ⏯ Watch progress: playback position is tracked via mpv IPC and resumed on the next watch
  • 🚫 SponsorBlock: mark segments as mpv chapters, cut them from downloads (SPONSORBLOCK in vidi.conf)
  • 🙈 Shorts hidden everywhere by default — lists, search, feed and the channel Shorts tab (SHOW_SHORTS: true re-enables)
  • 🎯 Custom playlists
  • 🕐 Recently watched
  • 🔎 Channel search via Miscellaneous → Explore Channels

Twitch

  • 🔍 Live stream search
  • 💜 Subscription status in one fast batched API call (live/offline, viewers, uptime), with a streamlink fallback
  • 🔥 Top live streams (Twitch directory)
  • 🗂 Browse categories → live streams per game, with box-art previews
  • ➕ Follow / unfollow channels in-app (writes twitch_subs)
  • 🎬 VOD browsing via fast GQL (Past Broadcasts / Highlights / Uploads / Premieres), with view counts, durations and thumbnails — for subscribed channels or any stream you find; resumes where you left off; download with audio/quality options
  • 💬 Live chat viewer with real Twitch name colours and broadcaster/mod/vip/sub badges (auto-reconnects)

Kick

  • 🔍 Live channel search
  • 💚 Subscription status for followed channels, with live/offline, uptime and thumbnails
  • 🔥 Top live streams (Kick directory)
  • 🗂 Browse categories → live streams per category
  • ➕ Follow / unfollow channels in-app (writes kick_subs)
  • 🎬 VOD browsing with durations and thumbnails; download or open in browser

PeerTube

  • 🌐 Pick your instance on first use (prefilled, saved to peertube.conf, changeable any time from the menu)
  • 🔥 Trending and 🆕 Recently Added from your instance
  • 🔍 Search across the whole fediverse via SepiaSearch
  • 📡 Subscription feed fetched straight from each channel's own instance, so new uploads show up before they federate (parallel fetch, cached startup with background refresh)
  • 🔎 Explore channels and subscribe/unsubscribe in-app (writes peertube_subs)
  • ▶️ Watch, download, save, queue and resume exactly like YouTube videos

General

  • Inline thumbnail previews (kitty / Ghostty graphics protocol, or iTerm2 / WezTerm)
  • Inline video playback via mpv / yt-dlp
  • Download support (video + audio-only, single + batch)
  • Save/unsave videos to a local watchlist
  • Fuzzy filter bar on all list screens (/, vim-style)
  • Help overlay on ?
  • Update check on launch, with a prompt to install the latest release (CHECK_UPDATES: false disables)

Dependencies

Install

Prebuilt binary

curl -fsSL https://raw.githubusercontent.com/Fel-2/Vidi/main/install.sh | sh

Installs the latest release to ~/.local/bin. Static musl builds for x86_64 and aarch64, checksum-verified. Set PREFIX=/usr/local/bin to change the destination or VERSION=v0.2.0 to pin a release.

Arch / Artix

git clone https://codeberg.org/Fel/Vidi.git
cd Vidi/packaging
makepkg -si

From source

cargo build --release

Binary is at target/release/vidi.

vidi --version prints the version; it is also shown under the logo on the start screen and in the ? help overlay.

Configuration

Config files are created automatically on first run:

File Purpose
~/.config/vidi/vidi.conf Player, quality, result limits, PLATFORMS, WATCH_PROGRESS, SPONSORBLOCK, YTDLP_CLIENT, CHECK_UPDATES
~/.config/vidi/subscriptions YouTube channel URLs (one per line)
~/.config/vidi/twitch.conf Twitch player and quality settings
~/.config/vidi/twitch_subs Twitch usernames (one per line)
~/.config/vidi/kick.conf Kick player and quality settings
~/.config/vidi/kick_subs Kick channel names (one per line)
~/.config/vidi/peertube.conf PeerTube instance (INSTANCE, optional SEARCH_INSTANCE)
~/.config/vidi/peertube_subs PeerTube channels as channel@instance (one per line)
~/.config/vidi/custom_playlists.json Custom playlist URLs

In subscriptions, each line is a channel URL, optionally followed by whitespace and a display name (https://www.youtube.com/channel/UC… My Channel). Providing the name inline lets the Channels view skip the per-channel yt-dlp lookup, so it loads instantly. Lines without a name are resolved once and cached in ~/.cache/vidi/channel_names.json.

PLATFORMS in vidi.conf controls which platforms appear on the start screen. It takes a comma-separated list of youtube, twitch, kick and peertube (aliases yt and pt work, case and spaces are ignored):

PLATFORMS: youtube,kick

Omitting the key shows all four, and an unrecognised value falls back to all four rather than leaving you with an empty menu. Hiding a platform only removes its menu — its config, subscriptions and history are left untouched, so re-enabling restores everything.

peertube_subs stores each channel with its home instance (blender_studio@video.blender.org); channel URLs work too and are normalised on read. Because the handle carries the origin, the feed queries each channel's own instance directly instead of waiting for federation.

To annotate an existing URL-only file in place, run:

scripts/name-subscriptions.py

It reuses the cache where possible and only calls yt-dlp (4 at a time) for names it doesn't already know. The original is backed up to subscriptions.bak.

Playback and downloads

vidi hands the video URL to mpv, which asks yt-dlp to work out the actual stream URLs. That means playback depends on what yt-dlp decides to ask YouTube for — and yt-dlp's own defaults change from release to release without warning, so a new default can break playback for everyone running vidi.

To keep that decision ours, vidi pins the YouTube player clients it asks for:

YTDLP_CLIENT: visionos,web

visionos leads because it is the one client that needs neither a PO token nor a JavaScript runtime — no cookies, no browser, nothing to keep in sync. web is a fallback. vidi sets this explicitly on every yt-dlp invocation it makes, so it takes precedence over both yt-dlp's defaults and any ~/.config/yt-dlp/config you have. Override YTDLP_CLIENT if YouTube starts refusing the defaults; the extractor argument accepts the usual yt-dlp client names.

This needs yt-dlp 2026.08.19 or newer, the first release that knows the visionos client; older builds ignore clients they don't recognise and fall back to their own defaults (vidi warns at startup when it sees that).

Downloads pin the same clients, so they don't drift either.

Keybindings

Key Action
↑ / k Move up
↓ / j Move down
PgUp / PgDn Page up / down
Enter Select
Esc Back
q Quit
Tab Add video to queue (in Queue: remove)
? Help overlay
/ Fuzzy filter list (vim-style prompt: Enter keeps the filter, Esc clears it)
Ctrl-W / Ctrl-U In the filter prompt: delete word / clear line
n / N Jump to next / previous match of the last filter text
g / G First / last row
Ctrl-U / Ctrl-D Half page up / down
Backspace Clear filter
p / d Play / download the selected item
y / s Copy URL to clipboard / toggle saved
Mouse wheel Scroll lists

Single-key overrides can be set in vidi.conf (KEY_UP, KEY_DOWN, KEY_SELECT, KEY_BACK, KEY_QUIT, KEY_PAGE_UP, KEY_PAGE_DOWN). Arrow and vim keys always work.

Troubleshooting

Kick VODs start from the live edge and cannot be scrubbed

Kick serves recorded videos as a live-style HLS playlist, so mpv sees an unseekable stream: playback begins near the live edge and the position cannot be moved. WATCH_PROGRESS does not apply to Kick VODs for the same reason — the reported length is only the buffered window. Use Download to keep a copy you can seek through locally.

A video occasionally fails to start

Now and then a launch fails like this:

[ffmpeg] https: HTTP error 403 Forbidden
Failed to open https://rr2---sn-....googlevideo.com/videoplayback?...
No video or audio streams selected.

vidi retries this for you, so it usually resolves itself within a second or two. You do not need to press anything.

This is a transient rejection by YouTube's media CDN, not a problem with vidi, yt-dlp or your setup. Because bestvideo+bestaudio streams the video and audio tracks from two separate URLs, one of them being refused is enough to abort playback. The refused URL is still valid: requesting it again seconds later succeeds. Measured on a sample of 60 launches, roughly 15% failed this way, in bursts.

vidi retries non-destructively: once with the same client (fresh URLs, same quality), then once on its fallback client, which may be lower quality but plays. If a video still won't start, the pinned client is the likely cause — see Playback and downloads for YTDLP_CLIENT.

Retrying is safe here — the 403 comes from the media servers, not from YouTube's API, so it is not a rate limit or a bot check and does not count against you.

One exception: vidi deliberately does not retry "Sign in to confirm you're not a bot", "Video unavailable", or geo/membership refusals. Those are permanent for that request, and hammering the bot check can get your IP flagged for real. If you see one of those, the video itself is the problem.

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages