Linux: захват видео с рабочего стола по сети и частота кадров VNC - PullRequest
30 голосов
/ 27 ноября 2010

Извините за стену текста - TL; DR:

  • Какова частота кадров соединения VNC (в кадрах / сек), или, скорее, кто его определяет: клиент или сервер?
  • Любые другие предложения для захвата экрана рабочего стола - но «правильно закодированные» / с неизменной частотой кадров (со стабильным периодом); и с возможностью получить его в виде несжатой (или без потерь) последовательности изображений?

Вкратце - у меня есть типичная проблема, с которой я сталкиваюсь: я иногда разрабатываю аппаратное обеспечение и хочу записать видео, которое показывает обе команды, введенные на ПК («захват рабочего стола»), и ответы оборудования («живое видео»). Далее следует часть вступления, прежде чем я перейду к конкретным деталям.

Введение / Контекст

На данный момент моей стратегией является использование видеокамеры для записи процесса аппаратного тестирования ( как «живое» видео ) - и одновременный захват рабочего стола. Видеокамера производит видеоизображение с разрешением 29,97 (30) FPS MPEG-2 .AVI; и я хочу получить захват рабочего стола в виде последовательности изображений PNG с той же частотой кадров, что и у видео. Идея была бы такова: если частота кадров двух видео одинакова; тогда я мог бы просто

  • выровнять время начала захвата рабочего стола с точкой совпадения в «живом» видео
  • Установите картинка в картинке , где уменьшенная версия захвата рабочего стола помещается - как наложение - поверх «живого» видео
    • (где часть экрана в «живом» видео служит источником визуальной синхронизации с наложением «захват рабочего стола»)
  • Экспорт «окончательного» комбинированного видео, сжатого соответствующим образом для Интернета

В принципе, я думаю, что для этого процесса можно использовать инструмент командной строки, например ffmpeg; однако я бы предпочел использовать графический интерфейс для нахождения начальной точки выравнивания для двух видео.

В конечном итоге я также хочу добиться максимального качества при экспорте «окончательного» видео: «живое» видео уже сжато вне камеры, что означает дополнительную деградацию при прохождении через Theora. Кодек ogv - вот почему я хотел бы сохранить исходное видео и использовать что-то вроде командной строки для создания «окончательного» видео заново, если требуется другое сжатие / разрешение. Вот почему мне нравится, когда видео «захвата рабочего стола» представляет собой последовательность PNG (хотя я предполагаю, что подойдет любой несжатый формат): я принимаю меры для «настройки» рабочего стола, чтобы не было большого количества градиентов и кодирования без потерь (т.е. PNG) будет уместно.

Параметры захвата рабочего стола

Что ж, в этом процессе много проблем с Ubuntu Lucid, который я сейчас использую (, и о некоторых из моих испытаний вы можете прочитать в 10.04: Оверлей видео / композитное редактирование с Theora ogv - Форумы Ubuntu ). Тем не менее, одной из важнейших проблем является предположение, что частота кадров двух входящих видео одинакова - в действительности, обычно захват рабочего стола имеет более низкую частоту кадров; и что еще хуже, очень часто кадры не синхронизированы .

Это, следовательно, требует хлопот, когда вы сидите перед видеоредактором и вручную обрезаете и редактируете менее чем за секунду клипы на уровне кадра - это требует часов работы для того, что будет в конце видео 5 минута . С другой стороны, если два видео («живое» и «захват») имели , имеют одинаковую частоту кадров и синхронизацию: в принципе, вам не потребуется больше пары минут, чтобы найти начало точка синхронизации в видеоредакторе - и остальная часть «объединенной» обработки видео может быть обработана одной командной строкой. Вот почему в этом посте я хотел бы сосредоточиться на захвате рабочего стола часть.

Насколько я могу видеть, существует всего несколько жизнеспособных (в отличие от 5 способов показать ваш рабочий стол Linux ) альтернатив для захвата рабочего стола в Linux / Ubuntu (заметьте,Обычно я использую ноутбук в качестве цели для захвата рабочего стола):

  1. Пусть ваш целевой ПК (ноутбук) клонирует рабочий стол на своем VGA-выходе;использовать VGA-композитное или VGA-S-видео оборудование для получения видеосигнала от VGA;использовать карту видеозахвата на другом ПК для захвата видео
  2. Использование recordMyDesktop на целевом ПК
  3. Настройка VNC-сервера (vi нет в Ubuntu или vncserver ) на целевом ПК для захвата;используйте программное обеспечение захвата VNC (например, vncrec ) на другом ПК для захвата / записи потока VNC (, который впоследствии можно преобразовать в видео ).
  4. Использование ffmpeg с опцией x11grab
  5. * ( использование какого-либо инструмента на целевом ПК, который будет выполнять DMA передачу образа рабочего столанепосредственно кадр - из памяти буфера кадра графической карты, в память сетевого адаптера )

