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

Конечно, для записи экрана существует тонна различного софта — и платного, и бесплатного. FFmpeg уверенно держит свои позиции из-за кроссплатформенности, минимального интерфейса (которого нет совсем, все управляется через консоль операционной системы) и огромного количества функций. На базе FFmpeg сделано множество программ по конвертированию видео из одного формата в другой. FFmpeg абсолютно самодостаточен. Для того чтобы посмотреть фильм нет необходимости искать в сети, скачивать и устанавливать кодеки. Достаточно всего лишь одного файла (ffplay.exe), все кодеки содержатся внутри этого файла.

Петь дифирамбы этому пакету можно бесконечно, настолько он хорош. Но, как упоминалось выше, мы здесь собрались по другому поводу.

В путь!

Экран в поток

Задача очень простая — нужно транслировать происходящее на экране компьютера на сайт, где поток будет воспроизводиться по технологии WebRTC. Захватить нужно как видео, так и звук.

sсhema_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

Рассмотрим два варианта решения с помощью 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

Перед публикацией статьи в блоге я проверил получившуюся команду и, к своему разочарованию, получил полное отсутствие в потоке и аудио, и видео составляющих.

no-audio-no-video_play_stream_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_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.

Итак. Захватываем экран в поток

no-audio_windows_publish_stream_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

и ловим его на стороне WCS. (Здесь и далее я использую плеер из примера Media Devices, потому что он позволяет на скриншоте показать наличие или отсутствие аудио потока.)

no-audio_windows_play_stream_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

Получаем поток скриншаринга. Правда без звука. На скриншоте видно, что в разделе «Audio stats» все по нулям.

Теперь предлагаю разобраться с захватом звука.

Первым шагом нужно определить доступные устройства для захвата звука. Все там же, в консоли Windows, выполняем команду:

ffmpeg -list_devices true -f dshow -i dummy

Получаем примерно такую картину:

list_device_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

В результате выполнения команды выводится список устройств, которые могут записывать или выводить звук. Это будут колонки, микрофоны и веб-камеры. В этом списке найдите имя аудиоустройства, то есть ваших динамиков, с которых вы хотите записывать звук. На скриншоте аудиоустройство, с которого я собираюсь захватывать звук, называется «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_mixer_windows_play_stream_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

Существует еще альтернативный метод. Он будет полезен, если у вас на компьютере нет устройства «Stereo Mix» или драйвер вашей звуковой карты его, по каким-то причинам, не поддерживает.

Для реализации альтернативного метода нам понадобится небольшая утилита «VB-Audio Virtual Cable» (На момент написания этой статьи распространяется бесплатно).

VB-CABLE — это виртуальное аудиоустройство, работающее как виртуальный аудиокабель. Весь звук, поступающий на вход CABLE, просто пересылается на выход CABLE.

Скачиваем программу VB-CABLE и устанавливаем. Установка не представляет собой ничего примечательного.

Запускаем установочный файл от имени администратора:

run-as-administrator_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

И нажимаем кнопку «Install Driver»

install_driver_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

После установки нужно переключить устройство по умолчанию для воспроизведения и записи аудио на установленный виртуальный кабель.

set_as_default_device_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

Теперь, звуки, воспроизводимые в программах, будут перенаправляться на виртуальное устройство Cable Output, которое будет работать как обычный микрофон и, соответственно, позволит захватить воспроизводимое аудио. Однако, при этом есть один недостаток: во время этого вы не будете слышать то, что записываете (т.е. звук вместо динамиков или наушников будет направляться на виртуальное устройство записи).

Теперь снова определяем доступные устройства для захвата аудио

ffmpeg -list_devices true -f dshow -i dummy

Видим, что в списке устройств появилось устройство «CABLE Output (VB-Audio Virtual Cable)»

list_device_Cable_Output_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

Запускаем захват скриншаринга с использованием этого устройства. Обращаемся к нему так же по альтернативному имени:

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

Cable_Output_windows_play_stream_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

Решение под Linux

В этом примере мы запускаем скриншаринг на ОС Ubuntu Desktop 20.04 LTS.

Начнем с определения доступных для захвата аудиоустройств. Выполните в консоли следующую команду:

pacmd list-sources

Вывод будет примерно таким как на скриншоте. Для дальнейшей работы нас интересует устройство, которое в Ubuntu называется «Monitor of Built-in Audio Analog Stereo». Это виртуальное устройство, которое, как и его кузен «Windows Stereo Mix», позволяет смешивать системные звуки и звуковой поток, получаемый с микрофона. Для дальнейшей работы нам понадобится значение индекса этого устройства.

linux_list_device_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

Запускаем скриншаринг в поток с помощью 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 команду, которую разобрали выше:

linux_publish_stream_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_stream

На стороне WCS сервера открываем любой удобный плеер и запускаем воспроизведение захваченного потока скриншаринга по WebRTC (имя потока rtmp_stream).

linux_play_stream_ffmpeg_screensharing_WebRTC_RTMP_WCS_bitrate_codec_framerate_video_audio_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. Он может быть записан, воспроизведен, ретранслирован, транскодирован или добавлен к микшеру.

До встречи на страницах нашего блога и удачного стриминга!

Ссылки

Наш демо сервер

WCS на Amazon EC2

WCS на DigitalOcean

WCS в Docker