О чём эта статья
В первой части мы разобрали архитектуру SPICE: каналы, TCP-only, image-based подход. Теперь копаем глубже — в Display Channel. Это самая сложная часть протокола, и именно здесь обычно начинаются нюансы.
Display Channel отвечает за то, чтобы картинка с экрана виртуальной машины попала на монитор пользователя. Звучит просто. На практике — это сжатие, стриминг, детекция видео, выбор кодеков, работа с разрешениями. И много компромиссов.
Если вы когда-нибудь слышали от пользователей «видео тормозит» или «почему всё такое мыльное» — эта статья про то, откуда это берётся. И почему это не всегда можно починить.
Почему это вообще важно
VDI красиво выглядит в презентации. Железо в датацентре, данные не покидают периметр, централизованное управление. А потом начинается жизнь.
Маркетолог открывает YouTube, чтобы посмотреть ролик конкурента. Видео дёргается, звук убегает. Он пишет в IT: «Система не работает». IT разводит руками — SPICE не для этого. Но попробуйте объяснить это бизнесу, который только что заплатил за «современное решение».
Дизайнер с 4K-монитором получает либо мыло (растянули Full HD), либо нечитаемый интерфейс (показали 1:1), либо лаги (передали честный 4K). Он требует вернуть нормальный компьютер. И он, в общем-то, прав.
Руководитель проводит Zoom через VDI. Камера — через USB redirection, картинка — через Display Channel, звук — через Playback. Всё вместе даёт артефакты, эхо и неизбежное «а вы меня слышите?». После третьего такого звонка он начинает искать способ выбраться из VDI.
SPICE строился на решениях, которые принимались в 2007–2009 годах и под другие сценарии. Тогда YouTube был молодым стартапом, 4K-мониторов не существовало, а видеозвонки оставались экзотикой. SPICE создавался для офисной работы — текст, почта, браузер без видео.
Коммерческие VDI-решения годами вкладывают ресурсы в эти проблемы — Citrix с HDX, VMware с Blast. У них есть команды, которые занимаются почти исключительно оптимизацией мультимедиа. SPICE — open source проект с другими приоритетами и другими ресурсами.
Понимать эти границы — значит применять инструмент в правильном контексте и не ждать от него того, для чего он никогда не предназначался.
Два мира: Image Mode и Stream Mode
В первой статье я говорил, что SPICE — image-based протокол. Это правда, но не вся.
Display Channel на самом деле работает в двух режимах. И понимание разницы между ними — ключ к тому, как SPICE вообще обращается с видео. Это одна из тех вещей, которые не очевидны из документации, но критически важны на практике.
Display Image Mode
Это основной режим. Когда что-то меняется на экране, происходит следующее:
QXL-драйвер в госте фиксирует изменённые области (dirty regions)
libspice на хосте получает эти области через command ring
Каждая область сжимается выбранным кодеком (QUIC, GLZ, LZ4)
Сжатые данные отправляются клиенту
Клиент декодирует и рисует результат
Ключевая особенность — каждый «кадр» сжимается независимо. Межкадрового сжатия здесь нет. Для статичного контента это нормально: изменения редкие, области маленькие, сжатие эффективное.
Вы набираете текст в Word — меняется небольшая область вокруг курсора, передаётся несколько килобайт. Вы открываете меню — передаётся область меню. Всё происходит быстро и предсказуемо.
Для видео этот режим не подходит. 30 раз в секунду обновляется большая область экрана. Каждый раз — независимое сжатие. Bandwidth растёт очень быстро.
Display Stream Mode
Когда libspice видит, что какая-то область экрана обновляется слишком часто, он переводит её в режим видеостриминга.
На практике это выглядит так.
libspice ведёт commands tree — дерево графических команд, приходящих от QXL. Эвристика анализирует частоту обновлений каждой области. Если область обновляется часто и регулярно — с высокой вероятностью это видео. Для неё создаётся отдельный stream, и дальше данные кодируются уже с межкадровым сжатием.
Важно понимать: стриминг применяется к отдельным областям, а не ко всему экрану. Текст вокруг видеоплеера продолжает идти через Image Mode, само видео — через Stream Mode.
С точки зрения идеи это выглядит разумно: зачем применять видеокодек к статичному тексту. Но на практике появляются свои особенности. Когда окно видеоплеера перемещается — stream приходится пересоздавать. Когда меняется его размер — тоже. В эти моменты обычно заметны артефакты.
Протокол стриминга
Если смотреть на это на уровне протокола, картина выглядит примерно так:
SPICE_MSG_DISPLAY_STREAM_CREATE
├── stream_id — уникальный ID потока
├── codec_type — тип кодека (MJPEG, VP8, H264...)
├── stream_width, stream_height — размер
└── dest — координаты на экране
SPICE_MSG_DISPLAY_STREAM_DATA
├── stream_id
├── multi_media_time — timestamp для синхронизации
└── data[] — закодированные данные кадра
SPICE_MSG_DISPLAY_STREAM_CLIP
└── clip — область изменилась (окно передвинули)
SPICE_MSG_DISPLAY_STREAM_DESTROY
└── stream_id — поток больше не нужен
Теоретически на экране может быть несколько видео, каждое в своём потоке. На практике это работает, но нагрузка при этом растёт почти линейно — и по CPU, и по bandwidth.

