There's a new feature that you can use on your custom UI with eyeson-js since v1.8.6.
Picture-in-picture camera is a nice addition to screenshare presentation as it includes the presenter's camera in the screenshare.
Support
It is only supported in chromium-based browsers like Chrome, Edge, Opera, etc. on desktop. So it will not work with Firefox and Safari whether on desktop nor on mobile.
The reason for Firefox is that it doesn't support the picture-in-picture API. And the reason for Safari is that it needs multiple user guestures to allow programmatic access to getUserMedia and picture-in-picture API.
It's not supported on mobile devices simply because browser screenshare is not available on mobile devices.
How it works
When a screenshare presentation is started, you need to check the type of screenshare. There are different types available: "monitor", "window", "browser". Picture-in-picture camera only makes sense in combination with "monitor", because otherwise it will not be part of the screenshare.
The presentation_started
event includes the new parameter present
. In case
it is set to screen-monitor
and the check for FeatureDetector.hasPipCamSupport()
is successfull, you can call eyeson.send({ type: 'start_pip_cam' })
.
It can be stopped with eyeson.send({ type: 'stop_pip_cam' })
.
New events
{ type: 'pip_cam', active: bool }
It indicates the current state of pip-cam and is triggered whenever the status
changes.
{ type: 'pip_cam_error' }
Triggered when pip-cam start has failed.
{ type: 'pip_cam_warning_video_ended' }
Triggered when an active pip-cam suddenly stopped working.
{ type: 'pip_cam_warning_unsupported' }
Triggered when pip-cam is started on an unsupported environment.
Show me the code
Here's an example that shows how the picture-in-picture camera feature can be combined with screenshare presentation.
Please note that this is just a very basic example for demonstration purpose.
import eyeson, { FeatureDetector } from 'eyeson';
const pipCamButton = document.querySelector('...');
pipCamButton.hidden = FeatureDetector.hasPipCamSupport() === false;
let pipCamActive = false;
const tryShowPipCam = present => {
if (present === 'screen-monitor' && FeatureDetector.hasPipCamSupport()) {
showPipCam();
}
};
const showPipCam = () => {
if (!pipCamActive) {
eyeson.send({ type: 'start_pip_cam' });
}
};
const hidePipCam = () => {
if (pipCamActive) {
eyeson.send({ type: 'stop_pip_cam' });
}
};
pipCamButton.addEventListener('click', () => {
if (!pipCamActive) {
showPipCam();
} else {
hidePipCam();
}
});
eyeson.onEvent(event => {
const { type } = event;
if (type === 'presentation_started') {
tryShowPipCam(event.present);
}
else if (type === 'presentation_ended') {
hidePipCam();
}
else if (type === 'pip_cam') {
pipCamActive = event.active;
pipCamButton.textContent =
event.active ? 'Hide camera' : 'Show camera';
}
else if (type === 'pip_cam_error') {
showError('...');
}
else if (type === 'pip_cam_warning_video_ended') {
showError('...');
}
});
eyeson.send({
type: 'start_screen_capture',
audio: true,
screen: true,
});
To make it even work better, you can combine it with pre-selected screensharing media:
// ... extend the example above
const startScreenCaptureOptions = {
type: 'start_screen_capture',
audio: true,
screen: true,
};
if (FeatureDetector.canChooseDisplaySurface()) {
startScreenCaptureOptions.surface = 'monitor';
}
eyeson.send(startScreenCaptureOptions);
Feedback or questions
If you have any feedback or question, feel free to add a ticket to the js-docs Github repository.