sanjay-np/nvim-yt-player

github github
media
stars 18
issues 0
subscribers 0
forks 1
CREATED

UPDATED


๐ŸŽต nvim-yt-player

CI Neovim Lua License PRs Welcome

A premium, lightweight, asynchronous YouTube music & audio player built directly inside Neovim.
Powered by pure Lua, UNIX domain socket IPC, mpv, and yt-dlp. Zero external servers. Zero editor lag.


โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Now Playing โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚  โ™ซ  Lofi Hip Hop Radio - Beats to Relax/Study to                          โ”‚
โ”‚     Lofi Girl                                                             โ”‚
โ”‚                                                                           โ”‚
โ”‚            โ–„โ–„โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–„โ–„               [ 01:42 / 03:30 ]                   โ”‚
โ”‚          โ–ˆโ–ˆโ–ˆ โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘ โ–ˆโ–ˆโ–ˆ            โ”โ”โ”โ”โ”โ”โ”โ”โ—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”                  โ”‚
โ”‚          โ–ˆโ–ˆโ–ˆ โ–‘โ–‘  โ—‰ โ–‘โ–‘ โ–ˆโ–ˆโ–ˆ                                                 โ”‚
โ”‚            โ–€โ–€โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–€โ–€               โ–ƒโ–…โ–ˆโ–‡โ–…โ–ƒ โ–ƒโ–…โ–‡โ–ˆโ–‡โ–…โ–ƒ                      โ”‚
โ”‚                                                                           โ”‚
โ”‚  ๐Ÿ”Š โ–ฐโ–ฐโ–ฐโ–ฐโ–ฐโ–ฐโ–ฐโ–ฑโ–ฑโ–ฑ 70%   โšก 1.0x   ๐Ÿ” Playlist   ๐Ÿ“ป Radio: ON                   โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

๐Ÿ’ก Why nvim-yt-player?

  • ๐Ÿš€ Save 1.5GB+ RAM: Stop keeping Chrome or Brave open with YouTube tabs just to listen to study/coding music in the background.
  • โšก Zero-Freeze Asynchronous IPC: Communicates directly with mpv over a local UNIX domain socket. Stream extraction and playback never block your editor or drop keystrokes.
  • โฉ Native SponsorBlock: Automatically skips sponsor segments, promos, and off-topic music intros so your focus is never broken.
  • ๐Ÿ“ป Endless Autoplay Radio: Automatically queries and queues fresh YouTube Mix recommendations matching your active track before the queue ends.
  • ๐Ÿ‘ฅ Multi-Instance Sync: Launch Neovim across multiple tmux panes or terminalsโ€”all instances automatically discover and coordinate playback with the shared background daemon.
  • ๐ŸŽ›๏ธ Zero Dependencies: Pure Lua + mpv + yt-dlp. No Python daemons, no Node.js processes, no Electron bloat.