Эвристика детекции: когда становится понятно, что это видео
Переключение между режимами происходит автоматически. Звучит удобно, но сразу возникает вопрос: как именно libspice понимает, что «это видео».
Commands Tree
libspice ведёт дерево команд — структуру, которая отслеживает все графические операции, приходящие от QXL. Она используется для двух вещей.
Оптимизация. Если новая команда полностью перекрывает старую, старую можно не отправлять. Зачем передавать пиксели, которые всё равно будут перерисованы?
Детекция стримов. Анализ частоты и характера обновления областей экрана.
Как работает детекция
Эвристика смотрит на несколько параметров:
Частоту обновлений — сколько раз в секунду область меняется
Размер — слишком мелкие области отфильтровываются, накладные расходы не окупятся
Регулярность — равномерные обновления больше похожи на видео, чем случайные всплески
Когда область проходит эти критерии, для неё создаётся stream. С этого момента она кодируется как видео.
Где могут быть неприятности
Ложные срабатывания. Терминал с быстро бегущим логом может определиться как видео. Результат — MJPEG-артефакты на тексте. Нечитаемо. Я видел подобное в production, и это выглядит почти сюрреалистично: половина терминала чёткая, половина — мыльная.
Похожая ситуация возникает при скроллинге в браузере. Область обновляется часто, но это не видео — это текст. Эвристика не всегда умеет различать такие случаи.
Пропуски. Видео с низким fps — например, обучающий ролик на 15 fps — может не детектироваться вовсе. Каждый кадр пойдёт через Image Mode. Вместо одного сжатого потока — сотни отдельных картинок.
Задержка переключения. Эвристике нужно время, чтобы накопить статистику. Первые секунды видео часто идут рывками — пока libspice «понимает», с чем имеет дело.
Границы области. Когда окно видеоплеера меняет размер или перемещается, stream пересоздаётся. В этот момент обычно заметны артефакты.
Настройка
-spice streaming-video=all|filter|off
# all — стримить всё, что похоже на видео
# filter — пропускать мелкие области (дефолт)
# off — отключить стриминг полностью
off иногда используют в случаях, когда артефакты стриминга становятся массовыми, а переключение в Image Mode неожиданно даёт лучший результат — особенно при работе с текстом на нестабильном соединении. Трафика станет больше, но читать снова можно.
MJPEG: наследие 2009 года
По умолчанию Display Stream использует MJPEG. Motion JPEG. Буквально — последовательность JPEG-картинок.
Исторический контекст
Когда SPICE проектировался, это был логичный выбор:
Простой в реализации — JPEG-библиотеки везде
Никаких патентных проблем (H.264 тогда стоил денег)
Устойчив к потерям пакетов — потерял кадр, показал следующий
Минимальная латентность — каждый кадр независим
Для 2009 года — разумно. VP8 Google открыл только в 2010. H.264 royalty-free профили появились позже. MJPEG использовали везде: цифровые камеры, системы видеонаблюдения, веб-камеры первого поколения.
Почему сегодня нужен другой подход
MJPEG не использует межкадровое сжатие. Каждый кадр — отдельная картинка. Нет P-frames, нет B-frames. Только I-frames.
Это как если бы вы каждую секунду отправляли 30 полных фотографий, вместо того чтобы отправить одну и потом только изменения.
Грубые цифры для Full HD:
Кодек |
Битрейт |
Почему |
|---|---|---|
MJPEG |
15-30 Мбит/с |
Каждый кадр — полный JPEG |
H.264 |
3-8 Мбит/с |
Межкадровое сжатие |
H.265 |
2-5 Мбит/с |
Ещё эффективнее |
VP9 |
2-6 Мбит/с |
Примерно как H.265 |
Разница в 3-10 раз.
На гигабитном LAN это терпимо. На 100 Мбит — уже не очень. Одно видео при 20 Мбит/с — это 20% канала. Два видео — начинаются трудности. На WAN — забудьте про нормальное видео.
Качество
И дело не только в bandwidth.
MJPEG оптимизирован для фотографий, не для видео с движением. На видео — характерные артефакты. Блочность на границах объектов. «Мыло» на низких битрейтах. Особенно заметно на быстром движении.
Современные кодеки используют motion compensation — понимают, что объект переместился, передают вектор движения. MJPEG этого не умеет. Каждый раз — полное описание кадра.
GStreamer: новый подход
К 2016 году стало понятно, что с MJPEG далеко не уедешь. Решение — интеграция с GStreamer.
GStreamer — мультимедиа-фреймворк, позволяет строить пайплайны из плагинов. Хотите H.264 — подключаете x264enc. Хотите NVENC — nvh264enc. Модульно.
Теперь libspice может использовать:
spice:mjpeg — встроенный (дефолт)
gstreamer:mjpeg — MJPEG через GStreamer
gstreamer:h264 — H.264
gstreamer:vp8 — VP8
gstreamer:vp9 — VP9
-spice video-codecs=gstreamer:h264;gstreamer:vp8;spice:mjpeg
Порядок важен — это приоритет. Сначала H.264, если не получится — VP8, последний fallback — MJPEG.
Краткая справка по кодекам
Поскольку с кодеками часто путаница — краткий обзор.
VP8 — открыт Google в 2010. Royalty-free, часть проекта WebM. Примерно как H.264 по эффективности. Хорошо поддерживается в браузерах благодаря WebRTC. Encoding относительно простой.
VP9 — наследник VP8, 2013. Конкурирует с H.265 по эффективности. YouTube использует для 4K. Тоже royalty-free. Encoding сложнее, чем VP8.
H.264 (AVC) — стандарт де-факто с 2003. Отличная аппаратная поддержка везде — любой GPU последних 10 лет. Базовые патенты MPEG-LA истекли, расширения — до 2027-2028. Самый безопасный выбор для совместимости.
H.265 (HEVC) — экономит 30-50% vs H.264 при том же качестве. Но патентная ситуация — кошмар. Три разных патентных пула, плюс независимые держатели. Из-за этого многие избегают.
Почему GStreamer, а не FFmpeg?
Вопрос задают часто. FFmpeg зрелее, документация лучше.
Насколько я понимаю, причины политико-лицензионные. GStreamer — LGPL, хорошо интегрирован в GNOME/freedesktop. SPICE развивался в Red Hat, который тесно связан с этой экосистемой.
FFmpeg — сложная лицензионная ситуация. Части GPL, части LGPL. Патентные вопросы. Для проекта, который хочет быть «чистым» — риск.
Реальность использования
Однако с GStreamer всё непросто. И это важно понимать до того, как вы решите «переключимся на H.264».
libspice должна быть собрана с поддержкой GStreamer. Не все дистрибутивы это включают. Fedora, RHEL — да. Debian, Ubuntu — проверяйте. Может понадобиться собирать из исходников или искать сторонние репозитории.
Нужны плагины — gst-plugins-good, gst-plugins-ugly. Для H.264 — gst-plugins-bad в некоторых дистрибутивах. И патентные соображения — Fedora не включает H.264 в основные репозитории, нужен RPM Fusion.
Клиент тоже должен уметь декодировать. spice-gtk использует GStreamer — нужны плагины и там. Нет gst-plugins-bad на клиенте — H.264 не заработает. А клиент может быть на другой машине, с другим дистрибутивом.
Capability negotiation: клиент и сервер согласовывают кодеки при подключении. Клиент сообщает, что умеет. Сервер выбирает лучший из доступных. Если клиент не умеет VP8 — fallback на MJPEG.
Software encoding H.264 — дорогой. Один Full HD поток может съесть ядро. x264 хорошо параллелится, но всё равно — это заметная нагрузка. При 50 VM — считайте ресурсы.

