Dṛśya (दृश्य) is Sanskrit for "sight, what is seen". It's the sibling
of nāda ("sound"), the music
player: same keys, same look.
Contents
Features
- Video first: mpv draws into the window (libmpv, hardware decoding).
The controls float over the video and fade after a moment; the timeline
shows the chapters, what's buffered, and a preview frame where you hover.
f is fullscreen as zen: just the video, and a small readout in the
corner when you seek or press i. t theater, z a mini player.
- Search from anywhere (
/): one floating panel for YouTube, your
videos, your history, a link you paste and commands. Your own videos
answer as you type, YouTube a moment later, the best match first; Tab
picks where to look. Play, play next, add or download without leaving it.
- YouTube without an account: every result with its thumbnail, channel,
views and length; related videos play after yours (autoplay,
M).
- Any link:
o and paste. HLS (.m3u8) and DASH streams from any
server, a video file over HTTP, live streams, and the sites yt-dlp
plays.
A stream's qualities are capped like YouTube's.
- Signs in when it has to: a server that asks for a username and
password gets a sign-in panel; sites that need an account can borrow
your browser's login. Logins you choose to remember go to your keyring.
- Your library as a grid: Continue watching first, then your folders;
inside, the episodes in order (
S01E02, "Episode 10" after "Episode 9"), thumbnails, and the
next episode lined up after the one you play.
- Resume and history: every video starts where you stopped. History
(
4) has a Continue watching list, with a red bar for how much you've seen.
- Up next, edited like text:
dd removes, J/K move, yy/p copy
and paste, V selects several, u undoes, Ctrl+r redoes.
- One settings menu (
Q): quality, speed, subtitles, audio track,
download. Quality lists what YouTube offers
for this video (4K down to 144p) or a stream's own qualities. Your pick
stays for the next videos and for downloads.
- Downloads with subtitles:
D (or the download button) saves a video
(YouTube or any link) at your quality, with its subtitles, chapters and
thumbnail; it then plays from your disk.
Install
Requirements
- Python 3.11+, PyGObject, GTK 4
- mpv (drishya uses its library, libmpv, which comes with it)
- yt-dlp for YouTube and other sites, ffmpeg for thumbnails and downloads
- optional:
secret-tool (libsecret) to remember logins in your keyring, brightnessctl for the brightness keys, a Nerd Font for the icons
# Arch
sudo pacman -S --needed python-gobject gtk4 mpv yt-dlp ffmpeg libsecret ttf-jetbrains-mono-nerd
# Debian / Ubuntu
sudo apt install python3-gi gir1.2-gtk-4.0 libmpv2 yt-dlp ffmpeg libsecret-tools
drishya
git clone https://github.com/Theyashsawarkar/drishya ~/.local/share/drishya
ln -s ~/.local/share/drishya/bin/drishya ~/.local/bin/drishya
drishya # opens the player (it starts itself the first time)
For app launchers and to open video files with it:
ln -s ~/.local/share/drishya/data/dev.vayu.Drishya.desktop ~/.local/share/applications/
xdg-mime default dev.vayu.Drishya.desktop video/mp4 video/x-matroska video/webm
Update with git -C ~/.local/share/drishya pull && drishya quit.
To start it with your session (so it opens at once), a user service:
# ~/.config/systemd/user/drishya.service
[Unit]
PartOf=graphical-session.target
After=graphical-session.target
[Service]
ExecStart=%h/.local/bin/drishya daemon
Restart=on-failure
[Install]
WantedBy=graphical-session.target
On a tiling compositor, float the mini player in a corner. sway:
for_window [app_id="^dev\.vayu\.Drishya$" title="^drishya mini$"] floating enable, sticky enable, resize set 480 270, move position 1420 790
Usage
drishya open the player, or close it if it's open
drishya play <what> play now: a YouTube link, any stream or video link, a file or folder,
or search words (plays the top YouTube result)
drishya add [--next] <what> add to Up next instead
drishya show | hide | mini the window, hidden, the mini player
drishya tab <name> watch queue library youtube history downloads
drishya ctl <command> toggle play pause next prev | seek +10 | seek 1:30 | vol 80 | speed 1.5
drishya status [--json] what's playing
drishya quit stop it
Tabs: 0 Watch, 1 Up next, 2 Library, 3 History, 4 Downloads;
/ searches YouTube, your videos and history from any of them. Lists move with j/k; Enter plays. ? shows every key.
Keys
drishya is vim-driven, with Space as the leader, the same grammar as every
Vayu tool (and as nāda): a key you use all the time is one key (j/k,
p play/pause, H/L tabs, f fullscreen, dd, yy); everything else
is Space, then a group, then the thing (Space c a the audio track,
Space t h the history). Wait a moment after Space (or g, d, y) and
a strip shows what can come next; Esc cancels. Space Space opens a
palette of every action, ? or Space ? shows every key of the tab you're
on. Counts work like vim: 5j, 3., 2dd; digits are always counts (tabs
are H/L, Space t, Ctrl+0..4). In fullscreen (zen) Space still
plays and pauses. While typing, Ctrl+j/Ctrl+k move. Confirmations take
y only.
Volume and brightness: =/- change the system volume and Ctrl+=/Ctrl+- the screen's brightness
(pactl or wpctl, and brightnessctl); when the window closes, both go back to how they were.
Moved in this release (the old key says where, then goes away):
Space play/pause is p (fullscreen keeps Space); Up next's paste
p/P is gp/gP; i info is Space i; zz is Space g p; a lone
0-4 is H/L or Space t. Q settings is also Space ,.
Everywhere
| Key | Action |
|---|
j | Move down (counts work: 5j) |
k | Move up |
g g | Jump to the top (12gg: to the 12th) |
G | Jump to the bottom (12G: to the 12th) |
Ctrl+d | Scroll half a page down |
Ctrl+u | Scroll half a page up |
H | Switch to the previous tab (wraps around) |
L | Switch to the next tab (wraps around) |
Ctrl+Tab | Switch to the next tab (also from the search box) |
Ctrl+Shift+Tab | Switch to the previous tab (also from the search box) |
Ctrl+0 | Switch to Watch at once (Ctrl+1 Up next, 2 Library, 3 History, 4 Downloads) |
p | Toggle play / pause (in fullscreen, Space too) |
Enter | Play the selected video |
. | Seek forward 10 seconds (3. = 30 s) |
, | Seek back 10 seconds |
> | Play the next video |
< | Play the previous video |
= | Raise the system volume (back as it was when the window closes) |
- | Lower the system volume |
Ctrl+= | Raise the screen brightness (back as it was when the window closes) |
Ctrl+- | Lower the screen brightness |
m | Toggle mute |
f | Toggle fullscreen (zen: just the video; Esc leaves it too) |
t | Toggle theater mode (the video without the side panel) |
z | Switch to the mini player (picture-in-picture) |
c |
Watch
| Key | Action |
|---|
h | Seek back 5 seconds (3h = 15 s) |
l | Seek forward 5 seconds |
Tab | Switch the side panel (up next, chapters, info) |
Enter | Play the side panel's video, or jump to its chapter |
Up next
| Key | Action |
|---|
d d | Remove the video from the queue (2dd: two; u undoes it) |
x | Remove the video from the queue (like dd; u undoes it) |
d G | Remove every video from here to the end (u undoes it) |
y y | Copy the video (yank) |
g p | Paste removed or copied videos below |
g P | Paste removed or copied videos above |
J | Move the video down |
K | Move the video up |
A | Move the video to play next |
D | Save the video to your disk (download) |
n | Jump to the next match (after a search here) |
N | Jump to the previous match |
Space d d | Remove the video from the queue (u undoes it) |
Library
| Key | Action |
|---|
h | Move left in the grid |
l | Move right in the grid |
Enter | Open the folder or play the video (the rest of the folder after it) |
Backspace | Go up a folder |
a | Add to the end of the queue |
A | Add to play next |
R | Reload the folders |
Space a a | Add to the end of the queue |
Space a n | Add to play next |
YouTube results
| Key | Action |
|---|
Enter | Play the result |
a | Add the result to the end of the queue |
A | Add the result to play next |
D | Save the result to your disk (download) |
Space a a | Add the result to the end of the queue |
Space a n | Add the result to play next |
History
| Key | Action |
|---|
Enter | Resume the video where you left it |
a | Add the video to the end of the queue |
A | Add the video to play next |
d d | Forget the video (removes it from the history; asks first) |
x | Forget the video (like dd; asks first) |
D | Save the video to your disk (download) |
n | Jump to the next match (after a search here) |
N | Jump to the previous match |
Space a a | Add the video to the end of the queue |
Space a n | Add the video to play next |
Space d d | Forget the video (asks first) |
Downloads
| Key | Action |
|---|
Enter | Play the saved video |
R | Retry a failed download |
x | Cancel a download in progress |
d d | Delete the saved file (asks first) |
Space x r | Retry a failed download |
Space x c | Cancel a download in progress |
Space d d | Delete the saved file (asks first) |
Up next, visual mode (V)
| Key | Action |
|---|
d | Remove the selected videos (u undoes it) |
x | Remove the selected videos (like d; u undoes it) |
y | Copy the selected videos (yank) |
V | Leave visual mode |
Esc | Leave visual mode |
History, visual mode (V)
| Key | Action |
|---|
d | Forget the selected videos (asks first) |
x | Forget the selected videos (like d; asks first) |
a | Add the selected videos to the end of the queue |
A | Add the selected videos to play next |
V | Leave visual mode |
Esc | Leave visual mode |
YouTube results, visual mode (V)
| Key | Action |
|---|
a | Add the selected results to the end of the queue |
A | Add the selected results to play next |
D | Save the selected results (download) |
V | Leave visual mode |
Esc | Leave visual mode |
Fullscreen (f)
| Key | Action |
|---|
Space | Toggle play / pause (zen has no leader) |
Settings menu (Q, Space ,)
| Key | Action |
|---|
j | Move down through the settings menu |
k | Move up through the settings menu |
l | Open the setting or choose it (Enter too) |
h | Go back in the settings menu (Backspace too) |
Esc | Close the settings menu (Q and q too) |
Search panel (/)
| Key | Action |
|---|
Tab | Switch where to look (all, YouTube, your videos, history, commands) |
Shift+Tab | Switch back where to look |
Ctrl+j | Move down through the results while typing |
Ctrl+k | Move up through the results while typing |
Enter | Play the result (a command: run it) |
Ctrl+Enter | Play the result next |
Shift+Enter | Add the result to Up next |
Ctrl+d | Download the result |
Ctrl+u | Clear the search box |
Ctrl+x | Clear recent searches |
Esc | Close the search panel |
Sign in
| Key | Action |
|---|
Enter | Sign in and play (from the password field) |
Tab | Move between the username and password fields |
Ctrl+b | Sign in with your browser's login instead (sites yt-dlp plays) |
Ctrl+s | Toggle remembering the login in your keyring |
Esc | Cancel signing in |
Palette (Space Space)
| Key | Action |
|---|
Ctrl+j | Move down through the actions (Down too) |
Ctrl+k | Move up through the actions (Up too) |
Enter | Run the action |
Esc | Close the palette |
While a key waits
| Key | Action |
|---|
Esc | Cancel a pending key or count (Space, g, d…) |
In the mini player (z)
| Key | Action |
|---|
Space | Toggle play / pause |
. / , | Seek forward / back 10 seconds |
> / < | Play the next / previous video |
= / - | Raise / lower the system volume |
Ctrl+= / Ctrl+- | Raise / lower the screen brightness |
z / Enter | Switch back to the full player |
q / Esc | Close the mini player (pauses) |
Commands
: opens the command line:
| Command | What it does |
|---|
:open <link, file or folder> | Play it now (o opens this) |
:add <…> | Add to Up next |
:yt <search> | Search YouTube |
:seek 1:30 · :seek +30 | Jump to a time, or by an amount |
:speed 1.5 | Playback speed |
:vol 80 · :vol +10 | Volume |
:sub en · :sub off | Pick subtitles by language |
:quality 720 | Play at up to 720p, from now on (Q picks from a list) |
:sleep 30m · :sleep off | Pause after a while |
:shot | Save a screenshot to ~/Pictures |
:logout [server] | Forget the login for a server (and remove it from your keyring) |
:autoplay on · off | Same as M |
:dl | Download what's playing |
:clear | Empty Up next (u brings it back) |
:q · :qa | Hide the window · quit |
Links, streams and signing in
Press o, paste a link and Enter (or paste it into the YouTube search
box, or run drishya play <link>). drishya plays:
- HLS and DASH (
.m3u8, .mpd) from any server, live or not. A
stream that offers several qualities plays the best one up to your
quality.
- A video file on a server (
https://…/film.mkv), streamed as it plays.
- Any site yt-dlp supports (Vimeo, Twitch, Dailymotion, news sites…).
rtmp://, rtsp://, srt:// streams.
When the server answers that it needs a login (HTTP 401 or 403), a
sign-in panel opens: your username and password, sent as HTTP
authentication with every request, including each segment of a stream.
Tick Remember in my keyring (Ctrl+s) to keep it in your keyring
(through libsecret), else it's kept only until drishya quits. A site that
needs an account offers your browser's login instead (Ctrl+b: yt-dlp
reads its cookies). A link with the login in it
(https://user:password@host/…) works too: the login is taken out of
the link, so it never reaches the history or the queue file.
Configuration
~/.config/drishya/config.toml, everything optional:
[drishya]
quality = 1080 # highest resolution to stream or download
autoplay = true # more after your videos: related ones, or the next episode
resume = true # start where you stopped
seek_step = 10 # seconds for , and .
fine_step = 5 # seconds for h and l on the Watch tab
volume_step = 5
subtitles = "en" # your subtitle languages, e.g. "en,hi"
video_dirs = ["~/Videos"]
download_dir = "~/Videos/YouTube"
hwdec = "auto-copy-safe" # mpv's hardware decoding; "no" to turn it off
pause_on_hide = true # q pauses (z keeps a mini player going)
# opacity = 0.62 # the window's glass (unset: your theme's)
Styles: ~/.config/drishya/style.css is loaded after drishya's own.
State: ~/.local/state/drishya (history, queue, settings, downloads);
thumbnails: ~/.cache/drishya.
How it works
- One resident process (
drishya daemon, the app id dev.vayu.Drishya)
holds the player, MPRIS and downloads; drishya only sends it a D-Bus
message, so the window opens at once.
- The player is libmpv, bound with ctypes (
drishya/mpv.py): no extra
Python package. Its OpenGL renderer draws into a GTK GLArea; the mini
player takes the renderer over and gives it back.
- YouTube plays through mpv's own yt-dlp support, which picks the streams
(no AV1, which few laptops decode in hardware) and renews them. Search,
related videos and downloads call yt-dlp directly, never on the GTK
main loop.
- Logs go to stderr:
journalctl --user -u drishya with the service.
DRISHYA_DEBUG=1 shows debug messages.
Troubleshooting
- Black video, sound plays. Look at
journalctl --user -u drishya
for "OpenGL" or "video output". hwdec = "no" rules out hardware
decoding.
- YouTube says "Sign in to confirm you're not a bot". The sign-in
panel offers your browser's login (
Ctrl+b).
- A stream won't play. Try it in mpv (
mpv '<link>'); if mpv can't,
drishya can't either. A 403 often means the link expired: get a fresh one.
- No thumbnails for your files. Install ffmpeg.
Contributing
Bug reports, ideas and pull requests are welcome: see
CONTRIBUTING.md, and CHANGELOG.md for
what changed in each release.
drishya comes from Vayu, a
keyboard-driven Wayland desktop, and works on any Linux desktop on its own.
License
MIT