i'm building a chrome extension that is used for screen and video capturing. Curently I'm having issuing with capturing both user's camera and screen at the same time. I had to capture the user's camera and display it to them while the recording of screen is going on.
I had initilized the request from the offscreen.js but I couldnt get it to display it on the screen because I couldn't use document.querySelector
from there as it return null
Second I have tried initializing the request from content-script but it would appear with the name of the hosting site.
My question now is:
.. Any better way of getting this to work is welcomed. This implementation is already in loom chrome extension. But I couldnt figure out how they got that to work
Finally, I got it working. first, you need to update your Chrome browser to the latest version at the time of my question I was using version 117, but upon updating to version 123, most of the bottlenecks gave way;
navigator.getUserMedia()
and its counterpart navigator.getDisplayMedia()
from the offscreen script. Then to handle my issue of accessing both camera, display and audio all at once and still showing a small preview screen to the user: I initialized the request from the offscreen page so I can access the camera and screen from any webpage the user is visiting. Then upon initializing, I sent a message to the content script which houses the code for initialising the front camera to have it appear at the bottom of the users' scene. the message could only be sent through the background script.// background.js
const OFFSCREEN_DOCUMENT_PATH = 'src/offscreen/index.html'
let creating:any = null
async function hasDocument() {
const offscreenUrl = chrome.runtime.getURL(OFFSCREEN_DOCUMENT_PATH)
const existingContexts = await chrome.runtime.getContexts({
contextTypes: ['OFFSCREEN_DOCUMENT'],
documentUrls: [offscreenUrl],
})
// console.log(existingContexts)
if (existingContexts.length > 0) {
return true
}
return false
}
async function setupOffscreenDocument(path) {
if (!(await hasDocument())) {
if (creating) {
await creating
} else {
creating = chrome.offscreen.createDocument({
url: chrome.runtime.getURL(path),
reasons: ['USER_MEDIA', 'BLOBS', 'DISPLAY_MEDIA', 'WEB_RTC'],
justification: 'Recording user media ',
})
await creating
// write code to claim offscreen as a client
creating = null
}
}
const offscreenUrl = chrome.runtime.getURL(path)
const existingContexts = await chrome.runtime.getContexts({
contextTypes: ['OFFSCREEN_DOCUMENT'],
documentUrls: [offscreenUrl],
})
return true
}
async function closeOffscreenDocument() {
if (!(await hasDocument())) {
return
}
await chrome.offscreen.closeDocument()
}
async function startRecording(message) {
await setupOffscreenDocument(OFFSCREEN_DOCUMENT_PATH)
chrome.runtime.sendMessage({
target: 'offscreen',
type: 'get-user-recording',
data: ''
})
}
........................
// offscreen.js script
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type == 'get-user-recording' && message.target == 'offscreen') {
handleMessage(message.data)
sendResponse()
} else if (
message.type == 'stop-recording' &&
message.target == 'offscreen'
) {
//stopRecording()
recorder.stop()
sendResponse()
}
})
// content script
chrome.runtime.onMessage.addListener(async (msg) => {
if (msg.type == 'notice' && msg.target == 'start_camera') {
.......
} else if (msg.type == 'notice' && msg.target == 'stop_camera') {
......
}
})
To end the camera, the message is also related from offscreen to the content script through the background script to request the small camera be stopped.