Hardware Encoding: где находится GPU?
Software encoding не масштабируется. Один H.264 поток Full HD @ 30fps — это ядро CPU. Десять VM с видео — десять ядер только на encoding.
Hardware encoding — NVENC, Quick Sync, VCE — выделенные блоки в GPU, которые кодируют практически бесплатно с точки зрения CPU.
Но вот вопрос: где находится GPU?
В типичной VDI-архитектуре с SPICE гость использует QXL — виртуальное устройство. Реального GPU в госте нет. Hardware encoder изнутри недоступен.
Encoding происходит на хосте, в libspice. Хост может использовать свой GPU... но это создаёт конкуренцию между всеми VM за один encoder.
Проблема плотности
Здесь мы подходим к тому, о чём редко говорят в маркетинговых материалах.
VDI продаётся на идее консолидации. Один сервер вместо сотни десктопов. Типичная плотность — 50-100 VM на хост. Для офисной работы это реально — VM в основном idle, реальная нагрузка низкая.
Но когда появляется видео, математика меняется.
Software encoding: 100 VM с видео = 50-100 ядер на encoding. Это больше, чем есть в большинстве серверов. Даже dual-socket Xeon с 64 ядрами не справится.
Hardware encoding: кажется решением, но лимиты реальные:
Quick Sync — единицы-десятки потоков, зависит от поколения процессора
Consumer NVENC — 3-5 потоков (искусственное ограничение NVIDIA, чтобы продавать Quadro)
Quadro/Tesla — больше, но конечное число
Один GPU на 100 VM — всё равно не хватит
Добавить GPU в сервер можно. Это деньги, слоты PCIe, тепло, электричество. И всё равно конечное число потоков.
При высокой плотности encoding становится bottleneck. Обычно это всплывает в неожиданный момент — когда все пользователи одновременно включают видеозвонки. Понедельник утром, общее совещание в Zoom, у всех включены камеры. И всё начинает тормозить.
Двойное преобразование: YouTube в госте
Просмотр YouTube или видеозвонки в госте, это то, чего пользователи хотят, и то, что требует больше ресурсов.
Что происходит на самом деле:
YouTube сервер
↓ H.264 поток (уже сжат оптимально)
ГОСТЬ: браузер декодирует → raw pixels в framebuffer
↓ raw framebuffer
ХОСТ: libspice детектирует «видео», кодирует → MJPEG/H.264
↓ закодированный поток
КЛИЕНТ: декодирует → отображает
Три преобразования вместо одного. decode → encode → decode.
Исходный H.264 от YouTube был уже оптимально сжат. Мы его распаковали, чтобы тут же запаковать заново — на лету, в реальном времени.
Результат:
Тройная нагрузка на CPU/GPU — decode в госте, encode на хосте, decode на клиенте
Потеря качества на каждом encode — особенно если MJPEG, там качество теряется существенно
Дополнительная латентность — каждый этап добавляет задержку
Больше bandwidth — потому что наш encode хуже, чем у YouTube из-за live режима
К сожалению архитектура SPICE не предусматривает другого пути. Каждый пиксель на экране гостя проходит через Display Channel.
Video passthrough — теоретическое решение
Теоретическое решение — video passthrough: передать исходный поток напрямую клиенту. Браузер в госте говорит «я сейчас буду показывать H.264», SPICE перехватывает этот поток и передаёт клиенту as-is. Клиент декодирует — один раз.
Коммерческие VDI это умеют:
Citrix HDX MediaStream — перехватывает видео в браузере, передаёт клиенту
VMware Blast — аналогично
Microsoft RDP — Media Optimization
В SPICE такой функциональности пока нет. Это требует:
Перехвата видеопотока в госте (hook в браузер, в media framework)
Отдельного канала для видео
Синхронизации позиции видео на экране
Обработки всех edge cases
Большая работа предстоит тому, кто за неё возьмётся.
Что с этим делать
Планируйте с запасом: если пользователи будут смотреть видео — закладывайте меньшую плотность. Не 100 VM на хост, а 50. Или 30.
Мониторьте CPU хоста: высокая утилизация может быть не от VM, а от encoding в libspice. top покажет процесс qemu, но нагрузка на самом деле от libspice внутри.
Ограничьте видео политикой: если VDI для работы — может, YouTube там и не нужен? Жёстко, но эффективно. Можно заблокировать на уровне прокси.

