UnbloatedTube: я написал свой YouTube-клиент, чтобы не копить вкладки

Draft

Браузер был забит вкладками YouTube, которые я собирался посмотреть позже и не смотрел. Ролик про GPUI разжёг любопытство, и я с помощью ИИ собрал небольшой десктопный клиент на Rust: mpv для воспроизведения, yt-dlp для данных, настоящая вкладка «Смотреть позже», очередь Up next и страница настроек, где любой элемент можно отключить.

UnbloatedTube: слева список истории, справа плеер, кнопки действий и вкладки «Recommended», «Watch later», «Comments» и «Up next»

Мой браузер вечно заполнен вкладками YouTube. Каждый раз, когда я вижу что-то, что хочу посмотреть, я открываю это в новой вкладке «на потом» вместо того, чтобы реально это сохранить. Вкладки копятся, а потом я про большинство из них забываю. И всё повторяется.

Сам интерфейс YouTube мне тоже никогда не нравился. Зачем бы я ни пришёл, рядом всегда лента, боковая панель и ряд рекомендаций, которые борются за один и тот же клочок экрана. Так что я сделал то, что обычно делаю с неудобством, которое достаточно мало, чтобы его починить: написал под него инструмент.

Получился UnbloatedTube (поначалу он назывался unbloated-youtube) — небольшой десктопный клиент YouTube для Linux. Он показывает подписки, плейлисты и историю, воспроизводит видео в mpv и хранит «посмотреть позже» как настоящий список, а не кладбище вкладок.

Стек
Rust, GPUI, mpv, yt-dlp
Платформа
Linux (X11 и Wayland); Windows и macOS в планах
Статус
Альфа — пользуюсь каждый день, но шероховатости будут
Установка
GitHub releases (архив, AppImage) · AUR · Nix flake
Лицензия
MIT

Откуда взялась идея

Всё началось с видео. Я посмотрел ролик Syntax I’m Using GPUI For Everything. GPUI — это UI-фреймворк на Rust, на котором сделан редактор Zed, и до этого я знал его только как «то, из чего сделан Zed». Когда я увидел, как его используют для всего подряд, а не только для редактора, мне стало достаточно любопытно, чтобы попробовать самому.

От фреймворка, о котором ты только посмотрел видео, мало толку, поэтому нужен был проект. Проблема с вкладками была прямо перед глазами. Я открыл репозиторий, запустил сессию с Claude Code и описал, что хочу: окно, в котором можно листать YouTube, смотреть видео и откладывать ролики в список, а не во вкладку.

Первая версия была просто окном, которое умеет проигрывать видео. Чтобы из демки получилось то, чем я реально пользуюсь каждый день, потребовалось много сессий — об этом большая часть статьи.

Что это такое

Вся идея в том, чтобы переиспользовать готовое, а не писать заново:

  • GPUI рисует интерфейс.
  • mpv воспроизводит видео. Он встроен в окно, поэтому плеер ощущается частью приложения.
  • yt-dlp поставляет данные: списки видео, результаты поиска, ссылки на потоки.
  • YouTube InnerTube API отвечает за действия, меняющие ваш аккаунт: подписаться, лайкнуть, сохранить в плейлист, «Смотреть позже». Вход идёт через сессию YouTube из вашего браузера, так что пароль приложение не видит никогда (подробнее ниже).

Всё медленное — yt-dlp, сетевой запрос или обращение к mpv — выполняется в фоновом потоке, так что интерфейс никогда не ждёт. Списки кэшируются на диске и при следующем открытии появляются мгновенно, а потом обновляются в фоне.

Настраивайте то, что нужно, и скрывайте остальное

«Unbloated» здесь значит вполне конкретную вещь: приложение не решает за вас, какие части YouTube вам нужны. Почти каждый элемент — это переключатель на странице настроек, и на этой же странице есть поле поиска, так как переключателей хватает.

Страница настроек: переключатели Subscriptions, Playlists, History, Recommendations, Chapters, Comments и вкладки Watch later
Страница настроек: подписки, плейлисты, историю, рекомендации, главы, комментарии и вкладку Watch later можно показывать или скрывать по отдельности.

Не нужны рекомендации под плеером? Выключите. Комментарии по умолчанию выключены и загружаются только когда вы открываете их вкладку. У каждой кнопки действия (подписка, лайк, дизлайк, поделиться, скачать, открыть в браузере) свой переключатель, так же как у числа просмотров, даты загрузки и числа подписчиков. Если часть интерфейса вам не нужна, она исчезает.

«Смотреть позже» вместо новых вкладок

