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

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 будет происходить основная логика расширения. За доступ к содержимому экрана, звуку системы, микрофону и камере будет отвечать класс 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.
Также создаем объект со всеми необходимыми элементами, на которые навешиваем обработчики, внутри которых будет меняться наш стейт.

Таким образом, в данной статье мы в общих чертах рассмотрели создание расширения google chrome для записи экрана и камеры. Исходный код — для более детального ознакомления с расширением.
ссылка на оригинал статьи https://habr.com/ru/post/721158/
Добавить комментарий