Part 2 - Media Devices
Contents:
- Part 1: Introduction to WebRTC and creating the signaling server Link
- Part 2: Understanding the MediaDevices API and getting access to the user’s media devices Link
- Part 3: Creating the peers and sending/receiving media Link
- Part 4: Sharing and sending the user’s display and changing tracks Link
- Part 5: Data Channels basics Link
- Part 5.5: Building the WebRTC Android Library Link
- Part 6: Android native peer Link
- Part 7: iOS native peer
- Part 8: Where to go from here
Hello, welcome to part 2 of my beginner WebRTC series :)
In this part I will introduce the MediaDevices API, how to get the user’s media devices (camera and microphone) and how to get a certain video resolution etc.
This part carries on from the previous part, so if you have not seen that please take the time to do so. (Or you could just clone the repo ;))
Part 1: WebRTC For Beginners - DEV Community
In order to use the Media Devices API, you must host your page on a secure domain. Also the user must allow the page to get access to their camera and microphone, this changes depending what browser is used. (Chrome asks once whilst Safari asks every session). If the page is not secure you may get an undefined returned when trying to use the MediaDevices API.
Well then let’s get started.
First we will prepare the static HTML file, so open public_index.html in your preferred IDE and type_copy the following:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Part 2 - Media Devices</title>
<meta charset="utf-8"/>
</head>
<body>
<h2>Media Devices example</h2>
<button onclick="startDefault()">Default</button>
<button onclick="startVGA()">VGA</button>
<button onclick="startHD()">HD</button>
<button onclick="startFullHD()">Full HD</button>
<button onclick="stop()">Stop</button>
<hr/>
<video id="localVideo" autoplay muted></video>
<script src="./main.js"></script>
</body>
</html>
Next we will need to prepare the main.js file, open public_main.js and type_copy the following: (Don’t worry I will explain what is going on after)
const localVideo = document.getElementById('localVideo');
const startDefault = () => getMedia({ video: true, audio: true });
const startVGA = () => getMedia({ video: { width: 640, height: 480 }, audio: true });
const startHD = () => getMedia({ video: { width: 1280, height: 720 }, audio: true });
const startFullHD = () => getMedia({ video: { width: 1920, height: 1080 }, audio: true });
const stop = () => {
if (!localVideo.srcObject) return;
for (const track of localVideo.srcObject.getTracks()) {
track.stop();
}
};
const getMedia = async (constraints) => {
try {
console.log('getMedia constraints: ', constraints);
const mediaStream = await navigator.mediaDevices.getUserMedia(constraints);
localVideo.srcObject = mediaStream;
} catch (error) {
alert('failed to get media devices, see console for error');
console.error(error);
}
};
Each function basically calls “navigator.mediaDevices.getUserMedia” with different media constraints. I will explain what the constraints mean, but first let’s run the examples.
npm i # If needed
npm run start
Now open your browser and go to:
https://localhost:3000
You should get an SSL error, but hopefully you trust your own host ;) If you are using chrome you may not be able to excess the page, if so please enter “thisisunsafe”.
There you should see the following page:
example — ImgBB
Feel free to experiment with the various buttons, you can tell if you have the resolution just from the size of the video :)
You may notice for example if you pick “Full HD” the resolution returned may be just “HD”. This is because if the resolution is not supported the API will automatically choose the resolution closest to the resolution wanted.
What if you absolutely wanted to make sure you get a certain resolution? You would need to use “exact” as shown below:
const constraints = { video: { width: { exact: 1920 }, height: { exact: 1080 } } };
This would make absolutely sure the resolution was full HD, however if the device does not support full HD it will throw an error.
What if you wanted a range? You would define the constraints like so:
const constraints = { video: { width: { min: 600, max: 1300 }, height: { min: 300, max: 800 } } };
One thing you will need to be careful of is that when you are sending the media to another peer, WebRTC may alter the resolution/frame rate according to the available bitrate, network condition, packet loss etc. Because of this I generally don’t recommend using the “exact” parameter, only use it if you plan to use the video locally.
Well that wraps up this part, hope to see you in part 3 where we finally get to send and receive media between peers!
Source Code: https://github.com/ethand91/webrtc-tutorial
Bonus: Things to consider:
- Is it possible to get just the camera/microphone without the other?
- See if you can adjust the video frame rate via the constraints.
- How would you handle the user not having a camera/mic? What if they just blocked access altogether?
- If using a smartphone, can you get the back camera?
MediaDevices.getUserMedia API:
MediaDevices.getUserMedia() - Web APIs | MDN
Top comments (2)
Amazing post. Thanks for sharing.
Hello! You can use the
series
in dev.to. It can help you to hold a lot of posts. :)