Ради этой возможности всё и затевалось.

  • Вкладка Watch later рядом с Recommended, Comments и Up next. Это ваш настоящий плейлист YouTube «Смотреть позже», он загружается при открытии вкладки, а у каждой строки есть кнопка удаления.
  • Кнопка «Смотреть позже» на каждом видео в каждом списке. Наведите курсор на видео в подписках, в результатах поиска, в рекомендациях или в истории и нажмите её. Открывать видео не нужно, и новая вкладка не появляется. Для воспроизводимого видео есть ещё и горячая клавиша.
  • Очередь Up next для «вот это — следующим». Добавляйте что угодно кнопкой + в строке; автовоспроизведение сначала идёт по очереди и только потом возвращается к списку, из которого вы выбрали видео.

Ещё две кнопки, которыми я пользуюсь постоянно: Download — скачивает видео через yt-dlp — и Open in browser — для редкого видео, которому действительно нужна страница YouTube. Обе работают одним кликом или одной клавишей и больше ничего в окне не меняют.

Тот же подход «сначала списки» идёт дальше. Подписки — это обычный список каналов, где каналы с новыми видео подняты наверх и рядом стоит счётчик непросмотренного. Каналы можно раскладывать по своим группам (Музыка, Tech) и фильтровать ленту по группе. Группы живут только в приложении, не на YouTube. История запоминает, где вы остановились в каждом видео, и предлагает «Continue watching».

Сделано для клавиатуры

Значительную часть дня я провожу в терминале, поэтому приложение должно было работать без мыши. В плеере есть ожидаемые клавиши (пробел, стрелки, j и l — на десять секунд, f — полный экран, m — без звука), ? показывает их все, а цифры переключают вкладки.

Есть и необязательный Vim-режим. Он добавляет движение по спискам клавишами j/k и режим подсказок в стиле Vimium: нажмите f, и у каждого кликабельного элемента появится короткая метка. Наберите её — и это как клик.

Режим подсказок: жёлтые двухбуквенные метки над каждой вкладкой, переключателем, кнопкой и строкой списка
Режим подсказок: у каждой вкладки, переключателя, кнопки и строки списка есть метка. Наберите её, чтобы кликнуть.

Так достижимо вообще всё, в том числе то, на что я никогда не стал бы вешать отдельное сочетание клавиш.

Доступность: заметное кольцо фокуса

Режим подсказок — для тех, кому он нравится. Работа с фокусом — для всех. Tab и Shift+Tab двигают видимое кольцо по каждой кнопке, строке и переключателю, а Enter или Space нажимают то, на чём стоит кольцо. Esc убирает его.

Кольцо фокуса по Tab: красная рамка вокруг переключателя Subscriptions на странице настроек
Кольцо фокуса на странице настроек: Tab двигает его, Enter или Space нажимают.

Мне не хотелось клиента, который удобен только тому, кто совпал со мной по раскладке клавиш, а видимое кольцо — самый дешёвый способ сделать так, чтобы пользователь клавиатуры никогда не терялся.

Как это сделано вместе с ИИ

Хочу честно рассказать, как это создавалось. Большую часть кода на Rust написал ассистент. Моя часть — решать, что приложение должно делать, пробовать его в реальной работе и говорить, что не так. У такого подхода есть конкретные последствия:

  • Автоматических тестов нет. Изменения интерфейса ассистент проверяет, запуская приложение на отдельном X-дисплее, управляя им через xdotool и снимая скриншоты, а затем смотрит на эти скриншоты. Это медленнее юнит-тестов, зато ловит то, что юнит-тесты не поймают никогда, например меню, свисающее за нижний край окна.
  • Мои баг-репорты были скриншотами. Большинство исправлений начиналось с того, что я вставлял картинку и говорил: «вот тут неправильно».
  • Мне приходилось всё время решать, чем является приложение. Ассистент с радостью добавит функцию под каждую идею. Страница настроек существует потому, что я раз за разом просил сделать что-то необязательным.