Обратите внимание, что полезность вышеупомянутых подходов ограничена моим контекстом использования: целевой ПК, которыйЯ хочу, чтобы захватить, как правило, запускает программное обеспечение (с использованием протестированного оборудования), которое перемещается вокруг огромного количества данных;Лучше всего сказать, что описание такой системы «едва стабильно» :) Я думаю, это похоже на проблемы, с которыми сталкиваются геймеры, когда хотят получить видеосъемку требовательной игры.И как только я начинаю использовать что-то вроде recordMyDesktop, которое также использует довольно много ресурсов и хочет записать на локальный жесткий диск - я сразу получаю серьезные сбои ядра (часто без генерируемого vmcore).

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

(подготовка рабочего стола)

Для всех методов, обсуждаемых ниже, я склонен "Подготовьте рабочий стол заранее:

  • Удалите фоновые рисунки и значки рабочего стола
  • Установите разрешение 800x600 через Систему / Настройки / Мониторы (gnome-desktop-properties)
  • Измените глубину цвета до 16 бит / с (используя xdpyinfo | grep "of root" для проверки)

..., чтобы минимизировать нагрузку на программное обеспечение для захвата рабочего стола.Обратите внимание, что изменение глубины цвета в Ubuntu требует изменений в xorg.conf;однако " xorg.conf (is) не найден в / etc / X11 (Ubuntu 10.04) " - поэтому вам может потребоваться сначала запустить sudo Xorg -configure.

Чтобы сохранить графикуиспользование ресурсов низкое, также обычно у меня отключен compiz - или, скорее, я бы установил для «Система / Настройки / Внешний вид / Визуальные эффекты» значение «Нет».Однако после того, как я попытался включить compiz, установив «Визуальные эффекты» на «Нормальный» (, который не сохраняется ), я могу заметить, что окна на ЖК-экране перерисовываютсянамного быстрее;так что я держу это так, также для захвата рабочего стола.Я нахожу это немного странным: как больше эффектов может вызвать более быстрое обновление экрана?Это не похоже на то, что это связано с проприетарным драйвером (карта называется « Интегрированный графический контроллер семейства Intel N10 »), и Ubuntu не предоставляет опцию проприетарного драйвера при переключении на compiz) - хотяВозможно, все размытие и эффекты просто обманывают мои глаза :)).

Клонирование VGA

Ну, это самый дорогой вариант (так как требует дополнительной покупки не только одного, но две части аппаратного обеспечения: VGA конвертер и карта захвата видео);и применимо в основном к ноутбукам (которые имеют как экран + дополнительный выход VGA - для настольных компьютеров также может потребоваться покупка дополнительной видеокарты или оборудования для клонирования VGA).

Тем не менее, это также единственный вариант, который не требует никакого дополнительного программного обеспечения целевого ПК (и, следовательно, использует 0% вычислительной мощности целевого процессора) - И также единственный, который даст видео с true , частота кадров без помех составляет 30 к / с (поскольку это выполняется отдельным оборудованием - хотя, при условии, что смещение тактовых доменов, присутствующее между отдельными частями оборудования, незначительно).

На самом деле, поскольку у меня уже есть что-то вроде карты захвата, я уже вложил средства в VGA-конвертер - в ожидании, что это в конечном итоге позволит мне создавать окончательные «объединенные» видео всего с 5 минутами поиска точки выравнивания, и единая командная строка; но мне еще предстоит увидеть, будет ли этот процесс работать так, как задумано. Я также интересуюсь, насколько возможно будет захватывать десктоп в виде несжатого видео с разрешением 800x600, 30 кадров в секунду.

RecordMyDesktop

Хорошо, если вы запускаете recordMyDesktop без каких-либо аргументов - он начинается сначала с захвата (как выглядит) необработанных данных изображения в папке, подобной /tmp/rMD-session-7247; и после того, как вы нажмете Ctrl-C, чтобы прервать его, он будет кодировать эти необработанные данные изображения в .ogv. Очевидно, что получение больших данных изображений на том же жестком диске, что и мое тестовое программное обеспечение (которое также перемещает большие объемы данных), обычно является причиной инстакрафа:)

