📱 Подписаться
IT и цифровая трансформация

Видеоплееры живут в 2012 году, а мы — нет

📰 Habr 👁️ 0 просмотров

risen22812 часов назадОбъяснить с

Видеоплееры живут в 2012 году, а мы — нет

Уровень сложностиПростойВремя на прочтение18 минОхват и читатели6.6KСофтРабота с видео*Интерфейсы*Open source*macOS*КейсFrame PlayerВсе мы любим VLC. Он открывает что угодно, работает на всём, не просит денег и не спрашивает, кто ты такой. IINA на маке выглядит как нормальное приложение, а не как диалог из нулевых. mpv вообще эталон: лучшая картинка, скрипты, конфиг под любую паранойю. Это отличные плееры, я пользовался всеми тремя годами и не собираюсь объяснять, что их авторы что‑то делают не так.

Но однажды я поймал себя на мысли: 2026 год, вокруг десятки приложений, отполированных до состояния, когда интерфейса просто не замечаешь: он не мешает, он угадывает, он не заставляет вспоминать, где лежит нужная галочка. И ни одного такого видеоплеера. Хороших видеоплееров не существовало — не в смысле «не умеют открыть файл», а в смысле, в котором мы говорим «хорошее приложение» про всё остальное на своём компьютере. Поэтому я сделал свой.

Он называется Frame Player, он бесплатный и с открытым кодом, Windows и macOS. Дальше — список того, что меня в плеерах раздражало, и что с каждым пунктом в итоге получилось сделать.

Дело не в плеерах, а в том, что изменилось вокруг

В 2012 году задача формулировалась так: один компьютер, один монитор, файл на диске, надо открыть и показать. Плееры решили её полностью и с тех пор решают её же.

Посмотрим, из чего состоит просмотр видео сейчас:

• Телевизор в комнате сам декодирует 4K HDR лучше ноутбука, и файл хочется отправить на него, а не смотреть с колен.
• Близкие и друзья живут в других городах, и «давай посмотрим вместе» означает либо пляски в Discord с ужасным качеством, либо полностью скачанную копию у каждого.
• У серии три дубляжа и пять наборов субтитров, и выбор приходится делать заново каждую серию.
• Видео качается торрентом, а смотреть хочется сейчас, а не через сорок минут.
• Стриминги давно научились пропускать вступление одной кнопкой, а в плеере конец опенинга вы каждый раз ищете пальцем по таймлайну или мотаете позицию стрелкой.
• У меня Windows и мак, и на них стоят разные плееры с разными клавишами и повадками: один и тот же файл ведёт себя по‑разному в зависимости от того, за какой машиной я сижу.И ни один из этих пунктов не про «открыть файл». Поэтому плеер, идеально решающий задачу 2012 года, в 2026-м оставляет вас с шестью задачами, которые вы решаете вручную, каждый раз, по кругу.

Интерфейс, который не выглядит как что‑то из 2012 года

Начну с того, из‑за чего вообще изначально возникла идея своего плеера. Откройте любой из трёх любимых плееров и посмотрите на панель управления. Серая полоса под видео или поверх него, кнопки размером с пару пикселей, меню, в котором «Дорожки» живут рядом с «Соотношением сторон» и «Деинтерлейсингом». Всё работает, всё на месте... и всё выглядит как инструмент, а не как приложение.

Панели управления рядом друг с другом: mpv, VLC, IINA и Frame PlayerПроблема архитектурная, а не вкусовая. Исторически плеер — это окно, в котором рисует видеовывод, и элементы управления приходится либо рисовать тем же видеовыводом (так делает OSC в mpv — отсюда ограничения в типографике и анимации), либо раскладывать вокруг видео нативными средствами (так делает VLC — отсюда «диалог из нулевых»).

