Апскейлить одно изображение с помощью Real‑ESRGAN несложно: передать файл модели, дождаться обработки и сохранить результат. С видео всё становится заметно интереснее.
Нужно декодировать тысячи кадров, передать их нейросети, собрать обратно в видеопоток, сохранить звук, показать пользователю прогресс и корректно остановить несколько одновременно работающих процессов. А если десятичасовой рендер оборвался на девятом часу, желательно не начинать всё сначала.
Именно из этой задачи вырос UltraFrame AI — бесплатное Windows‑приложение с открытым исходным кодом для пакетного апскейлинга видео и изображений.
Основной целью проекта было не создать ещё одну графическую оболочку над консольной командой, а собрать полноценный рабочий процесс: очередь файлов, потоковую обработку без огромных каталогов с кадрами, восстановление прерванных заданий и понятный интерфейс для пользователя, который не обязан разбираться в параметрах FFmpeg.
Я работал с видео, для которого обычного масштабирования было недостаточно. В первую очередь речь шла об аниме, мультипликации, визуальных новеллах и другом рисованном контенте.
Для таких материалов модели семейства Real‑ESRGAN способны не только увеличить размер кадра, но и восстановить более чёткие контуры, сгладить ступеньки и частично уменьшить артефакты сжатия.
Консольные инструменты уже существовали, однако рабочий процесс оставался неудобным. Для каждого файла требовалось вручную запускать команды, контролировать временные каталоги, следить за свободным местом и затем собирать результат через FFmpeg.
На одном коротком ролике это терпимо. При обработке сезона сериала или большой папки изображений ручная схема быстро превращается в отдельную работу.
Так появилось первое требование к UltraFrame AI: пользователь добавляет несколько файлов или папку, выбирает параметры и запускает очередь. Всё остальное приложение должно делать самостоятельно.
Почему я отказался от папки с извлечёнными кадрами
Самая простая архитектура видеоапскейлера выглядит так:
Исходное видео ↓Извлечение кадров в PNG ↓Апскейлинг каждого PNG ↓Сохранение обработанных кадров ↓Сборка нового видео
Этот подход удобен для разработки. Каждый этап легко проверить отдельно, а после сбоя можно увидеть, на каком кадре возникла проблема.
Однако у него есть существенный недостаток — расход дискового пространства.
Десятиминутное видео с частотой 30 кадров в секунду содержит примерно 18 000 кадров. При сохранении в PNG один кадр может занимать несколько мегабайт. После увеличения разрешения размер каждого изображения становится ещё больше.
В результате сравнительно короткое видео способно создать десятки или даже сотни гигабайт временных данных. К этому добавляются постоянные операции чтения и записи, медленная очистка каталога и риск оставить весь набор кадров после аварийного завершения.
Мне хотелось, чтобы программа могла обрабатывать длинные ролики даже на компьютере без огромного запаса свободного места. Поэтому вместо схемы с временной папкой я перешёл к потоковой обработке.
FFmpeg decoder ↓Real-ESRGAN / Vulkan ↓FFmpeg encoder ↓Готовое видео
Декодер выдаёт последовательность кадров, нативный движок увеличивает их, а кодировщик сразу записывает результат. Полная коллекция кадров на диске не создаётся.
Простая схема оказалась сложной системой
На диаграмме потоковый конвейер выглядит почти тривиально. На практике приложение должно одновременно управлять несколькими компонентами.
FFmpeg‑декодер может выдавать кадры быстрее, чем GPU успевает их обрабатывать. Кодировщик, в свою очередь, может временно замедлиться из‑за выбранного кодека или скорости накопителя. Если один процесс завершился с ошибкой, остальные нельзя оставлять работающими.
Кроме передачи данных нужно читать диагностический вывод, определять реальный прогресс, реагировать на отмену и не допускать зависания каналов между процессами.
Упрощённо логика оркестрации выглядит так:
StartDecoder();StartUpscaler();StartEncoder();try{ await PumpFramesAsync( decoderOutput, upscalerInput, upscalerOutput, encoderInput, cancellationToken);}finally{ StopDecoder(); StopUpscaler(); StopEncoder(); throw;}
В реальном приложении каждый этап дополнительно сообщает своё состояние. Завершение декодера ещё не означает завершение задания: часть кадров может оставаться внутри конвейера, а кодировщик должен корректно дописать контейнер.
Особенно важно корректное завершение при отмене. Если просто уничтожить процесс FFmpeg, выходной файл может остаться повреждённым. Поэтому приложение сначала пытается остановить обработку штатно и лишь затем прибегает к принудительному завершению.
Почему Real‑ESRGAN пришлось вынести в отдельную нативную часть
Интерфейс UltraFrame AI написан на C# и WPF, но сам апскейлинг выполняется нативным Vulkan‑приложением на базе realesrgan-ncnn-vulkan.
Это разделение оказалось естественным.
WPF хорошо подходит для очереди, настроек, окон прогресса и управления заданиями. Переносить вычислительный движок на C# не имело смысла: существующая реализация уже использует NCNN и Vulkan и оптимизирована для GPU.
При этом стандартная консольная версия Real‑ESRGAN прежде всего рассчитана на отдельные изображения и каталоги. Для видео мне требовалась работа внутри потокового конвейера, поэтому в репозитории используется отдельный fork нативного компонента.
Основное приложение в этой архитектуре выступает оркестратором. Оно подготавливает параметры, запускает процессы, контролирует их состояние и преобразует низкоуровневые ошибки в сообщения, понятные пользователю.
Видео и изображения пришлось разделить
Первоначально UltraFrame AI был ориентирован на видео. Позже стало понятно, что тот же интерфейс удобно использовать для изображений, но общий экран настроек быстро стал бы перегруженным.
У видео есть кодек, частота кадров, аудиодорожки, контейнер, FFmpeg и возможность восстановления. У изображений вместо этого важны формат сохранения, качество JPEG, прозрачность PNG и итоговое разрешение.
Поэтому в приложении появились два отдельных режима.
В режиме Video пользователь формирует очередь роликов и запускает потоковый конвейер. В режиме Images можно добавить отдельные файлы, несколько изображений или целую папку и обработать их без участия FFmpeg.
Общей осталась система очереди: приложение последовательно выполняет задания и хранит результат каждого элемента. Но сами конвейеры и наборы параметров различаются.
Такой подход оказался удобнее одного универсального окна с десятками переключателей, половина которых в конкретном режиме не используется.
Восстановление после прерванного рендера
Длительный рендер может оборваться по разным причинам: перезагрузка Windows, закрытие приложения, ошибка драйвера, проблема с кодировщиком или нехватка места.
Простое сохранение номера последнего кадра ещё не гарантирует возможность продолжения. Нужно учитывать состояние выходного файла и этап, на котором остановилась обработка.
Поэтому восстановление в UltraFrame AI построено не как безусловная кнопка Resume. При запуске приложение ищет незавершённые задания и проверяет, сохранилось ли достаточно данных для безопасного продолжения.
Если состояние задания согласовано, пользователь получает предложение восстановить обработку. Если продолжение невозможно, приложение не обещает восстановление и предлагает начать заново.
Для меня это было важным UX‑решением. Лучше честно отказаться от восстановления, чем продолжить с неверной позиции и получить повреждённый или рассинхронизированный файл.
Benchmark вместо универсальных требований к видеокарте
Скорость нейросетевого апскейлинга зависит не только от модели GPU. На неё влияют разрешение исходника, коэффициент увеличения, выбранная модель, доступная видеопамять и драйвер Vulkan.
Поэтому формулировка вроде «требуется видеокарта уровня RTX 3060» мало помогает пользователю. Два файла на одной и той же системе могут обрабатываться с сильно разной скоростью.
В UltraFrame AI появился небольшой benchmark. Он запускается на текущем компьютере, проверяет доступные GPU и помогает подобрать исходные параметры.
Benchmark не пытается предсказать точное время любого рендера. Его задача — дать начальную конфигурацию и заранее обнаружить проблемы с Vulkan или выбором устройства.
Пользователь получает не абстрактное системное требование, а результат проверки собственной машины.
FFmpeg и вопрос распространения
Для работы с видео программе нужны ffmpeg.exe и ffprobe.exe. Можно было просто положить их в архив вместе с приложением, но я решил не смешивать компоненты автоматически.
Причина не только в размере сборки. Условия лицензирования FFmpeg зависят от конкретной конфигурации, включённых библиотек и способа распространения.
UltraFrame AI умеет искать FFmpeg в PATH, позволяет указать существующий каталог и может предложить автоматическую загрузку после явного подтверждения пользователя.
Таким образом, исходный код проекта и основной релиз не притворяются владельцами стороннего компонента. Пользователь при этом не обязан вручную изучать консоль и переменные окружения.
Если кто‑то создаёт собственную сборку UltraFrame AI вместе с FFmpeg, ему всё равно необходимо проверить условия лицензии выбранной сборки.
Интерфейс оказался не менее сложной частью проекта
Технически работающий pipeline ещё не делает приложение удобным.
Например, пользователь может добавить папку с файлами разных форматов. Некоторые из них программа обработает, некоторые пропустит. Один файл может завершиться успешно, а другой — с ошибкой. После окончания очереди нужно показать не общий статус, а результат каждого задания.
В приложении появились отдельные окна прогресса и итогов обработки. Из итогового окна можно открыть готовый файл, перейти в его каталог или посмотреть ошибку.
Также есть окно сравнения исходного и обработанного результата. Оно особенно полезно для изображений: нейросетевой апскейлинг не всегда объективно улучшает исходник, и результат желательно проверить до обработки большого архива.
Интерфейс переведён на английский, русский, немецкий, японский и китайский языки. Локализация выявила ещё одну проблему: текст, который хорошо помещается на английском, может занимать значительно больше места на другом языке. Поэтому часть интерфейса пришлось проектировать с учётом динамической длины строк, а не просто заменять надписи.
Что оказалось самым трудным
До начала разработки мне казалось, что основной сложностью будет Real‑ESRGAN. На практике нейросетевая часть оказалась лишь одним элементом системы.
Больше всего времени потребовали границы между компонентами: корректная передача кадров, завершение нескольких процессов, диагностика ошибок FFmpeg, отмена заданий и восстановление состояния интерфейса.
Отдельной проблемой стала разница между «ошибка произошла» и «пользователь понял, что произошло». Сообщение нативного процесса может быть полезно разработчику, но бесполезно человеку, который просто выбрал видео и нажал Render.
Поэтому приложение классифицирует типичные ситуации: отсутствие FFmpeg, недоступный Vulkan, неверный выходной каталог, недостаток места или аварийное завершение внешнего процесса.
Ограничения проекта
UltraFrame AI пока остаётся Windows‑приложением, поскольку интерфейс построен на WPF. Для запуска требуется 64-битная Windows и GPU с поддержкой Vulkan.
Кроме того, нейросетевой апскейлинг не восстанавливает реальные утраченные данные. Модель генерирует правдоподобные детали на основе обучающих примеров. На качественной рисованной анимации это часто выглядит убедительно, но на сильно сжатом материале могут появляться ложные контуры и текстуры.
На реалистичном видео результат также зависит от модели. Инструмент изначально ориентирован прежде всего на аниме, мультипликацию и иллюстрации, поэтому я рекомендую сначала обработать небольшой фрагмент.
Проекту также нужны дополнительные тесты на GPU разных производителей. Основная архитектура не привязана к NVIDIA, однако драйверы и реализация Vulkan могут вести себя по‑разному.
Как собрать проект
Репозиторий содержит submodules, поэтому клонировать его нужно соответствующей командой:
git clone --recurse-submodules https://github.com/dagnarus15/UltraFrameAI.gitcd UltraFrameAI
Основное приложение собирается через.NET SDK:
dotnet build .\UltraFrameAI\UltraFrameAI.csproj -c Release -r win-x64
Для создания готовой portable‑сборки используется PowerShell‑скрипт:
.\UltraFrameAI\publish-portable.ps1
По умолчанию формируется self‑contained приложение, поэтому пользователю не требуется отдельно устанавливать.NET Desktop Runtime.
Подробности сборки нативного компонента и структура проекта описаны в README репозитория.
Что я планирую дальше
Сейчас я рассматриваю дополнительные модели, улучшение предварительного просмотра, профили настроек и более подробную диагностику.
Но основным направлением остаётся не количество функций, а надёжность конвейера. Для приложения, которое может работать несколько часов, корректная отмена, восстановление и понятные ошибки важнее ещё одного переключателя в интерфейсе.
Особенно полезны результаты тестирования на разных видеокартах. Мне интересно не только время обработки, но и то, как приложение ведёт себя при длинных очередях, смене разрешений и нестандартных видеофайлах.
Итог
UltraFrame AI начинался как способ не вводить вручную одни и те же команды для каждого видео. В процессе стало понятно, что удобный апскейлер — это не кнопка над Real‑ESRGAN, а система управления несколькими сложными компонентами.
Самым важным архитектурным решением стал переход от временных каталогов с тысячами кадров к потоковому конвейеру:
FFmpeg → Real-ESRGAN/Vulkan → FFmpeg
Он позволил значительно уменьшить требования к свободному месту, но потребовал решить задачи синхронизации процессов, отмены, обработки ошибок и восстановления.
Проект распространяется под лицензией MIT. Исходный код и готовые сборки доступны на GitHub:
Буду рад технической критике, результатам тестирования и рассказам о том, какие материалы вы обычно апскейлите.
ссылка на оригинал статьи https://habr.com/ru/articles/1059520/