В сети можно найти достаточное количество мануалов, о том, как с помощью FFmpeg записать происходящее на экране в файл. В этой статье мы заглянем чуть дальше и попробуем передать поток скриншаринга, захваченный FFmpeg, в трансляцию на сайт.
Конечно, для записи экрана существует тонна различного софта — и платного, и бесплатного. FFmpeg уверенно держит свои позиции из-за кроссплатформенности, минимального интерфейса (которого нет совсем, все управляется через консоль операционной системы) и огромного количества функций. На базе FFmpeg сделано множество программ по конвертированию видео из одного формата в другой. FFmpeg абсолютно самодостаточен. Для того чтобы посмотреть фильм нет необходимости искать в сети, скачивать и устанавливать кодеки. Достаточно всего лишь одного файла (ffplay.exe), все кодеки содержатся внутри этого файла.
Петь дифирамбы этому пакету можно бесконечно, настолько он хорош. Но, как упоминалось выше, мы здесь собрались по другому поводу.
В путь!
Экран в поток
Задача очень простая — нужно транслировать происходящее на экране компьютера на сайт, где поток будет воспроизводиться по технологии WebRTC. Захватить нужно как видео, так и звук.
Рассмотрим два варианта решения с помощью FFmpeg, под Linux и под Windows.
Небольшое лирическое отступление о вреде перфекционизма
Здесь я решил сделать небольшое признание. При написании этой статьи мне впервые пришлось столкнуться с работой FFmpeg. Пришлось изучать мануалы и достаточно долго гуглить. В итоге, я нагуглил сочетание ключей программы FFmpeg для скриншаринга со звуком, на основании документации добавил ключи для передачи скриншаринга в поток на WCS сервере, успешно протестировал публикацию через FFMpeg и воспроизведение по WebRTC в среде Windows и Linux и начал писать эту статью-инструкцию.
На этапе тестирования команда для FFmpeg скриншаринга показалась мне достаточно хаотичной. Поэтому, работая над текстом статьи я решил ее «причесать» — собрал все что относится к захвату и кодированию видео в начале команды, потом собрал ключи для захвата и кодирования звука и завершил команду ключами для передачи данных на сервер и формирования потока.
Внимание! НЕ используйте эту команду!
ffmpeg.exe -f gdigrab -i desktop -draw_mouse 1 -rtbufsize 100M -framerate 30 -probesize 10M -c:v libx264 -r 30 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{F585B65B-4690-4433-8109-F16C6389C066}" -acodec aac -f flv rtmp://demo.flashphoner.com:1935/live/rtmp_stream
Перед публикацией статьи в блоге я проверил получившуюся команду и, к своему разочарованию, получил полное отсутствие в потоке и аудио, и видео составляющих.
Пришлось вернуться к мануалам и Google.
Я вновь и вновь проверял ключи, с которыми запускается FFmpeg. Я даже нашел альтернативный способ захвата системного звука для Windows (о чем обязательно расскажу далее). Я тестировал с разными драйверами в Windows и разными версиями рабочих столов в Ubuntu, но все мои действия приводили к одному:
На WCS сервере формировался пустой поток.
В одном из мануалов мне попалась фраза, которая прочно засела в моей голове: «Не смешивайте ключи для аудио и видео!». Вот я старательно и раскладывал ключи по полочкам. Сначала связанное с аудио, потом связанное с видео, потом передача в поток.
В какой-то момент, я запустил исходную команду, которая на первый взгляд выглядела хаотичным набором ключей. И, о чудо! В плеере был поток скриншаринга со звуком. Тогда я внимательно присмотрелся к ключам, и, наконец-то, понял свою ошибку. Нельзя смешивать ключи для аудио и видео и ключи для разных действий!
Опытным путем мне удалось выяснить, что структура команды должна быть такой:
ключи для захвата аудио + ключи для захвата видео + ключи для кодирования аудио + ключи для кодирования видео + ключи для отправки данных в поток на сервере
К сожалению, FFmpeg не поддерживает каких-либо служебных ключей для разделения секций команды, поэтому неопытному пользователю бывает сложно сориентироваться. Далее по тексту, в описаниях ключей я уточню, какие ключи к какому действию относятся.
Решение под Windows
Рассмотрим запуск скриншаринга в поток с помощью FFmpeg. В командной строке Windows запустите на выполнение следующую команду:
ffmpeg.exe -f gdigrab -rtbufsize 100M -framerate 30 -probesize 10M -draw_mouse 1 -i desktop -c:v libx264 -r 30 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p -f flv rtmp://demo.flashphoner.com:1935/live/rtmp_stream
где:
//захват видео составляющей скриншаринга
-f gdigrab — драйвер захвата экрана Windows;
-rtbufsize 100M — буфер под видео. Трансляция с экрана должна идти быстро и гладко, чтобы не было пропусков кадров. Поэтому лучше сначала записывать видео в оперативную память, а затем FFmpeg сам передаст его в поток.
-framerate 30 — частота кадров при захвате экрана;
-probesize 10M — количество кадров необходимое FFmpeg для идентификации потока;
-draw_mouse 1 — захватывать движения мыши;
-i desktop — говорим FFmpeg записывать весь экран.
//кодирование видео составляющей скриншаринга
-c:v libx264 — сжимать будем в формат MP4 кодеком x264;
-r 30 — кодек запишет видео с частотой 30 кадров в секунду;
-preset ultrafast — говорим кодеку, чтобы долго не раздумывал и кодировал видеопоток, как можно быстрее (при записи экрана это актуально);
-tune zerolatency — опция кодека x264 для ускорения кодирования;
-crf 25 — качество записываемого видео (большее значение — хуже видео, меньшее — лучше);
-pix_fmt yuv420p — цветовой формат результирующего видео.
//формирование потока и передача его WCS
-f flv rtmp://demo.flashphoner.com:1935/live/rtmp_stream — запись в поток с именем «rtmp_stream» и передача его на сервер demo.flashphoner.com.
Итак. Захватываем экран в поток
и ловим его на стороне WCS. (Здесь и далее я использую плеер из примера Media Devices, потому что он позволяет на скриншоте показать наличие или отсутствие аудио потока.)
Получаем поток скриншаринга. Правда без звука. На скриншоте видно, что в разделе «Audio stats» все по нулям.
Теперь предлагаю разобраться с захватом звука.
Первым шагом нужно определить доступные устройства для захвата звука. Все там же, в консоли Windows, выполняем команду:
ffmpeg -list_devices true -f dshow -i dummy
Получаем примерно такую картину:
В результате выполнения команды выводится список устройств, которые могут записывать или выводить звук. Это будут колонки, микрофоны и веб-камеры. В этом списке найдите имя аудиоустройства, то есть ваших динамиков, с которых вы хотите записывать звук. На скриншоте аудиоустройство, с которого я собираюсь захватывать звук, называется «Stereo Mix (Realtek (R) Audio)». Stereo Mix – одно из устройств записи звука. Это виртуальное (программное) устройство, которое позволяет смешивать источники звука, воспроизводимые внутри операционной системы и получаемые с микрофона.
Чтобы захватить звук в исходную команду для скриншаринга нужно добавить ключи:
-f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{8A4D10E5-8DB9-4B92-8C29-4BA2E60C1DDE}" ... -acodec aac
где:
//захват аудио составляющей скриншаринга
-f dshow — драйвер захвата звука Windows;
-i audio= — параметр «audio» в этом случае ставим равным альтернативному имени нашего «Stereo Mix (Realtek (R) Audio)».
//захват видео составляющей скриншаринга
//кодирование аудио составляющей скриншаринга
-acodec aac — сжимать аудио будем кодеком aac
//кодирование видео составляющей скриншаринга
//формирование потока и передача его WCS
Запускаем:
ffmpeg.exe -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{8A4D10E5-8DB9-4B92-8C29-4BA2E60C1DDE}" -rtbufsize 100M -f gdigrab -framerate 30 -probesize 10M -draw_mouse 1 -i desktop -acodec aac -c:v libx264 -r 30 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p -f flv rtmp://demo.flashphoner.com:1935/live/rtmp_stream
И наслаждаемся:
Существует еще альтернативный метод. Он будет полезен, если у вас на компьютере нет устройства «Stereo Mix» или драйвер вашей звуковой карты его, по каким-то причинам, не поддерживает.
Для реализации альтернативного метода нам понадобится небольшая утилита «VB-Audio Virtual Cable» (На момент написания этой статьи распространяется бесплатно).
VB-CABLE — это виртуальное аудиоустройство, работающее как виртуальный аудиокабель. Весь звук, поступающий на вход CABLE, просто пересылается на выход CABLE.
Скачиваем программу VB-CABLE и устанавливаем. Установка не представляет собой ничего примечательного.
Запускаем установочный файл от имени администратора:
И нажимаем кнопку «Install Driver»
После установки нужно переключить устройство по умолчанию для воспроизведения и записи аудио на установленный виртуальный кабель.
Теперь, звуки, воспроизводимые в программах, будут перенаправляться на виртуальное устройство Cable Output, которое будет работать как обычный микрофон и, соответственно, позволит захватить воспроизводимое аудио. Однако, при этом есть один недостаток: во время этого вы не будете слышать то, что записываете (т.е. звук вместо динамиков или наушников будет направляться на виртуальное устройство записи).
Теперь снова определяем доступные устройства для захвата аудио
ffmpeg -list_devices true -f dshow -i dummy
Видим, что в списке устройств появилось устройство «CABLE Output (VB-Audio Virtual Cable)»
Запускаем захват скриншаринга с использованием этого устройства. Обращаемся к нему так же по альтернативному имени:
ffmpeg.exe -f dshow -i audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{F585B65B-4690-4433-8109-F16C6389C066}" -rtbufsize 100M -f gdigrab -framerate 30 -probesize 10M -draw_mouse 1 -i desktop -acodec aac -c:v libx264 -r 30 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p -f flv rtmp://demo.flashphoner.com:1935/live/rtmp_stream
Решение под Linux
В этом примере мы запускаем скриншаринг на ОС Ubuntu Desktop 20.04 LTS.
Начнем с определения доступных для захвата аудиоустройств. Выполните в консоли следующую команду:
pacmd list-sources
Вывод будет примерно таким как на скриншоте. Для дальнейшей работы нас интересует устройство, которое в Ubuntu называется «Monitor of Built-in Audio Analog Stereo». Это виртуальное устройство, которое, как и его кузен «Windows Stereo Mix», позволяет смешивать системные звуки и звуковой поток, получаемый с микрофона. Для дальнейшей работы нам понадобится значение индекса этого устройства.
Запускаем скриншаринг в поток с помощью FFmpeg:
ffmpeg -f pulse -ac 2 -i 0 -f x11grab -rtbufsize 100M -s 1200x720 -framerate 30 -probesize 10M -draw_mouse 1 -i :0.0 -acodec aac -c:v libx264 -r 30 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p -f flv rtmp://demo.flashphoner.com:1935/live/rtmp_stream
где:
//захват аудио составляющей скриншаринга
-f pulse — драйвер захвата звука Linux;
-ac 2 — режим аудио «стерео» (-ac 1 — режим аудио «моно»);
-i 0 — указываем индекс устройства для захвата аудио. Как мы ранее выяснили, для «Monitor of Built-in Audio Analog Stereo» это «0».
//захват видео составляющей скриншаринга
-f x11grab — опция необходима, если вы захватываете экран Linux;
-rtbufsize 100M — буфер под видео;
-s 1200×720 — размеры захватываемой на экране области. В px;
-framerate 30 — частота кадров при захвате экрана;
-probesize 10M — количество кадров необходимое FFmpeg для идентификации потока;
-draw_mouse 1 — захват движений мышки;
-i :0.0 — координаты «первой точки» захватываемой области экрана.
//кодирование аудио составляющей скриншаринга
-acodec aac — сжимать аудио будем кодеком aac.
//кодирование видео составляющей скриншаринга
-c:v libx264 — сжимать видео будем в формат MP4 кодеком x264;
-r 30 — кодек запишет видео с частотой 30 кадров в секунду;
-preset ultrafast — кодировать поток как можно быстрее (при записи экрана это актуально);
-tune zerolatency — опция кодека x264 для ускорения кодирования;
-crf 25 — качество записываемого видео (большее значение — хуже видео, меньшее — лучше);
-pix_fmt yuv420p — цветовой формат результирующего видео.
//формирование потока и передача его WCS
-f flv rtmp://demo.flashphoner.com:1935/live/rtmp_stream — запись в поток с именем «rtmp_stream» и передача его на сервер demo.flashphoner.com.
Проверяем.
Запускаем воспроизведение ролика в плеере, в консоли Ubuntu запускаем FFmpeg команду, которую разобрали выше:
На стороне WCS сервера открываем любой удобный плеер и запускаем воспроизведение захваченного потока скриншаринга по WebRTC (имя потока rtmp_stream).
Сравнение команд FFmpeg для Windows и Linux
Сравнительная таблица ключей FFmpeg для скриншаринга с захватом системного звука и передачи данных в поток на WCS
Windows | Linux | |
Драйвер захвата звука | -f dshow | -f pulse |
Указание устройства для захвата звука | `-i audio=»@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{8A4D10E5-8DB9-4B92-8C29-4BA2E60C1DDE}»` | -i 0 |
Драйвер захвата экрана | -f gdigrab | -f x11grab |
Буфер под видео | -rtbufsize 100M | -rtbufsize 100M |
Размеры захватываемой на экране области | -i desktop | -i :0.0 <br /> -s 1200×720 |
Частота кадров при захвате экрана | -framerate 30 | -framerate 30 |
Количество кадров необходимое FFmpeg для идентификации поток | -probesize 10M | -probesize 10M |
Захватывать движения мыши | -draw_mouse 1 | -draw_mouse 1 |
Кодек для сжатия аудио | -acodec aac | -acodec aac |
Кодек для сжатия видео | -c:v libx264 | -c:v libx264 |
Частота кадров итогового видео | -r 30 | -r 30 |
Опция для ускорения кодирования | -preset ultrafast | -preset ultrafast |
Опция кодека x264 для ускорения кодирования | -tune zerolatency | -tune zerolatency |
Качество записываемого видео | -crf 25 | -crf 25 |
Цветовой формат результирующего видео | -pix_fmt yuv420p | -pix_fmt yuv420p |
Запись в поток на сервер demo.flashphoner.com | -f flv rtmp://demo.flashphoner.com:1935/live/rtmp_stream | -f flv rtmp://demo.flashphoner.com:1935/live/rtmp_stream |
Заключение
Сегодня мы в подробностях разобрали тонкости скриншаринга со звуком при помощи FFmpeg для операционных систем Windows и Linux. В дальнейшем, с потоком скриншаринга, который был захвачен на сервере можно производить любые действия, поддерживаемые WCS. Он может быть записан, воспроизведен, ретранслирован, транскодирован или добавлен к микшеру.
До встречи на страницах нашего блога и удачного стриминга!