Я пошёл третьим путём: mpv рисует в нативное дочернее окно, а весь интерфейс — это современный веб‑апп в прозрачном webview поверх него. Видео никогда не попадает в DOM, то есть сохраняется настоящий путь вывода mpv: аппаратное декодирование, тональное отображение HDR, никакого копирования кадров. А интерфейс при этом можно делать так, как делают интерфейсы в 2026-м.

Что из этого получилось на практике:

• Шапка — часть плеера, а не полоска сверху. Заголовок с кнопками окна живёт в том же слое, что и панель управления, и уезжает вместе с ней — на маке за ней следуют и системные кнопки‑«светофор». В итоге при простое и в полном экране на экране остаётся только видео, без рамки, напоминающей, что это всё‑таки окно программы.
• Одна кромка на всё. Все края интерфейса — панель, таймбар, логотип, меню дорожек, кнопка «пропустить», показания — заканчиваются на 20 пикселях от края окна, причём отмеренных по глифу, а не по рамке кнопки. Это звучит как мелочь, пока не посмотришь на плеер, где отступы «на глаз» разные с четырёх сторон.
• Правый кластер кнопок складывается в одну, когда окно сужается. Не по брейкпоинту — ширина измеряется, потому что число кнопок зависит от файла: у одного есть субтитры и главы, у другого нет. Брейкпоинт в такой ситуации всегда либо срабатывает рано, либо выталкивает «play» из центра.
• Меню, диалоги и попапы — одна система, а не семь разных. Все диалоги собраны в одной оболочке, иконки — один набор с одной толщиной линии, а не сборка из того, что нашлось под рукой. И каждый список, который скроллится, честно это показывает: градиент с шевроном внизу вместо молча обрезанного края, чтобы не приходилось угадывать, есть там ещё строки или нет.
• Автоскрытие — это две настройки, а не одна. Панель: всегда / только в полном экране / никогда. Курсор — отдельно, потому что «спрячь курсор, но оставь панель» — нормальное желание, а в большинстве плееров это одна галочка на двоих.
• Мини‑плеер как режим окна: маленькое окно поверх всех, видео в углу, пока занимаешься чем‑то ещё. Мини‑плеер по‑умолчанию прилипает к ближайшему краю окна, у которого его отпустили.Демонстрация интерфейса Frame Player, включая контекстное меню

Телевизор, который не хочет проигрывать ваш файл

Самый частый бытовой сценарий и самое частое разочарование. Нажимаешь «Send to TV», на экране появляется имя файла — и чёрный кадр. Или всё начинает тормозить, потому что ноутбук втихую перекодирует 4K в реальном времени и не справляется.

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

Google Cast — это приёмник на самом устройстве, со своим списком форматов. MKV в этом списке нет вообще. Значит, либо перепаковка контейнера, либо перекодирование, либо чёрный экран.

DLNA — это встроенный плеер самого телевизора. Если телевизор умеет этот файл (а современные умеют почти всё), он берёт его как есть. Проверял на реальном наборе: 6,3 ГБ, 4K HEVC Main-10, ушло на телевизор без единого прикосновения к потоку.

При этом DLNA капризен в деталях, о которых не пишут. Телевизор отказывается от файла, чей MIME‑тип он сам не объявлял, а разные производители пишут Matroska по‑разному: video/x-matroska, video/mkv и video/x-mkv — это для него три разные строки. Куча программ отправляет одну фиксированную, телевизор отвечает «нет», и ни одна сторона не объясняет, что произошло.

Что я сделал: плеер спрашивает устройство, какие форматы оно объявляет, и отправляет ту строку, которую назвало именно это устройство. А в списке устройств рядом с каждым написано, что будет с этим конкретным файлом: уйдёт как есть, будет перепакован перед отправкой или не пойдёт вовсе. Это главное, чего мне не хватало: не «попробуй и посмотри», а вердикт до нажатия.

