Создаём расширение 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": [
""
],
"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 для записи экрана и камеры. Исходный код — для более детального ознакомления с расширением.