โœจ Features

  • โšก Zero-Freeze Asynchronous Playback: Stream fetching and caching run entirely in the background. Neovim remains 100% responsive.
  • ๐Ÿ—๏ธ Zero-Dependency Backend: Pure Lua talking to a local mpv process over a UNIX domain IPC socket. No bloated servers or external daemons needed.
  • ๐ŸŽจ Premium Player Layouts:
    • :YT player โ€” Toggles a dedicated side-panel buffer featuring a beautiful custom ASCII bounding-box, a live bouncing music visualizer, an interactive progress slidebar, and volume/speed tracking.
    • :YT mini โ€” Toggles a gorgeous floating window with the same premium visual player layout.
  • ๐Ÿ” Interactive Search Picker (:YT search): Query YouTube and pick a result using a beautiful floating picker displaying channel names and track durations.
  • ๐Ÿ“ Local Playlists (:YT playlists): Save tracks instantly with s and manage them inside a split-pane local playlist manager.
  • ๐Ÿ“ Interactive Queue Editor (:YT queue_edit): Reorder tracks with J/K or delete them with dd in real-time.
  • ๐ŸŽต Seamless Playlist Ingestion (:YT queue_playlist): Rapidly ingest and parse YouTube playlists containing 100+ tracks without blocking the UI.
  • โฉ Auto SponsorBlock: Automatically skip sponsors, intros, and non-music off-topic segments (enable in config).
  • ๐Ÿ“ป Autoplay Radio Mode (:YT radio): Endless recommendation stream (enabled by default). Spawns the YouTube Mix playlist matching your active song, deduplicates against active queue and history, and seamlessly appends fresh tracks before your queue ends.
  • ๐Ÿ“Š Lualine & Statusline Integration: Formats playing state, volume, speed, and real-time progress bars smoothly for statuslines.
  • ๐Ÿ• Persistent Play History (:YT history): Stores recently played tracks so you can jump back or queue them later.
  • ๐ŸŽจ Currently Playing Track Highlight: The active track is visually highlighted in green across the queue editor, playlist manager, and history picker.
  • ๐Ÿ”” Customizable Notifications: Control the format of track-change notifications with placeholders like {title}, {artist}, and {icon}.

๐Ÿ“ฆ Requirements

Before installing, ensure the following commands are available in your system path:

  • Neovim 0.9+
  • mpv (configured with Lua support)
  • yt-dlp

๐Ÿ”ง Installation

Install using your favorite package manager:

lazy.nvim

{
  "sanjay-np/nvim-yt-player",
  dependencies = { "nvim-lualine/lualine.nvim" }, -- optional, for statusline component
  config = function()
    require("yt-player").setup({
      -- your configuration options here (see Configuration section)
    })
  end,
}

packer.nvim

use {
  "sanjay-np/nvim-yt-player",
  requires = { "nvim-lualine/lualine.nvim" }, -- optional
  config = function()
    require("yt-player").setup()
  end,
}

๐Ÿš€ Quick Start

  1. Start playing a URL immediately:
    :YT play https://www.youtube.com/watch?v=dQw4w9WgXcQ
    
  2. Search and select tracks interactively:
    :YT search lofi hip hop
    
    In the search picker window:
    • <CR> (Enter): Play selected track (replaces active playlist)
    • a / A / <C-a>: Append selected track to the active queue
    • s: Save selected track to a Local Playlist
    • gg: Jump to first result
    • G: Jump to last result
    • i: Re-enter insert mode to refine your query
    • q / <Esc>: Close the picker

๐Ÿ“‹ Command Reference

All functions are available under the master command :YT with rich autocomplete (press <Tab>!).

Subcommand Description
:YT play [url] Play a URL/search query, or resume playback
:YT pause Pause playback
:YT toggle Toggle play/pause
:YT stop Stop playback entirely
:YT next / :YT prev Skip to next or previous track
:YT seek <seconds> Seek to an absolute position (e.g. :YT seek 90 jumps to 1m 30s)
:YT seek_rel <ยฑseconds> Seek relatively (e.g. :YT seek_rel -10 seeks back 10 seconds)
:YT volume <0-100> Set playback volume
:YT vol_up / :YT vol_down Increase/decrease volume by 5%
:YT mute Toggle playback mute state
:YT speed [value] Adjust speed absolutely or relatively (Forms listed below)
:YT player Toggle the premium player side-panel
:YT mini Toggle the premium player floating window
:YT search [query] Open the interactive search picker
:YT queue <url> Append a track to the active queue
:YT queue_playlist <url> Parse and append all tracks from a YouTube playlist URL
:YT queue_edit Open the interactive queue editor
:YT playlists Open the split-pane local playlist manager
:YT radio Toggle autoplay radio mode (ON by default)
:YT history Open the persistent play history picker
:YT history_clear Clear play history
:YT resume Resume the last persistent playback session