И ещё одна деталь, которую я нашёл, когда у меня самого телевизор перестал находиться: обнаружение устройств работает через multicast, а роутер не обязан пропускать multicast между диапазонами 2,4 и 5 ГГц. Поэтому поиск дополнительно опрашивает адреса локальной сети напрямую, по одному. Выглядит как грубая сила — зато телевизор находится.

Меню отправки видео на TV. Плеер сразу понимает, какой файл можно проиграть «как есть», а для какого нужна переупаковка

Кино вдвоём, когда вы в разных городах

Стандартные варианты: шеринг экрана в Discord и «на три‑два‑один нажимаем play». Первый даёт собеседнику сжатый поток, который разваливается на тёмных сценах, а на защищённом видео — чёрный прямоугольник, потому что DRM запрещает захват. Второй рассыпается на первой же паузе, потому что буферизация у всех разная.

Правильная модель обратная: каждый смотрит свою копию, а по сети едет только таймлайн. Так работает Syncplay, и так работает то, что я встроил в плеер.

Комната создаётся с кодом из шести символов. По сети передаётся снимок состояния после изменения: что играет, пауза или нет, позиция, скорость, время события. Не «действие», а именно состояние — потому что пакеты теряются и приходят не в том порядке, и из потерянного «нажал паузу» ничего восстановить нельзя, а из «вот как сейчас» можно всегда.

Две вещи, которые решают, живёт ли такая синхронизация на практике.

Первая: расхождение исправляется скоростью, а не перемоткой. Когда плееры разъехались на полсекунды, перемотка в 4K‑файле может встать на две секунды и оставить вас дальше от цели, чем до неё. Поэтому скорость подкручивается на пару процентов на несколько секунд, и позиции сходятся незаметно.

Вторая: комната знает, кто её держит. Если у одного началась буферизация, пауза ставится всем, а воспроизведение возвращается само, когда он догрузился. Звучит не серьезно, а по двухчасовому фильму экономит десяток вопросов «ты где?».

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

Страница захода в комнату Watch Together. Ссылку можно удобно отправить друзьям

Субтитры, которые разъезжаются

Самая частая жалоба в тредах про субтитры звучит так: «сдвигаю задержкой, к середине фильма опять мимо». И это не кривые руки, это две разные проблемы, из которых кнопка задержки решает одну.

Постоянный сдвиг — все строки опаздывают одинаково, от первой сцены до последней. Задержка лечит за один раз и навсегда.

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

Расхождение почти всегда означает, что субтитры делали к копии с другой частотой кадров: классика — 25 fps со старых европейских релизов против 23,976 современных. Разница около 4%: это 25 секунд к десятой минуте и примерно две с половиной минуты к концу часового эпизода. Лечится не задержкой, а растяжением: sub-speed = частота субтитров делить на частоту видео.

Что сделал я:

• Поиск на OpenSubtitles по хешу файла, а не по названию. Хеш считается от размера и первых с последними 64 КиБ, то есть опознаёт конкретный релиз, и то, что нашлось, уже совпадает с вашей копией — настраивать нечего.
• Если результат знает свою частоту кадров и она не совпадает с видео, плеер предлагает растяжение вместо того, чтобы молча отдать файл, который разъедется. И он именно предлагает, не применяет сам.
• Задержки запоминаются на файл, а не на сессию, потому что единожды подогнанные субтитры не должны требовать подгонки на следующий вечер.
• Пока панель управления поднята, строка субтитров уезжает выше неё. Казалось бы, ерунда — а реплику закрывает ровно в тот момент, когда её читают, потому что панель поднялась от того, что вы двинули мышь.Интерфейс поиска субтитров на OpenSubtitles

Дорожка, которую помнят по описанию, а не по номеру

Мелочь, которая бесит каждую серию. Выбираешь нужный дубляж в первой серии, открываешь вторую — играет не то.

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