GPU Passthrough: когда хост слеп
Есть сценарий, где всё работает совсем иначе.
Когда физический GPU проброшен в VM:
Гость имеет настоящий GPU с драйверами вендора
QXL не используется
Рендеринг идёт на реальном железе
Хост не видит framebuffer
Последний пункт ломает всю архитектуру. GPU полностью контролируется гостем. Память GPU, framebuffer — всё недоступно хосту. libspice не может детектировать области, не может сжимать — ему нечего сжимать, он ничего не видит.
Это используется для workloads, которым нужен реальный GPU:
3D/CAD (SolidWorks, AutoCAD, Blender)
Видеомонтаж (Premiere, DaVinci)
Machine Learning (inference, иногда training)
Игры (да, бывает и такое в enterprise)
Классический SPICE в этом случае просто не работает. Нужен другой подход.
spice-streaming-agent: обходной путь
Для сценария с GPU passthrough создали spice-streaming-agent.
Идея: раз хост не видит экран — пусть гость сам его захватывает и стримит.
spice-streaming-agent — демон внутри гостя:
Захватывает экран (через X11/DRM)
Кодирует в видеопоток
Отправляет через virtio-порт на хост
Хост передаёт клиенту
Критически важный момент: он захватывает весь экран целиком. Никакой детекции «где видео» — стримится всё.
Текущее состояние spice-streaming-agent
Если смотреть на spice-streaming-agent без ожиданий «универсального решения», его проще воспринимать как практический ответ на конкретное архитектурное ограничение SPICE.
Когда QXL недоступен — например, при GPU passthrough — классическая модель Display Channel перестаёт работать. В этой точке нужен другой подход. spice-streaming-agent появился именно как такой обходной путь: не развитие существующей архитектуры, а способ закрыть сценарий, который иначе вообще не покрывался.
Из коробки агент работает в самом базовом варианте — software MJPEG под X11 в Linux. Это минимальная конфигурация, которую можно запустить без дополнительной подготовки и сборки. Она не претендует на максимальную эффективность, но позволяет получить рабочий стрим в условиях, где других вариантов просто нет.
Поддержка GStreamer существует в виде экспериментального плагина (патчи 2018 года). Для его использования требуется сборка с --enable-gstreamer. Поддерживаются H.264, VP8 и VP9. Статус — for testing purposes, в основной ветке это решение так и не закрепилось. На практике собрать и запустить можно, но это требует заметного объёма ручной работы и понимания стека.
Поддержка Windows отсутствует. Теоретически портирование возможно, но на данный момент этим никто всерьёз не занимался. Wayland также не поддерживается — агент работает только с X11.
Активность разработки невысокая. Основные изменения приходятся на 2019–2020 годы. Проект нельзя назвать заброшенным, но и активной эволюции в последние годы не происходит. Он находится в состоянии «рабочего решения для узкого сценария».
По ощущениям, spice-streaming-agent — это функциональный proof of concept, доведённый до состояния, в котором его можно использовать. Его возможностей достаточно, чтобы закрыть use case «GPU passthrough + SPICE», но он не позиционируется как готовый мультимедийный стек для широкого production без дополнительной доработки.
Практические особенности настройки
Использование spice-streaming-agent требует некоторой подготовки:
настройка virtio-порта в QEMU/libvirt
установка агента в гостевой системе
при необходимости H.264 — сборка с поддержкой GStreamer
настройка прав доступа к DRM/GPU
диагностика и отладка в случае проблем
Это не сценарий «установил пакет и забыл». Скорее, это инструмент для тех, кто готов разбираться в деталях и понимать, что именно происходит в системе.
Когда это имеет смысл
spice-streaming-agent хорошо вписывается в сценарии, где:
используется GPU passthrough для 3D, CAD или видео
применяется vGPU (Intel GVT-g, NVIDIA vGPU)
QXL принципиально недоступен
При этом предполагается:
Linux guest + X11
готовность к ручной настройке
приоритет качества картинки над плотностью размещения VM
В этих условиях агент позволяет получить рабочий стриминг экрана там, где классический SPICE просто не применим.