Playback Speed Control Forms

  • :YT speed โ€” Display current speed in a notification
  • :YT speed 1.25 โ€” Set absolute speed (supports values between 0.25 and 3.0)
  • :YT speed up / down โ€” Adjust speed by +0.25 / -0.25
  • :YT speed +0.5 / -0.5 โ€” Adjust speed by a custom offset

๐ŸŽ›๏ธ Interactive Player Controls

When either the side-panel (:YT player) or floating window (:YT mini) is focused, you can control playback instantly using the following keymaps:

Keymap Action
p / s / t Play / Pause / Toggle
n / b Next / Previous track
m Mute toggle
+ / - Volume ยฑ5%
> / < Speed ยฑ0.25x
l / h Seek ยฑ5s (relative)
L / H Seek ยฑ30s (relative)
0 to 9 Seek to absolute percentage (0% to 90% of track)
G Seek to 100% (ends track)
R Cycle Repeat Mode (Track ๐Ÿ”‚ โž” Playlist ๐Ÿ” โž” Off)
r Toggle Autoplay Radio Mode
q / <Esc> Close player window

โš™๏ธ Configuration

Override defaults by passing options into setup():

require("yt-player").setup({
  statusline = {
    enabled = true,
    format = "{icon} {title} - {artist} [{position}/{duration}]",
    icon_playing = "โ–ถ",
    icon_paused = "โธ",
    truncate_title = 30,
    progress_width = 10,
  },

  search = {
    limit = 10, -- default number of results returned per search query
  },

  notifications = {
    enabled = true,
    notify_on_track_change = true, -- notify when a new song starts playing
    format = "โ–ถ {title} - {artist}", -- customizable notification format
    icon_playing = "โ–ถ", -- icon used in notification format
    icon_paused = "โธ", -- icon used when paused
    timeout = 3000, -- notification timeout in ms
  },

  player = {
    queue_display_limit = 5, -- number of upcoming tracks to show in the player layout
  },

  keymaps = {
    enabled = false, -- set to true to enable global keymaps
    prefix = "<leader>y",
    play = "p",
    pause = "s",
    toggle = "t",
    next = "n",
    prev = "b",
    mute = "m",
    volume_up = "+",
    volume_down = "-",
    seek_forward = "f",
    seek_backward = "r",
    speed_up = ">",
    speed_down = "<",
  },
  
  radio = {
    enabled = true, -- set to false to disable autoplay radio by default
    limit = 5,      -- number of related tracks to fetch at a time
  },
  
  youtube = {
    -- yt-dlp player clients used by mpv's ytdl_hook to resolve streams.
    -- YouTube currently 403-blocks stream URLs resolved via its default
    -- clients (ANDROID_VR/MWEB/WEB), causing tracks to skip instantly with
    -- no audio. Verified working: "android", "tv_simply", "web_music".
    player_client = "android,tv_simply",
  },
  
  sponsorblock = false, -- set to true to automatically skip YouTube sponsor segments
})

Statusline Customization

Use these placeholders to customize your statusline:

  • {icon} โ€” Play/Pause status icon (โ–ถ / โธ)
  • {title} โ€” Current track title
  • {artist} โ€” Channel / Uploader name
  • {position} โ€” Current playback position (e.g. 2:45)
  • {duration} โ€” Total track duration (e.g. 4:10)
  • {progress} โ€” Interactive progress bar (e.g. โ–“โ–“โ–“โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘)
  • {volume} โ€” Volume percentage
  • {speed} โ€” Speed multiplier (e.g. 1.25x)
  • {radio} โ€” Autoplay radio status icon (renders ๐Ÿ“ป when enabled)

Notification Customization

Use these placeholders to customize track-change notifications:

  • {title} โ€” Current track title
  • {artist} โ€” Channel / Uploader name
  • {icon} โ€” Playing icon (default โ–ถ)

Example configurations:

-- Minimal notification
format = "{title}"

-- Include artist
format = "โ–ถ {title} - {artist}"