Следовательно, я попытался настроить Samba для совместного использования диска в сети; затем на целевом ПК я бы подключился к этому диску - и поручил recordMyDesktop использовать этот сетевой диск (через gvfs ) в качестве расположения временных файлов:

recordmydesktop --workdir /home/user/.gvfs/test\ on\ 192.168.1.100/capture/ --no-sound --quick-subsampling --fps 30 --overwrite -o capture.ogv 

Обратите внимание, что, хотя эта команда будет использовать сетевое местоположение для временных файлов (и, следовательно, позволяет recordMyDesktop работать параллельно с моим программным обеспечением) - как только вы нажмете Ctrl-C, она начнет кодирование и сохранение capture.ogv непосредственно на локальном жестком диске цели (хотя в этот момент мне все равно :))

Первое, что я поняла с recordMyDesktop, это то, что вы не можете указать ему сохранять временные файлы и избегать их кодирования, в конце концов: вы можете использовать Ctrl + Alt + p для паузы - или вы можете быстро нажать Ctrl-C после первого, чтобы вызвать его падение; который затем оставит временные файлы (, если вы не нажмете Ctrl-C достаточно быстро во второй раз, программа "Очистить кеш ..." ). Затем вы можете запустить, скажем:

recordmydesktop --rescue /home/user/.gvfs/test\ on\ 192.168.1.100/capture/rMD-session-7247/

... для преобразования необработанных временных данных. Тем не менее, чаще всего recordMyDesktop будет сам по себе в разгар выполнения этого «спасения». Хотя причина, по которой я хочу сохранить временные файлы, заключается в том, чтобы иметь несжатый источник для монтажа «картинка в картинке». Обратите внимание, что «--on-the-fly-encoding» вообще не будет использовать временные файлы - за счет использования большей вычислительной мощности процессора (что, для меня, опять же является причиной сбоев).

Затем, есть частота кадров - очевидно, вы можете установить запрашиваемую частоту кадров, используя опцию '--fps N'; тем не менее, это не гарантия того, что вы действительно получите эту частоту кадров; например, я бы получил:

recordmydesktop --fps 25
...
Saved 2983 frames in a total of 6023 requests
...

... для захвата при работающем тестовом программном обеспечении; это означает, что фактически достигнут скорость больше похожа на 25 * 2983/6032 = 12,3632 кадров в секунду!

Очевидно, что кадры пропущены - и в основном это показывает, что воспроизведение видео происходит слишком быстро . Однако, если я уменьшу запрошенный fps до 12 - тогда согласно сохраненным / итоговым отчетам я получу что-то вроде 11 fps; и в этом случае воспроизведение видео не выглядит «ускоренным». И я до сих пор не пытался выровнять такой захват с живым видео - поэтому я понятия не имею, имеют ли те кадры, которые действительно были сохранены, точную метку времени.

Захват VNC

Для меня захват VNC состоит из запуска VNC-сервера на «целевом» ПК и запуска vncrec (twibright edition) на «записывающем» ПК. В качестве VNC-сервера я использую vino, то есть «Система / Настройки / Удаленный рабочий стол (Настройки)». И, очевидно, даже если настройка vino может оказаться не самым простым в управлении, vino, поскольку сервер кажется не слишком обременительным для «целевого» ПК; поскольку я не испытывал сбоев, когда он работает параллельно с моим тестовым программным обеспечением.

С другой стороны, когда vncrec снимает на ПК с записывающим устройством, он также вызывает окно, показывающее вам «целевой» рабочий стол, как это видно в «реальном времени»; когда на «цели» происходят большие обновления (т. е. движутся целые окна) - вполне можно увидеть проблемы с частотой обновления / обновления на «рекордере». Но только для небольших обновлений (т. Е. Просто курсор, перемещающийся на статическом фоне), все выглядит хорошо.

Это заставляет меня задуматься об одном из моих основных вопросов в этом посте - что задает частоту кадров в соединении VNC?

Я не нашел четкого ответа на этот вопрос, но по частям информации ( см. Ссылки ниже ) я понял, что:

  • VNC-сервер просто отправляет изменения (изменения экрана + щелчки и т. Д.) Так быстро, как только может, когда получает их; ограничено максимальной пропускной способностью сети, доступной для сервера
  • Клиент VNC получает события изменений, задержанные и дрожащие сетевым подключением, и пытается восстановить рабочий стол "видео" снова, как можно быстрее