Но даже если плеер эту проблему решает, часто остаётся вторая: дорожки запоминаются по идентификатору, а идентификатор дорожки — это её позиция внутри конкретного файла. Дубляж, который в первой серии второй, во второй серии бывает третьим, потому что релизер положил ещё одну аудиодорожку. Плеер, который запомнил «дорожка № 2», ошибается до конца сезона.

Поэтому в моём плеере выбор хранится как описание: язык, название, кодек. На следующем файле ищется наиболее похожая дорожка, а не та же позиция. Область памяти — папка, а не файл: сериал обычно лежит в одной, и выбор, сделанный на первой серии, должен действовать на всю.

Отдельно пришлось разобраться с вопросом «не показывай субтитры на языке, который я и так слышу». У mpv для этого есть своя опция со значениями «нет / только форсированные / да», и по умолчанию она включена — то есть субтитры к дубляжу на том же языке по умолчанию не появляются. Полезно знать, прежде чем искать баг там, где его нет.

В стримингах есть «пропустить вступление». Почему её нет в плеерах?

Любой стриминг десять лет умеет показывать кнопку на опенинге и на титрах. Сериал на двадцать серий — это двадцать опенингов, и каждый из них вы либо смотрите заново, либо перетаскиваете таймлайн пальцем, целясь мимо.

Почему этого нет в плеерах, понятно: стриминг знает про свой каталог всё, у него на каждую серию лежит разметка, полученная автоматическим анализом и правками редакторов. У локального плеера такой разметки нет.

Зато у файла часто есть главы — и особенно у аниме‑релизов и ремуксов, где они подписаны: Opening, Intro, Recap, Preview, Ending, Credits. То есть разметка уже лежит в контейнере, просто ни один плеер не делает из неё ничего, кроме пунктов в меню «Главы».

Поэтому: если текущая глава называет себя вступлением, пересказом предыдущей серии, превью следующей или титрами, в первые секунды этой главы появляется кнопка «Пропустить». Нажали — оказались в следующей главе. На последней главе та же кнопка становится «Следующая серия», и Enter отвечает и там и там, так что вслепую, не глядя на экран, работает одинаково.

Одна деталь, на которой легко обжечься: сравнивать название главы нужно целиком, а не по подстроке. Глава «Ending the war» — это не финальные титры, и человек, который нажмёт на такую кнопку, потеряет полчаса фильма. Поэтому совпадение только по полному названию, из закрытого списка слов.

Пропуск вступления — определяется по названию главы, проверено на различных эдж‑кейсахИ честная граница: если у релиза глав нет вообще, предложить нечего. Определять опенинг по звуковому отпечатку, как это делают стриминги со своим каталогом, плеер не умеет, и обещать этого я не буду.

Торрент, который можно смотреть сейчас

Если файл всё равно качается, ждать его целиком — странно. Поэтому плеер умеет открывать торрент как источник: отдаёт файл сам себе по локальному HTTP, а mpv читает его диапазонами байт.

Из этого получается главное свойство: загрузка идёт за тем, что вы смотрите. Каждое чтение говорит торрент‑клиенту, где находится воспроизведение, поэтому куски прямо перед курсором запрашиваются первыми, а перемотка не ждёт, а переставляет приоритеты. На таймлайне закрашено то, что уже на диске, так что видно, прыгнет ли воспроизведение сразу или подождёт раздачу.

Несколько решений, которые я считаю важными:

• Ничего не качается наперёд просто так. Из сезона качается та серия, которую открыли, и ровно одна следующая — после того, как текущая дособралась.
• Раздача выключена по умолчанию (но включить её можно). В Германии и ряде других стран ответственность за отдачу категорически хуже, чем за загрузку, и плеер не должен подписывать на это человека, который просто нажал play. При этом в настройке честно написано, что это не делает вас невидимым: пиров всё равно приходится искать через трекеры и DHT.
• Шифрование соединений, SOCKS5-прокси и выбор сетевого интерфейса — для тех, у кого VPN и торренты не дружат. Маршрут, который нельзя обеспечить, приводит к отказу от раздачи, а не к тихому выходу «как получится».
• Субтитры, лежащие внутри раздачи, подключаются сами и соаавляются с той серией, которую вы открыли.
• Торрент, который ещё качается, можно отправить на телевизор и смотреть с другим человеком через комнату Watch Together — он подключается к той же раздаче сам, никто ничего никому не пересылает вручную.Tears of Steel, свободный фильм Blender Foundation. Полосы на таймлайне — карта буфера: в приоритете скачиваются куски ближе к текущему месту проигрывания