-- With icon placeholder
format = "{icon} Now playing: {title}"

Lualine Integration

Add yt-player directly to your lualine configuration sections:

require("lualine").setup({
  sections = {
    lualine_x = { "yt-player" }
  }
})

Highlight Groups

All highlight groups can be customized to match your colorscheme. Override them in your Neovim config:

-- Player UI highlights
vim.api.nvim_set_hl(0, "YtPlayerTitle", { fg = "#bd93f9", bold = true })
vim.api.nvim_set_hl(0, "YtPlayerArtist", { fg = "#6272a4" })
vim.api.nvim_set_hl(0, "YtPlayerProgress", { fg = "#50fa7b" })
vim.api.nvim_set_hl(0, "YtPlayerProgressBg", { fg = "#44475a" })
vim.api.nvim_set_hl(0, "YtPlayerControls", { fg = "#8be9fd" })
vim.api.nvim_set_hl(0, "YtPlayerVolume", { fg = "#ffb86c" })
vim.api.nvim_set_hl(0, "YtPlayerVolumeBg", { fg = "#44475a" })
vim.api.nvim_set_hl(0, "YtPlayerRadio", { fg = "#ff79c6" })
vim.api.nvim_set_hl(0, "YtPlayerQueue", { fg = "#f8f8f2" })
vim.api.nvim_set_hl(0, "YtPlayerQueueCurrent", { fg = "#50fa7b", bold = true })
vim.api.nvim_set_hl(0, "YtPlayerBorder", { fg = "#6272a4" })
vim.api.nvim_set_hl(0, "YtPlayerHelp", { fg = "#6272a4" })

-- Currently playing track highlights (green by default)
vim.api.nvim_set_hl(0, "YTQueueCurrent", { fg = "#50fa7b", bold = true })
vim.api.nvim_set_hl(0, "YTPlaylistCurrent", { fg = "#50fa7b", bold = true })
vim.api.nvim_set_hl(0, "YTHistoryCurrent", { fg = "#50fa7b", bold = true })

๐Ÿ—๏ธ Architecture

Neovim (Lua) โ”€โ”€ UNIX Socket โ”€โ”€โž” mpv โ”€โ”€โž” yt-dlp โ”€โ”€โž” YouTube Stream

The plugin spawns a headless, detached background mpv process with IPC enabled. Multiple Neovim instances safely share the same mpv process via standard client process registration. The socket is automatically cleaned up when the last client closes.


๐Ÿ”ง Troubleshooting

  • Tracks skip instantly with no audio? YouTube is 403-blocking the direct stream URLs resolved by yt-dlp's default player clients (ANDROID_VR/MWEB/WEB). This plugin forces working clients via youtube.player_client (default android,tv_simply). If playback breaks again, switch to another verified-working client:
    require("yt-player").setup({
      youtube = { player_client = "web_music" }, -- or "android", "tv_simply"
    })
    
  • No Audio? Check that both mpv and yt-dlp are functioning correctly on your system by playing a URL directly:
    mpv --no-video "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    
  • Outdated yt-dlp? If YouTube streams fail to parse, update yt-dlp to get the latest decoders:
    yt-dlp -U
    
  • Warning: mpv exited? Ensure mpv is compiled with Lua support. Most native distribution package managers compile it with Lua support by default.
  • Searching Fails? Ensure Neovim has internet access and your geographic region is not blocked or rate-limited by YouTube's API filters.

โ“ FAQ

Q: Does this download videos to my computer?
A: No. It streams only the audio tracks in real-time, saving disk space and bandwidth.

Q: Can multiple Neovim instances control the same audio?
A: Yes! A shared client registry coordinates instances. When you start audio in one instance, others can view the statusline or control the active player.


๐Ÿค Contributing

Contributions, issues, and feature requests are welcome!
Check out our Contributing Guidelines to get started with local testing and architectural details.


๐Ÿ“„ License

Distributed under the MIT License. See LICENSE for more information.