... это означает, что нельзя утверждать что-либо в терминах стабильной периодической частоты кадров (как в видео).

Что касается vncrec клиента, конечное видео, которое я получаю, обычно объявляется как 10 кадров в секунду, хотя кадры могут быть довольно смещены / дрожать (что затем требует обрезки в видеоредакторах). Обратите внимание, что vncrec-twibright / README заявляет: « Частота дискретизации фильма по умолчанию равна 10 или переопределяется переменной среды VNCREC_MOVIE_FRAMERATE, или 10, если она не указана. »; однако на странице руководства также указано « VNCREC_MOVIE_FRAMERATE - задает частоту кадров выходного фильма. Имеет эффект только в режиме -movie. По умолчанию - 10. Попробуйте 24, если ваш транскодер вызывает рвоту от 10. ». И если посмотреть на источник "vncrec/sockets.c", можно увидеть:

void print_movie_frames_up_to_time(struct timeval tv)
{
  static double framerate;
  ....
  memcpy(out, bufoutptr, buffered);
  if (appData.record)
    {
      writeLogHeader (); /* Writes the timestamp */
      fwrite (bufoutptr, 1, buffered, vncLog);
    }

... который показывает, что записаны некоторые временные метки - но я не могу сказать, являются ли эти временные метки источником «оригинального» «целевого» ПК или «рекордера». EDIT : благодаря ответу @kanaka я снова проверил vncrec / sockets.c и увидел, что сама функция writeLogHeader вызывает gettimeofday; таким образом, временные метки, которые он записывает, являются локальными, то есть они берутся с компьютера «рекордера» ( и, следовательно, эти временные метки не точно описывают, когда кадры возникли на «целевом» ПК ).

В любом случае, мне все еще кажется, что сервер отправляет - и vncrec при получении клиентом - всякий раз, когда ; и только в процессе кодирования видеофайла из исходного захвата впоследствии устанавливается / интерполируется некоторая форма частоты кадров.

Я также хотел бы заявить, что на моем «целевом» ноутбуке соединение с проводной сетью оборвано ; поэтому беспроводная связь - это мой единственный способ получить доступ к маршрутизатору и локальной сети - на гораздо более низкой скорости, чем 100 МБ / с, которые маршрутизатор может обрабатывать из проводных соединений. Однако, если дрожание в захваченных кадрах вызвано неправильными временными метками из-за нагрузки на «целевой» ПК, я не думаю, что хорошая пропускная способность сети слишком сильно поможет.

Наконец, что касается VNC, могут быть и другие альтернативы, такие как VNCast server ( многообещающий, но требует некоторого времени для сборки из исходного кода и находится на ранней стадии эксперимента). версия "); или MultiVNC (, хотя он выглядит как клиент / программа просмотра без параметров записи ).

ffmpeg с x11grab

Не играл с этим много, но я пробовал это в связи с netcat;это:

# 'target'
ffmpeg -f x11grab -b 8000k -r 30 -s 800x600 -i :0.0 -f rawvideo - | nc 192.168.1.100 5678
# 'recorder'
nc -l 0.0.0.0 5678 > raw.video  #

... захватывает файл, но ffplay не может правильно прочитать захваченный файл;в то время как:

# 'target'
ffmpeg -f x11grab -b 500k -r 30 -s 800x600 -i :0.0 -f yuv4mpegpipe -pix_fmt yuv444p - | nc 192.168.1.100 5678
# 'recorder'
nc -l 0.0.0.0 5678 | ffmpeg -i - /path/to/samplimg%03d.png

действительно создает изображения .png - но с артефактами сжатия (я думаю, это результат сжатия, связанного с yuv4mpegpipe).

Таким образом, мне не очень нравится ffmpeg + x11grab в настоящее время - но, возможно, я просто не знаю, как настроить его для своих нужд.

* (видеокарта -> DMA -> сеть)

Я, правда, не уверен, что что-то подобное существует - на самом деле, я бы поспорил, что нет :) И я 'Я не эксперт здесь, но я размышляю:

, если передача памяти DMA может быть инициирована с графической карты (или ее буфера, который сохраняет текущее растровое изображение рабочего стола) как source и сетевой адаптеркак destination - тогда в принципе должна быть возможность получить несжатый захват рабочего стола с правильной (и приличной) частотой кадров.Смысл использования DMA-передачи, конечно же, состоит в том, чтобы избавить процессор от задачи копирования образа рабочего стола в сетевой интерфейс ( и, таким образом, уменьшить влияние программного обеспечения захвата на процессы, выполняемые вцелевой ПК - особенно те, которые имеют дело с оперативной памятью или жестким диском ).

Подобное предположение, конечно, предполагает, что: существуют огромные увеличения пропускной способности сети ( для 800x600, 30 кадров в секунду по крайней мере 800 * 600 * 3 * 30 = 43200000 бит / с = 42 МБ / с, что должно быть в порядке для локальных сетей 100 МБ / с );много жесткого диска на другом ПК, который выполняет «запись» - и, наконец, программное обеспечение, которое впоследствии может читать эти необработанные данные и генерировать последовательности изображений или видео на их основе :)

Требования к пропускной способности и жесткому дискуЯ мог бы жить с - пока есть гарантия как для стабильной частоты кадров, так и для несжатых данных;вот почему я хотел бы услышать, если что-то подобное уже существует.

- - - - -

Ну, я думаю, что это было - как можно более кратко :) Любые предложения для инструментов - или процесса (ов),это может привести к захвату рабочего стола

  • в несжатом формате (в конечном итоге конвертируемому в последовательность изображений PNG без сжатия / без потерь) и
  • с "правильно заданным временем", стабильной частотой кадров

..., которая в конечном итоге пригодится для «простой» обработки в единой командной строке для создания оверлейных видеоизображений «картинка в картинке» - будет высоко оценена!

Спасибо зазаранее за любые комментарии,
Ура!


Ссылки

  1. Опыт создания скриншота для Linux для CryptoTE - idlebox.net
  2. Форумы VideoLAN •Просмотр темы - Поддержка ввода клиента VNC (например, screen: //)
  3. VNCServer регулирует пользовательский вход для медленного клиента - Kyprianou, Марк - com.realvnc.vnc-list - MarkMail
  4. FAQ по Linux - X Windows: Как я могу отображать и управлять удаленным рабочим столом с помощью VNC
  5. Какая пропускная способность требуется VNC?RealVNC - часто задаваемые вопросы
  6. x11vnc: VNC-сервер для реального отображения X
  7. HowtoRecordVNC (сеанс X11) - Debian Wiki
  8. Альтернатива gtk-RecordMyDesktop в Ubuntu
  9. (пользователь Ffmpeg) Как использовать каналы в ffmpeg
  10. (ffmpeg-devel) (PATCH) Исправление ошибки сегмента в x11grab при рисовании курсора на серверах X, которые не поддерживают расширение XFixes

1 Ответ

16 голосов
/ 30 ноября 2010

Вы должны получить значок за такой длинный колодец, хотя наш вопрос.; -)

В ответе на ваш основной вопрос VNC использует протокол RFB, который является протоколом удаленного буфера кадра (таким образом, аббревиатура), а не протоколом потокового видео.Клиент VNC отправляет сообщение FrameBufferUpdateRequest на сервер, который содержит область области просмотра, в которой заинтересован клиент, и инкрементальный флаг.Если инкрементный флаг не установлен, то сервер ответит сообщением FrameBufferUpdate, которое содержит содержимое запрошенной области.Если установлен инкрементный флаг, то сервер может ответить сообщением FrameBufferUpdate, которое содержит любые части запрошенного региона, которые изменились с момента последней отправки клиенту этого региона.

Определение порядка запросов и обновлений.взаимодействие не четко определено.Сервер не обязательно будет отвечать на каждый запрос обновлением, если ничего не изменилось.Если на сервере имеется несколько запросов, поставленных в очередь от клиента, ему также разрешается отправлять одно обновление в ответ.Кроме того, клиент действительно должен иметь возможность отвечать на асинхронное сообщение обновления от сервера (не в ответ на запрос), иначе клиент выйдет из синхронизации (поскольку RFB не является протоколом с фреймами).

Часто клиенты просто реализуют отправку запросов на постепенное обновление всего окна просмотра буфера кадра с периодическим интервалом и обрабатывают любые сообщения обновления сервера по мере их поступления (т.е. не делается попытка связать запросы и обновления вместе).

Здесь - описание сообщений FrameBufferUpdateRequest.

...