Сеть говорит «нет» двумя разными способами

Самая неприятная поломка выглядит так: пиры нашлись, часть подключилась, скорость ноль. Изнутри плеера непонятно ничего, а qBittorrent на этой же сети качает.

Причины две, и лечатся они по‑разному.

Первая: сети не нравится, что это за трафик. Обычное рукопожатие BitTorrent начинается с опознаваемой строки BitTorrent protocol, и провайдерский DPI обрывает соединение, едва оно установилось. Снаружи это выглядит как пир, который подключился и тут же умер.

Лечится шифрованием соединений (MSE): после обмена ключами в начале соединения нет узнаваемых байтов, и отличить торрент от любого другого потока уже нельзя. В библиотеке, на которой построены торренты в плеере, такого шифрования нет ни в одном релизе. Зато оно есть в открытом пулл‑реквесте к ней — это чужая работа, которую я взял целиком и везу в своём репозитории, пока её не примут в основную ветку.

Перед тем как тащить к себе полторы тысячи строк чужого кода, я проверил четыре вещи: накладывается ли патч на нашу версию, собирается ли, проходят ли его собственные тесты и — главное, чего чтением не узнать — работает ли это с живым роем. В самом строгом режиме, где пир без шифрования просто отбрасывается, магнет нашёл раздачу за 0,8 секунды, и файл пошёл на 2,2 МБ/с с 24 пиров.

Вторая: сети не нравится, куда трафик идёт. Если мешает провайдер, помогает SOCKS5-прокси. А вот если торренты запрещает ваш VPN — обычная политика коммерческих сервисов, — прокси не спасает: дело не в адресате, а в том, что весь трафик уходит в туннель.

Решение — не менять маршруты в системе, а привязать соединения к конкретному сетевому интерфейсу. Тогда маршрут VPN, который живёт на своём адаптере, просто не рассматривается. Привязывать надо всё разом: пиры, DHT, трекеры, поиск в локальной сети, проброс порта — одного забытого сокета достаточно, чтобы вся затея потеряла смысл.

В библиотеке это было сделано для macOS и Linux, а на Windows она честно отвечала «не поддерживается». Эту половину пришлось написать самому, и там есть ровно одна ловушка, на которой легко молча проиграть: номер интерфейса для IPv4 и для IPv6 передаётся в разном порядке байт. Перепутаете — код соберётся, запустится и не ограничит ничего.

Замеры на macOS: мимо туннеля около 4 МБ/с с 26 пиров, контрольный прогон через туннель — ни байта за минуту. На Windows я пока только собрал и проверил компилятором, живого теста с поднятым VPN ещё не было, и до него писать «работает» нечестно.

Два правила оказались важнее самого механизма. Если выбранный маршрут обеспечить нельзя, плеер отказывается качать, а не едет «как получится», — иначе трафик уйдёт ровно туда, куда просили не отправлять. И цена названа там же, где предлагается выбор: в обход VPN рой видит ваш настоящий адрес.

