Создаём расширение google chrome для записи экрана и камеры

от автора

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

В расширении также будет использоваться интернационализация (i18next). Для управления состоянием будет использоваться библиотека onChange. Для перемещения встраиваемой камеры по странице jquery-ui. И для стилизации видеоплеера библиотека plyr-player.

Ссылка на исходный код расширения

Первым делом нужно настроить главный файл расширения google chrome — manifest.json

"action": {     "default_popup": "html/popup.html"  },

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

"background": {     "service_worker": "js/background.js",     "type": "module"  },

Файл background.js обязателен для всех расширений google chrome. Он может использоваться для выполнения различных задач в фоновом режиме, таких как обновление данных, отправка запросов на сервер, мониторинг веб-страниц и т.д. Это позволяет расширению работать в фоновом режиме, даже если пользователь не активен в браузере. В нашем случаем в нем нет необходимости, поэтому просто создадим его и оставим пустым.

"content_scripts": [     {       "matches": [         "https://*/*",         "http://*/*"       ],       "js": [         "js/content-script.js"       ]     }   ],

Пожалуй, главный файл нашего расширения — это content-script.js. Он может использоваться для изменения внешнего вида и поведения веб-страницы, добавления или удаления элементов на странице, взаимодействия с содержимым страницы и т.д. matches: URL-адреса веб-страниц, на которых должен быть запущен сценарий.

"web_accessible_resources": [     {       "matches": [         "<all_urls>"       ],       "resources": [         "html/popup.html",         "html/iframe.html",         "js/renderContent/camera.js",         "js/renderContent/iframe.js",         "libs/jquery-3.6.0.min.js",         "libs/jquery-ui.min.js"       ]     }   ],

Файл «web_accessible_resources» в Google Chrome Extension используется для определения ресурсов, которые могут быть доступны на веб-странице, даже если они находятся за пределами расширения.

"permissions": [     "tabs",     "storage",     "downloads",     "activeTab",     "scripting"   ]

Ну и «permissions» является важным элементом в разработке расширений Google Chrome, позволяющим расширению запросить необходимые разрешения у пользователя, чтобы выполнить необходимые действия. Без этого файла расширение не сможет получить доступ к некоторым функциям браузера, что может ограничить его функциональность.

вид popup
setTimeout(() => {     chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {       chrome.tabs.sendMessage(tabs[0].id, "open")       window.close()     })  }, 1500)

Итак в выпадающем окне popup у нас отображается loader, после загрузки которого с помощью таймера передается сообщение в content-script и закрывается наш popup с помощью window.close()

chrome.runtime.onMessage.addListener((msg, _, sendResponse) => {   const iframePlugin = document.querySelector("#record_plugin")    switch (msg) {     case "close": {       iframePlugin?.remove()       break     }     case "open": {       ;(async () => {         const src = chrome.runtime.getURL("js/renderContent/iframe.js")         const contentScript = await import(src)         contentScript.renderIframe(iframePlugin)       })()       break     }

В content-script мы слушаем сообщения, которые нам приходят из popup и из нашего iframe, который мы встраиваем тут же.

iframe после встраивания на страницу

Внутри iframe будет происходить основная логика расширения. За доступ к содержимому экрана, звуку системы, микрофону и камере будет отвечать класс Media с помощью методов navigator.mediaDevices.getDisplayMedia и navigator.mediaDevices.getUserMedia.

получение видеопотока с камеры
а тут получение доступа к видеопотоку экрана
if (state.mode === "screen") {         combine = new MediaStream([           ...this.screenStream.getTracks(),           ...this.voiceStream.getTracks(),         ])       } else {         combine = new MediaStream([           ...this.cameraStream.getTracks(),           ...this.voiceStream.getTracks(),         ])       }

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

let blobData = new Blob(data, { type: "video/mp4" }) // Convert the blob data to a url let url = URL.createObjectURL(blobData) // Assign the url to the output video tag and anchor output.src = url downloadTitle.href = url

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

const player = new Plyr("#video", {     controls: [       "play-large",       "play",       "progress",       "current-time",       "volume",       "captions",       "settings",       "fullscreen",     ],   })   const newMedia = new Media()   const defaultLanguage = lStorage.get("language_plugin") || "en"   newMedia.getFlowCamera()    const i18nInstance = i18next.createInstance()   await i18nInstance.init({     lng: defaultLanguage,     debug: false,     resources,   })

Итак внутри iframe сперва создаем экземпляр плеера, затем экземпляр Media для работы с потоками видео и аудио, запрашиваем доступ к камере, достаем из localStorage текущий язык и инициализируем тексты.

const initialState = {     //активность записи     recording: false,     language: defaultLanguage,     // полный экран для плеера     fullscreen: false,     // проверка на то, что запись не пустая     emptyRecord: true,     // режим - screen или camera     mode: "screen",     UIState: {       wiewIframe: "control",       switch: {         microphone: false,         camera: false,         cameraLocal: false,         audio: false,       },     },   }

Создаем стейт iframe, состояние которого будем отслеживать с помощью библиотеки onChange и в следствие этих изменений перерисовывать наш UI.

Также создаем объект со всеми необходимыми элементами, на которые навешиваем обработчики, внутри которых будет меняться наш стейт.

вид UI после записи экрана

Таким образом, в данной статье мы в общих чертах рассмотрели создание расширения google chrome для записи экрана и камеры. Исходный код — для более детального ознакомления с расширением.


ссылка на оригинал статьи https://habr.com/ru/post/721158/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *