У Apple Studio Display есть один нюанс, о котором не пишут в рекламе.
За пару тысяч долларов вы получаете великолепный 5K-монитор: честная цветопередача, приличные динамики, фирменный алюминий и общее ощущение «дорого-богато».
А ещё — ни одного видеовхода.
Нет HDMI.
Нет DisplayPort.
Нет даже намёка на что-нибудь, куда можно воткнуть игровую консоль.
Только Thunderbolt.
То есть монитор искренне убеждён, что единственное живое существо во вселенной, достойное подключения к нему, — это Mac. Всё остальное — плебс.
А у меня, как назло, накопился этот самый плебс:
Nintendo Switch 2 — вечерний уют, Animal Crossing и Mario Kart;
Steam Deck — вся Steam-библиотека в кармане, но на маленьком экране;
Xbox — потому что «ну а вдруг».
И все три очень хотели на большой красивый 5K-экран. А экран смотрел на них, как швейцар дорогого отеля на человека в шлёпанцах.
Готовое решение: capture card + OBS
Интернет, конечно, эту задачу давно решил. Схема известная:
Консоль │ HDMI ▼ Capture Card │ USB ▼ OBS │ ▼ Studio Display
Берём карту захвата, берём OBS, показываем окно превью на весь экран. Всё.
Я так и сделал. Картинка появилась. Звук появился.
На этом статья могла бы закончиться.
Если бы в этом можно было играть.
Когда «вроде работает», но играть невозможно
Технически всё работало. Изображение есть, звук есть, консоль жива.
А потом я взял в руки геймпад.
И почувствовал, что где-то между мной и телевизором поселился призрак с пингом. Не «чуть-чуть не 60 fps» — а честные низкие двадцатые, что-то между слайдшоу и «ну почти терпимо». Персонаж реагировал на кнопку с ощутимой задержкой, будто я играю не на консоли рядом, а по удалённому рабочему столу через кофейню на другом конце города.
В Mario Kart это раздражало. В Smash Bros уже реально мешало. А Steam Deck, который умеет в честные 60 через свой же экран, через эту цепочку превращался в диафильм.
OBS при этом никаких fps не показывал — я не сидел с калькулятором. Просто играть было некомфортно, субъективно — двадцать с хвостиком, не шестьдесят.
И вторая беда — картинка. Studio Display — это 5120×2880. Консоли отдавали по HDMI максимум 4K (а я гонял вообще в 1080p). Любой вывод на весь экран — это гигантский апскейл. Без нормального масштабирования на 5K всё выглядело мыльно, как будто монитор за две тысячи долларов специально напоминает: «ты подключил ко мне не то».
Мне стало интересно:
Куда деваются миллисекунды — и можно ли сделать, чтобы на 5K не было так стыдно?
Где рождается задержка
На первый взгляд тракт простой. На практике каждый этап тихонько докидывает свои миллисекунды:
Консоль → HDMI → Capture Card → USB → OBS → Композитор macOS → Studio Display
Каждое звено — немного. Все вместе — уже чувствуется пальцами.
И тут выяснилось, что OBS для моей задачи — двойной перебор:
По функциям. Стримы, записи, сцены, десять источников, наложения. Мне нужно было ровно одно: показать кадр с карты на весь экран.
По латентности. Даже без замеров было ясно — отклик «мимо», всерьёз играть не хочется.
Мне не нужен был ещё один комбайн для стримеров. Мне нужен был скальпель: взять кадр с карты и положить его на экран — быстро и без мыла.
Так родилась идея написать своё.
Что я хотел получить
Не стрим. Не запись. Не монтаж. Не десять источников.
Только:
Консоль на Studio Display. Со звуком. В fullscreen. Чтобы не бесило.
Я программист, но не стример, и не собирался писать «OBS на Swift». Хотелось просто нормально играть на мониторе, за который заплатил слишком много, чтобы мириться с input lag.
Так появился GameMonitor — маленькое нативное macOS-приложение под связку консоль → ezcap Cam Link 4K → Mac → Studio Display.
Забавно, что задумывался он только под Switch. А потом оказалось, что…
«Свитч в свитч»: как подключились все три
Вот тут начинается моя любимая часть, где русский язык и Nintendo сговорились надо мной поиздеваться.
Я не хотел дёргать HDMI-кабель каждый раз, когда меняю консоль. Поэтому взял обычный HDMI-переключатель — по-английски HDMI switch. Воткнул один его выход в Cam Link, а в три входа — свои три устройства.
Одним из этих устройств был Nintendo Switch.
То есть буквально: я воткнул Switch в switch. И Steam Deck в switch. И Xbox в switch. А switch — в карту захвата.
Nintendo Switch ─┐ Steam Deck ──────┤ HDMI switch ──→ Cam Link ──USB──→ Mac ──→ Studio Display Xbox ────────────┘
Переключаю вход на HDMI-переключателе — на 5K-экране меняется консоль. Никаких перетыканий кабелей, никакого танца с бубном. Одна карта, одна программа, три консоли.
И вот тут выяснилось самое приятное: GameMonitor писался под Switch, но ему вообще всё равно, что на другом конце HDMI. Cam Link отдаёт USB-видео (UVC), а что там его породило — Nintendo, Valve или Microsoft — программе безразлично. Скальпель оказался универсальным.
Кто в этой цепочке главный
Прежде чем писать «красивый» код, пришлось понять, кто вообще решает, какая картинка приедет на Mac.
Кто | Что реально решает |
|---|---|
Консоль | Разрешение и FPS по HDMI (1080p, 1440p, 4K, 60/50 Hz) |
Cam Link | «С HDMI пришло одно → по USB отдам другое» (UVC-режим) |
GameMonitor | Просит у карты режим и рисует картинку. Сам сигнал консоли не меняет |
Ключевой момент, который меня сначала бесил: приложение не управляет консолью. Если на источнике 1080p, а в меню GameMonitor ткнуть «4K@60» — магии не будет. Приложение лишь просит карту отдать определённый UVC-режим; получится это или нет — решает связка «консоль + карта».
Поэтому в оверлее есть две строчки: «Запрос UVC» (что попросили) и «Карта (UVC)» (что реально приехало). Не сходятся — значит узкое место не в Mac, а раньше.
Технический твист: консоли ведут себя по-разному
А вот дальше — самое интересное наблюдение, ради которого стоило подключать не одну консоль.
Все три я гонял в 1080p. И оказалось, что на запрос смены режима из GameMonitor они реагируют по-разному:
Xbox и Steam Deck — слушались. Меняешь пресет в приложении — реально меняется разрешение потока с карты.
Nintendo Switch — стоял на своём. Что ни проси — на выходе стабильно одно и то же 1080p.
Полностью механику я утверждать не берусь (тут вмешиваются и EDID, и то, как каждая консоль договаривается с картой о выходном формате), но наблюдение честное и воспроизводимое: Switch — самый упрямый источник в цепочке, Xbox и Deck куда сговорчивее. Как минимум это отличный повод не гадать «почему не меняется», а сразу смотреть в оверлей: если запрос и факт не сошлись — вопрос не к Mac.
Мораль на будущее простая: сначала выставь режим на самой консоли, потом (опционально) проси что-то в приложении. GameMonitor не апскейлит консоль до 4K силой мысли.
Как я к этому шёл
Я не сел и не написал идеальный плеер за выходные. Порядок был скучный, но правильный:
Сначала — картинка. Просто увидеть, что консоль доходит до Mac.
Потом — цифры. Сколько fps реально приходит и сколько показывается. Не «кажется, лагает», а счётчики.
Потом — скорость. Выкинуть всё, что стоит между картой и экраном.
В конце — красота. Fullscreen, звук, циферка fps в углу.
Бóльшую часть времени я чинил не «приложение», а понимание, на каком именно этапе всё ломается. Это, наверное, главный урок всей затеи. А теперь — боссфайты.
Босс №1: «60 на карте, ~20 на экране» — и всё мыльное
Самый обидный баг, потому что самый обманчивый.
Консоль: 1080p @ 60. GameMonitor честно показывает UVC 60 fps — уже со счётчиками, не как OBS вслепую. А на глаз Том Нук двигается как в PowerPoint. Низкие двадцатые. И картинка при этом мыльная.
Долго казалось, что виноваты USB или карта. Нет. С карты приходило ровно 60. Ломалось уже на Mac — и fps, и резкость сразу.
Причина — тот самый апскейл до 5K. Чтобы заполнить экран, кадр надо очень сильно увеличить. Красивые алгоритмы масштабирования (тот же Lanczos) — точные, но медленные. GPU не успевал прогнать их на каждый кадр — и на экране выходило ~20–25 fps при стабильных 60 по USB.
Что видишь | Что это, скорее всего |
|---|---|
UVC ~60, экран ~20–25 | Апскейл до 5K — GPU не успевает (мой случай) |
UVC ~60, картинка мыльная | Простое «растянуть» вместо нормального апскейла |
UVC ~60, экран дёргается | Кадры не синхронизированы с монитором |
UVC ~25, экран ~25 | Источник реально в 25/50 fps |
Спас MetalFX Spatial — нейронный апскейлер от Apple, заточенный под игры и Apple Silicon. Он и 60 fps держит, и на 5K смотреть не так стыдно. Причём весь путь кадра — «карта → YUV→RGB прямо на GPU шейдером → MetalFX → экран», без единой копии через CPU. Ноль лишних поездок кадра туда-сюда.
Когда это завелось — впервые совпали цифры, глаз и картинка.
Босс №2: «а давай дорисовывать кадры, как телек»
Был момент, когда я подумал: современные телевизоры же умеют дорисовывать промежуточные кадры (MEMC). Давай и я так.
Звучало круто.
На экране появился зелёный.
Не «глюк на секунду». Ровный, уверенный, гамма-зелёный. Hulk mode. Animal Crossing превратился в тренинг по управлению гневом.
Вывод простой: для игр честные 60 fps с карты лучше, чем «плавность», которая ломает цвет. MEMC телевизора — не для консоли через capture card. Идею тихо похоронил.
Босс №3: FPS «прыгает» — 52, 58, 60, 57…
Когда UVC стал стабильным, счётчик на экране всё равно плясал.
Консоль отдаёт 60. Монитор — 60 Hz. А ощущение — «почти, но не quite».
Причина оказалась неочевидной: кадры с USB приходят когда хотят, а монитор обновляется по расписанию (по VSync). Показываешь каждый USB-кадр немедленно — ритм сбивается.
Решение — развязать «получить кадр» и «показать кадр». Карта прислала — мы просто запомнили последний кадр. CADisplayLink на выделенном render-потоке дёргается на VSync — и вот тогда мы кладём на экран то, что есть. Ровно один раз за такт монитора.
После этого fps в углу стал честные 60. Не «59.9 для красоты», а просто 60. И глаз перестал ловить микродёргания.
Босс №4: моргание «кадром из прошлого»
FPS починили, играть стало приятно. А потом — миг. Не чёрный экран, а кадр, которому давно пора на пенсию. Будто игра на долю секунды откатила сейв недельной давности.
Опять казалось, что это карта или USB. Оказалось — macOS иногда «помогает»: подсовывает старый снапшот слоя, пока приложение занято layout’ом или переходом в fullscreen.
Чинилось скучно и без романтики: всё, что касается картинки, — в одном потоке; AppKit не лезет в слой руками; чуть больше буферов на GPU. Не героическая история, но моргание ушло, и drops в статистике стал нулём. Вот в этот момент pet-project впервые начал ощущаться как продукт.
Босс №5: звук пропадает в fullscreen
Отдельный круг ада.
В окне звук есть. Жму fullscreen — тишина. Выхожу — снова есть. Повторил раз десять, чуть не бросил.
Дело было в том, как macOS прогоняет аудио с карты через приложение: в fullscreen поток начинал приходить пакетами, звук отставал и отваливался.
Переделал на системный аудиовывод напрямую из capture-сессии, а fullscreen сделал нативным — как у нормального Mac-приложения, без второго окна и без «захвата всего экрана». Когда звук заработал и в полноэкранном режиме — можно было честно сказать: готово для игры, а не «почти, но наушники только в окне».
Мелочи, которые приятно дошлифовать
Когда основное завелось, осталось то, ради чего Mac-приложение хочется открывать, а не терпеть:
Compact FPS — маленькая стеклянная цифра в углу, как часы на iPhone. Не панель во весь экран.
Полная статистика — для параноиков: UVC, GPU, drops, USB. Когда снова что-то пойдёт не так — сразу видно, где.
Game Mode — через
beginActivityговорю системе, что это игра, а не фоновая вкладка. macOS отдаёт приоритет, снижает свою латентность. Мелочь, но приятная.Иконка — три итерации. Первая вычурная, финальная — спокойная, как у родных Apple-приложений.
Почему не OBS
Самый частый вопрос, который я жду в комментариях.
OBS — отличный инструмент. Для стрима, записи, сцен и наложений лучше не придумать. Но моя задача была другой — просто играть.
OBS | GameMonitor | |
|---|---|---|
Стрим / запись | ✅ | ❌ |
Много источников | ✅ | ❌ |
Минимальная латентность для игры | ⚠️ | ✅ |
Нормальный апскейл на 5K (MetalFX) | ⚠️ | ✅ |
Счётчики fps / диагностика | ⚠️ | ✅ |
Fullscreen без сюрпризов со звуком | ⚠️ | ✅ |
Это не «OBS плохой». Задачи разные. Мне нужен был скальпель, а не швейцарский нож.
Что получилось
Switch / Steam Deck / Xbox → HDMI switch → Cam Link → GameMonitor → Studio Display
Переключаю вход на HDMI-переключателе, жму Start, ухожу в fullscreen. 60 fps. Звук. Без ощущения Remote Desktop.
Animal Crossing ночью на 5K выглядит неожиданно хорошо для связки «консоль → USB-карта → софт, написанный по вечерам». Mario Kart перестал раздражать задержкой. В Smash можно играть всерьёз. Steam-библиотека с Deck — на большом экране. Xbox — просто потому что теперь может.
Три консоли. Один HDMI-переключатель. Одна программа, которую я вообще-то писал под одну консоль.
Что я понял по дороге
«60 на карте» и «60 на экране» — разные вещи. Пока не меришь оба fps, чинишь не то звено.
5K-монитор — отдельный boss fight. Источник максимум 4K, экран 5K — без умного апскейла страдают и fps, и резкость. MetalFX здесь героически спас.
Консоли — разные. Xbox и Steam Deck слушались запросов режима, Switch упирался. Полезно знать, прежде чем винить софт.
Универсальность выходит случайно. Писал под Switch, а получил монитор для чего угодно с HDMI — потому что программе всё равно, кто на том конце.
Pet-project может начаться с обиды на монитор без HDMI — и закончиться тем, чем реально пользуешься каждый вечер.
Заключение
Я всего лишь хотел подключить консоль к Apple Studio Display.
Пришлось разобраться с картой захвата, задержками, апскейлом до 5K, синхронизацией с монитором, fullscreen, звуком и с тем, как macOS ведёт себя, когда просишь её «просто покажи видео без лагов».
Иногда pet-project — не про стартап и не про туториал. Иногда он начинается с вопроса:
Почему монитор за две тысячи долларов не умеет в HDMI?
А заканчивается тем, что Том Нук наконец-то бегает плавно — и неважно, с какой из трёх консолей он приехал.
Железо: Nintendo Switch 2, Steam Deck, Xbox, HDMI-переключатель, ezcap Cam Link 4K, Mac на Apple Silicon, Apple Studio Display.
Код и сборка — https://github.com/KashN9sh/gamemonitor.
Pet-project. Не аффилирован с Nintendo, Valve, Microsoft, Apple или ezcap. Все каламбуры про «Switch в switch» — за счёт заведения.