Что нашлось по дороге. Пока я выяснял, почему торренты не качаются, в клиенте трекеров обнаружились три ошибки, каждая невидимая снаружи: терялась часть адреса анонса, и приватный трекер отвечал отказом; не отправлялся заголовок User‑Agent, а без него сервер трекера отдавал 403 и отдавал 200 с ним, причём содержимое заголовка не играло роли; и ответ трекера не разбирался целиком, если в нём не было счётчиков сидов и личей, — а значит, все пиры из этого ответа выбрасывались. Все три исправления теперь в самой библиотеке. Отдельная история — DHT на Windows: там обычные сетевые ошибки приходят постоянно, а библиотека роняла от них весь поиск пиров. Стоковая версия умирала через полторы минуты и до перезапуска приложения больше не находила ничего.

И то, чего в плеере нет сознательно: он приезжает без единого адреса для поиска торрентов. Панель каталога умеет работать с Torznab‑совместимым индексатором — Prowlarr, Jackett, что у вас поднято, — и поле пустое, пока вы не вставите свой адрес. Плеер ничего не подсказывает и никаких списков не везёт.

Картинка: почему на маке темнее и что делать с полосами

Жалоба «mpv показывает кино темнее, чем QuickTime» ходит по форумам годами, и в ответ обычно дают рецепт из трёх опций и ICC‑профиля. Я решил измерить это.

Один и тот же кадр H.264 вообще без цветовых метаданных, QuickTime и плеер на mpv, один дисплей, сравнение по числам:

• серый Y=64 — QuickTime 63,3, mpv 55,5
• серый Y=128 — QuickTime 140,0, mpv 128,7
• ночной кадр, полутона — 102,1 против 92,8Три вывода, из которых два меня удивили. Отсутствие метаданных — не причина: копия с тегом BT.709 измеряется точно так же, QuickTime просто читает BT.709 более мягкой кривой. Провисают нижние полутона, а не глубокие тени — до 12 уровней между Y=40 и Y=160, при этом самые тёмные ступени в mpv даже чуть светлее. И популярный рецепт даёт правильную кривую и неправильный цвет: на macOS система уже управляет цветом окна, ICC добавляет второе преобразование, и красный BT.709 уезжает с 232,51,35 на 213,68,49.

В плеере это стало настройкой из двух положений: кривая mpv или кривая macOS. Второе — это комбинация из четырёх опций, подобранная по этим замерам, а не ICC‑профиль.

Заодно про полосы. Чёрные поля, впечатанные в кадр, плеер измеряет сам по яркостной плоскости нескольких кадров из разных мест файла и либо обрезает по измерению, либо по выбранной форме. Режим живёт на плейлист, а прямоугольник на файл: в сериале кадрирование одинаковое, а в сборной папке — нет. Яркость, контраст, насыщенность и гамму можно держать отдельно для файла, для плейлиста или для всего, и при перетаскивании ползунка меню становится полупрозрачным, чтобы было видно, что меняется.

Мелочи, которые заметны только когда они работают

Этого в заголовки не тавишь, но из этого состоит ощущение, что приложение не спорит с тобой.

Превью на таймлайне показывает кадр, на который вы попадёте. Обычно превью берётся с сетки и округляется до кейфрейма — на часовом фильме шаг сетки доходит до десяти секунд, то есть вы наводитесь на одно, а попадаете в другое. Здесь при остановке курсора кадр декодируется по точной позиции, а превью сохраняет пропорции самого видео, а не условные 16:9.

Позиция и «продолжить смотреть». Файл попадает в историю, только когда просмотрено больше минимума, и уходит из неё, когда досмотрен. На стартовом экране показывается то название, которое показывал плеер, а не имя файла: путь пишут для сортировки, а не для чтения.

Вашmpv.confостаётся вашим. Настройки переписывают только те строки, которые сами же и ставили, и в подвале показывают, какое декодирование реально используется сейчас, — потому что тихий откат на программное незаметен и объясняет половину жалоб на «тормозит перемотка».

Все действия переназначаются, и привязаны к физическим клавишам, а не к символам, поэтому работают в любой раскладке.

Ни аккаунта, ни телеметрии. Папки можно пометить приватными: то, что в них, не попадает в историю и в «продолжить смотреть».