4K и High DPI: математика против нас
Теперь про разрешения. В этой точке SPICE начинает упираться не столько в архитектуру, сколько в простую математику — и это проявляется независимо от режима работы.
Базовая арифметика выглядит так:
Разрешение |
Мегапиксели |
vs Full HD |
|---|---|---|
Full HD |
2.07M |
1x |
2K/QHD |
3.69M |
1.8x |
4K/UHD |
8.29M |
4x |
5K |
14.7M |
7x |
4K — это в четыре раза больше пикселей по сравнению с Full HD. При прочих равных — в четыре раза больше данных, которые нужно передать, сжать, декодировать и отрисовать. Это не линейное усложнение, а кратное.
Соответственно, растут:
требования к bandwidth,
нагрузка на encoding и decoding,
объёмы памяти под буферы.
Image Mode в 4K
Для офисных сценариев сжатие продолжает работать. GLZ хорошо находит повторы, QUIC эффективно сжимает градиенты. Статичный текст и интерфейсы по-прежнему передаются достаточно эффективно.
По данным Red Hat, ориентиры для SPICE выглядят так:
офисная работа — от 150 Кбит/с
мультимедиа — 500 Кбит/с – 1 Мбит/с
Но это минимальные значения для Full HD и, по сути, нижняя граница приемлемости.
Из практических наблюдений для Full HD при активной работе:
спокойная работа — 200–500 Кбит/с
браузер и документы — 0.5–2 Мбит/с
быстрый скроллинг — до 5 Мбит/с
Для 4K эти значения приходится умножать примерно на 3–4. В результате активный скроллинг в 4K легко выходит в диапазон 15–20 Мбит/с.
Stream Mode в 4K
В режиме стриминга нагрузка растёт ещё заметнее.
4K MJPEG при приемлемом качестве требует порядка 50–100 Мбит/с. Это ожидаемо: каждый кадр — более 8 мегапикселей, обновляющихся десятки раз в секунду.
Использование H.264 снижает требования к bandwidth. Для 4K это обычно диапазон 15–30 Мбит/с, при условии, что software encoding справляется с нагрузкой.
Software-кодирование 4K — ресурсоёмкая задача. Один поток 4K@30fps в x264 может потреблять несколько CPU-ядер. В среде с высокой плотностью виртуальных машин это быстро становится ограничивающим фактором и требует либо аппаратного ускорения, либо пересмотра сценария использования.
High DPI
Retina-экраны, 4K-мониторы и высокая плотность пикселей стали нормой.
Пользователь с 4K-ноутбуком подключается к виртуальной машине, изначально настроенной на Full HD. Возникают три варианта:
Растянуть Full HD до 4K — интерфейс остаётся читаемым, но теряет чёткость
Показать 1:1 — картинка резкая, но элементы интерфейса становятся слишком мелкими
Переключить VM в 4K — нагрузка возрастает кратно
SPICE через vdagent поддерживает динамическое изменение разрешения. Клиент сообщает своё разрешение, гость подстраивается. Технически это работает корректно.
На практике это часто выглядит так: пользователь подключается с 4K-устройством, виртуальная машина переключается в 4K, нагрузка возрастает, появляются задержки. В ответ предлагается снизить разрешение — что логично с точки зрения инфраструктуры, но плохо воспринимается пользователем, который сознательно выбрал 4K-экран.
Практические границы
Из опыта, субъективно:
Разрешение |
Офис |
Видео |
|---|---|---|
Full HD |
Комфортно |
С оговорками |
2K |
Комфортно |
Заметные ограничения |
4K |
Приемлемо для статики |
Сильно ограничено |
Если пользователю нужен 4K именно как рабочий инструмент — для дизайна, видео или CAD — это уже пограничный сценарий для классического SPICE. В таких случаях чаще рассматривают либо GPU passthrough со всеми сопутствующими сложностями, либо локальную рабочую станцию. Это не недостаток SPICE как такового, а следствие физических и архитектурных ограничений, с которыми приходится считаться.
Multi-Monitor
С точки зрения нагрузки всё достаточно прямолинейно: больше мониторов — больше пикселей.
Конфигурация |
Суммарно |
|---|---|
1×Full HD |
2.07M |
2×Full HD |
4.14M |
3×Full HD |
6.21M |
1×4K |
8.29M |
Три монитора Full HD по объёму данных находятся примерно на уровне одного 4K. С точки зрения Display Channel это означает сопоставимую нагрузку на передачу и обработку изображения.
SPICE поддерживает multi-monitor на архитектурном уровне. QXL эмулирует несколько heads, vdagent синхронизирует конфигурацию дисплеев между клиентом и гостем. На уровне протокола каждый монитор представлен отдельным surface в Display Channel.
remote-viewer умеет работать с несколькими дисплеями: можно растянуть одно окно на все мониторы или использовать отдельное окно для каждого. Поведение настраивается и в целом предсказуемо.
Практические особенности
При использовании нескольких мониторов начинают проявляться нюансы, связанные не столько с SPICE, сколько с общей сложностью конфигурации.
Синхронизация. Окно, растянутое на два монитора, должно обновляться синхронно. Любые задержки между surface становятся визуально заметны на границе экранов — в виде «шва» или кратковременного рассинхрона при движении курсора.
Разные разрешения. Конфигурации с одинаковыми мониторами обычно работают стабильнее. Смесь Full HD и 4K добавляет сложности: масштабирование, разные пропорции, смешанный DPI. Не все сочетания отрабатываются одинаково гладко.
Разный DPI. Типичный пример — ноутбук с Retina-экраном и внешний Full HD монитор. Как именно отображать такую конфигурацию в гостевой системе — однозначного ответа нет. Это компромисс между читаемостью и чёткостью.
Поведение гостевой ОС. Windows с QXL WDDM и Linux с xf86-video-qxl ведут себя по-разному. Некоторые комбинации работают без проблем, другие требуют подбора настроек и экспериментов.
Порядок мониторов. Иногда гость определяет порядок дисплеев иначе, чем клиент. В результате логика «лево–право» может не совпадать с физическим расположением мониторов и требует ручной коррекции.
Практические ориентиры
Multi-monitor с SPICE обычно даёт наилучший результат, когда:
все мониторы одного разрешения
одинаковый DPI
нагрузка преимущественно офисная
В более сложных конфигурациях multi-monitor остаётся рабочим, но требует времени на настройку и готовности к тому, что не все сочетания параметров будут вести себя идеально. Это естественное следствие увеличения сложности, а не признак некорректной работы протокола.