Несколько проблем оказались поучительными:

  • Видео — не моё окно. В X11 mpv рисует в собственном нативном дочернем окне поверх области видео. GPUI не может рисовать поверх него, поэтому любое меню или подсказка, заходящие на видео, прячутся под ним. Новые такие случаи я находил снова и снова. Теперь меню держатся внутри левой колонки, а оверлей сохранения в плейлист скрывает видео, пока открыт, но подсказки поверх видео остаются известным ограничением.
  • Моё окно было больше экрана. Оно открывалось фиксированного размера, а при масштабировании дисплея могло оказаться выше экрана, и низ правой колонки (включая кнопку «Load more comments») уезжал за край. Теперь окно открывается не больше экрана.
  • Комментарии неудобны. yt-dlp не умеет отдавать комментарии потоком, поэтому «Load more» перезапрашивает всё с начала с большим лимитом, и каждый следующий клик медленнее предыдущего. Нормальное решение — говорить с InnerTube напрямую.
  • Время компиляции. В дереве зависимостей около 730 крейтов, в основном из-за GPUI. Чистая сборка в Nix заняла у меня 26 минут. Никому не стоит такое ждать, поэтому каждый раз, когда я пушу тег, workflow в GitHub Actions собирает бинарник примерно за семь минут.

Установка

Нужны mpv и свежий yt-dlp (старые версии YouTube ломает быстро), а также deno — через него yt-dlp решает JavaScript-задачи YouTube. Дальше выберите один способ:

Arch / AUR
yay -S unbloatedtube-bin
Nix
nix run github:antlis/UnbloatedTube

Либо скачайте архив для Linux x86_64 или AppImage со страницы релизов. В AppImage на всякий случай уже есть свои yt-dlp и deno, так что поставить останется только mpv. Релизы делаются по тегу: workflow всё собирает, публикует релиз и обновляет пакет в AUR, так что AUR-версия следует за GitHub без моего участия.

Поиск и воспроизведение работают без аккаунта. Для подписок, плейлистов, истории и кнопок аккаунта при первом запуске приложение предложит Connect YouTube: выбираете браузер, в котором вы вошли в YouTube, и приложение читает оттуда сессию и проверяет её. Пароль оно не спрашивает и не хранит, а в браузере вы остаётесь залогинены.

Что изменилось с первой версии

Первая версия этого поста заканчивалась списком хотелок. Большую часть из него я сделал:

  • Wayland. В X11 mpv может рисовать в дочернее окно, а в Wayland такого нет. Поэтому там приложение запускает mpv как библиотеку (libmpv) внутри своего процесса и рисует видео в subsurface своего окна через OpenGL. Где оно запущено, приложение определяет само.
  • Каст. Целью может быть любая команда — для Chromecast это одна строчка с catt. Но больше всего мне хотелось отправлять видео на свою ТВ-приставку с tg-mpv-bot: приложение говорит с её HTTP API, отправляет видео (или целый плейлист, или очередь Up next), и дальше привычные клавиши и полоса прогресса управляют телевизором, а не локальным плеером.
  • Нормальный вход вместо строчки в config.toml — тот самый экран Connect YouTube.
  • Вкладки с описанием и расшифровкой. Таймкоды в описании и комментариях перематывают видео; по расшифровке можно искать, а клик по строке переносит в этот момент.
  • Меньше шума — по желанию. Shorts можно выключить везде, SponsorBlock пропускает рекламные вставки, DeArrow заменяет кликбейтные заголовки и превью, а Return YouTube Dislike возвращает счётчик дизлайков.
  • Больше способов установки: к архиву и AUR добавились AppImage и Nix flake.
  • Новое имя. unbloated-youtube стал UnbloatedTube (unbloatedtube или просто ubt). Старая команда, пакет в AUR и выход Nix продолжают работать как алиасы.

Одну функцию я вообще не планировал: там, где YouTube замедляют, видео просто зависает. В Settings → Network есть режим Bypass slowdown, который делает то же, что ByeDPI и zapret, но встроенно. Фильтр узнаёт YouTube по имени сервера в первом пакете каждого TLS-соединения, поэтому приложение режет этот пакет прямо посередине имени. Фильтр его не видит, а серверы YouTube собирают пакет обратно и ничего не замечают. Есть и обычный режим Proxy для Tor или ByeDPI, и кнопка Test connection, которая объясняет, почему маршрут не работает.

Что дальше

Это всё ещё альфа. Что осталось, примерно по порядку:

  • Windows и macOS. Весь платформенный код уже собран в одном модуле, но самое сложное — встроенный плеер, и к нему я ещё не подступался.
  • Комментарии получше: ответы, сортировка и подгрузка через InnerTube вместо перезапроса с начала на каждый «Load more».
  • Управление плейлистами: создавать, переименовывать и переупорядочивать, а не только добавлять в них.
  • Экспорт и импорт настроек и групп каналов, которые сейчас лежат в одной папке на одной машине.
  • Открытие ссылок YouTube из других программ в приложении, а не в браузере.

Я перестал смотреть YouTube в браузере — ради этого всё и затевалось. Если попробуете и что-то сломается, заведите issue — в README описаны все возможности и сочетания клавиш.