Авто‑обновления. При новых релизах в шапке появляется кнопка с номером версии и предложением обновиться, а при наведении можно увидеть перечисление изменений. Кстати, генерация changelog'а встроена в процесс разработки через changesets и результат автоматически попадает сразу в 3 места: в кнопку обновления в плеере, в релиз на GitHub, и в раздел на сайте.

Чего в плеере нет

Раз уж я начал с того, что чужие плееры в чём‑то плохи, честно будет про свой.

• Это не нативное приложение. Интерфейс — веб‑технологии в нативном окне. IINA из нативнее и останется такой. Я считаю это осознанным обменом: интерфейс, который рисуется поверх видео и так себя ведёт, я получил намного быстрее и в том виде, в каком хотел. У webview есть недостатки, особенно они заметны при ресайзе окна, но я очень постарался замаскировать все такие кейсы — сейчас увидеть какую‑то проблему практически невозможно
• macOS только на Apple Silicon. На Intel‑маке остаётся только IINA.
• Windows‑сборка не подписана. Сертификат для частного лица — это проверка личности, аппаратный токен и годовая плата, после которой SmartScreen всё равно предупреждает, пока у файла не наберётся установок. Для бесплатного проекта это огромные неудобства без выгоды, поэтому при первом запуске будет предупреждение. Сборки делает публичный CI, и это на вопрос «что я запускаю» отвечает лучше подписи.
• Нет Linux‑сборки.
• Это не сервер и не медиатека по вашим файлам. Своей полки с постерами из того, что лежит у вас на диске, здесь нет, как нет сервера и клиентов на телевизор и телефон — для этого есть Plex и Jellyfin. Каталог в плеере отвечает на другой вопрос: не «что у меня есть», а «что посмотреть», и работает он с тем индексатором, адрес которого вы дали.

Как это сделано

Tauri 2, Svelte 5, libmpv через --wid. На Windows mpv рисует в дочерний HWND, на macOS — в NSView, и там же находится самое неприятное место проекта: штатный mpv на macOS--widне реализует вообще, поэтому сборка несёт патч. Если вы когда‑нибудь будете встраивать mpv в собственное окно на маке — он и объяснение к нему лежат в репозитории, это сэкономит вам время.

Весь код почти целиком написан ИИ‑агентами, и интересным в этом оказался не сам факт, а то, что из‑за него пришлось встроить в проект: набор проверок, которые ловят классы ошибок, не видимых ни на ревью, ни в собранном выводе. Правило состояния, которое не компилируется, пока человек не решит, что делать с потерянным событием. Таблица, из‑за которой новое действие — ошибка компиляции, пока его не классифицировали. И история про 256 файловых дескрипторов на macOS, из‑за которых видео не играет вообще, а в логах не остаётся ничего. На каждую из этих историй хватит отдельной статьи.

И ещё один вывод, который стоит сказать прямо: без ИИ у меня не получилось бы собрать такой плеер за два месяца. И это возвращает к главной теме статьи — странно оставлять всё как в 2012 году, когда прямо перед тобой лежит возможность сделать удобнее и современнее.

Ссылки

• Сайт
• РепозиторийПлеер бесплатный, GPL-3.0, Windows и macOS, полностью открытый код.

Если какие‑то мелочи раздражали или раздражают вас в видеоплеерах — расскажите, какие. Многие доработки появились именно из фидбека: спасибо пользователю «citizen_of_glass» с Reddit =)Теги:• видеоплеер
• mpv
• libmpv
• tauri
• rust
• торренты
• dlna
• субтитры
• ui
• uxХабы:• Софт
• Работа с видео
• Интерфейсы
• Open source
• macOS

Получайте больше инсайтов о систематизации бизнеса

Подписывайтесь на Telegram-канал Business Operations — ежедневные материалы о бизнес-процессах, операционном управлении и повышении эффективности

💬 Подписаться на канал