Как правильно применять специи
Инфраструктура
Bandwidth — для VDI важен запас по пропускной способности. Гигабит на пользовательский сегмент — разумный ориентир. Речь не о «гигабите на всех», а о том, что этот гигабит должен быть реально доступен. Если 50 пользователей делят его с остальным офисным трафиком, ограничения проявятся довольно быстро.
QoS — если сеть shared, имеет смысл приоритизировать SPICE-трафик. По умолчанию используются порты 5900+. Это не решает проблему нехватки bandwidth, но помогает снизить задержки и сгладить пиковые нагрузки.
Топология — чем меньше hops между клиентом и хостом, тем лучше. VDI через WAN всегда работает как компромисс. Если есть возможность размещать хосты ближе к пользователям — это почти всегда даёт ощутимый эффект.
Выделенная сеть — в идеальном случае VDI-трафик идёт по отдельному VLAN и не конкурирует с обычным офисным трафиком. Это упрощает прогнозирование нагрузки и диагностику проблем.
Гость
Визуальные эффекты. Анимации, прозрачность, тени и сглаживание шрифтов напрямую превращаются в обновления экрана. Отключение эффектов снижает объём передаваемых данных и делает поведение системы более предсказуемым. Windows: Performance Options → Adjust for best performance. Linux: лёгкий window manager без композитора или минимальный набор эффектов.
Разрешение экрана. Иногда чёткий Full HD даёт лучший пользовательский опыт, чем 4K с постоянными задержками. Пользователи часто ожидают «как на своём ноутбуке», но физические ограничения никуда не исчезают. Здесь почти всегда приходится искать баланс.
Фон рабочего стола. Однотонный фон сжимается заметно лучше, чем фотография или сложный градиент. Это мелочь, но в сумме она снижает шум в Display Channel.
Screensaver. Анимированные заставки в VDI обычно не дают практической пользы и создают лишний трафик. В большинстве сценариев их проще отключить.
Клиент
Актуальная версия remote-viewer. Использование свежего virt-viewer важно для поддержки новых кодеков и исправлений. Старые версии могут работать корректно, но часто становятся узким местом.
Аппаратное декодирование. Если клиент поддерживает VA-API (Linux) или DXVA (Windows), имеет смысл включить hardware decoding. Это снижает нагрузку на CPU и улучшает плавность.
Производительность клиента. Даже при аппаратном декодировании требуется определённый запас по CPU. Raspberry Pi 3 находится на границе комфортной работы, Pi 4 уже заметно лучше. Обычный ноутбук, как правило, справляется без проблем.
Про ожидания
Офисная работа в LAN — это базовый сценарий, под который SPICE и проектировался. Текстовые редакторы, таблицы, браузер без активного видео, почта — всё это работает стабильно и предсказуемо.
Видео, 4K и WAN с потерями выходят за пределы основного сценария. В отдельных конфигурациях это может работать приемлемо, но всегда с оговорками и компромиссами.
Понимание этих границ — не ограничение, а инструмент. Оно позволяет применять SPICE там, где он действительно эффективен, и не требовать от него того, для чего он не предназначался.
Итог
SPICE изначально не проектировался как медиа-протокол. В момент его появления основной сценарий был довольно чётким: офисная работа, текст, интерфейсы. Поддержка видео добавлялась позже, постепенно и в рамках тех ресурсов, которые были доступны проекту. Это наложило свой отпечаток на архитектуру — и его невозможно не заметить.
Image Mode в этой модели чувствует себя уверенно. Для статичного контента он работает быстро и эффективно: изменения локальные, сжатие хорошее, задержки предсказуемые. Если основной сценарий — текст, интерфейсы и изображения, SPICE справляется с этим очень достойно.
Stream Mode позволяет работать с видео, но несёт в себе исторические компромиссы. MJPEG по умолчанию — наследие конца 2000-х с заметным оверхедом по bandwidth. Использование GStreamer открывает путь к современным кодекам, но требует дополнительной настройки, сборки плагинов и совместимости между клиентом и сервером. Даже с H.264 это остаётся иным классом решений по сравнению с коммерческими VDI, где над мультимедиа годами работают специализированные команды.
При высокой плотности виртуальных машин encoding становится ограничивающим фактором. Увеличить вычислительные ресурсы можно, но это всегда связано с дополнительными затратами и не масштабируется бесконечно. Просмотр видео внутри виртуальной машины добавляет ещё один уровень сложности из-за двойного преобразования, и в рамках текущей архитектуры SPICE это ограничение не имеет простого решения. Video passthrough здесь отсутствует и потребовал бы серьёзных архитектурных изменений.
Разрешения 4K в SPICE работают приемлемо для статичных сценариев, но при видео и активной динамике быстро упираются в ресурсы. Multi-monitor добавляет удобство пользователю, но одновременно увеличивает нагрузку и сложность конфигурации.
spice-streaming-agent остаётся практичным обходным решением для сценариев с GPU passthrough. Он закрывает конкретный класс задач и позволяет получить рабочий стриминг там, где классический Display Channel неприменим. При этом его текущее состояние логично воспринимать как инструмент для узкого набора сценариев, а не универсальное решение.
В какой-то момент становится очевидно: SPICE хорошо справляется с теми задачами, под которые он изначально создавался. Офисная работа в локальной сети — текст, почта, браузер без активного видео, один-два Full HD монитора — это сценарии, где он остаётся надёжным и предсказуемым инструментом.
За пределами этих условий начинаются компромиссы. Видео будет уступать локальному воспроизведению, 4K потребует ресурсов, WAN добавит задержки. Иногда такие компромиссы допустимы, иногда — нет. В этих случаях разумно рассматривать другие подходы: коммерческие VDI-решения, GPU passthrough с альтернативным стримингом или локальную рабочую станцию.
Вопрос здесь не в том, хорош SPICE или плох. Вопрос в том, насколько он подходит для конкретного сценария. Эта статья — попытка дать достаточно контекста и практических наблюдений, чтобы такой выбор можно было сделать осознанно и без иллюзий.
В следующей статье: Цена отклика — почему «быстрое видео» не равно «комфортная работа». Разберём Input Channel, Cursor Channel, round-trip latency. Потому что UX определяется не только битрейтом — иногда задержка ввода важнее качества картинки.
И это, пожалуй, самая недооценённая часть VDI — не как красиво показать картинку, а как быстро среагировать на действие пользователя.