{"componentChunkName":"component---packages-blog-gatsby-blog-core-src-templates-post-js-content-file-path-content-posts-dev-managing-devices-index-mdx","path":"/managing-devices-in-webrtc/","result":{"data":{"post":{"id":"296be325-9ce0-59fe-b746-bdc5e26a06a5","title":"Managing Devices in WebRTC","slug":"/managing-devices-in-webrtc/","link":null,"excerpt":"To have good WebRTC conversations, you first have to offer the user the right devices to use. Imagin…","tableOfContents":{"items":[{"url":"#introduction","title":"Introduction"},{"url":"#permissions","title":"Permissions"},{"url":"#devices-enumeration","title":"Devices enumeration"},{"url":"#grouping-devices-together","title":"Grouping devices together"},{"url":"#input-devices-selection","title":"Input devices selection"},{"url":"#output-devices-selection","title":"Output devices selection"},{"url":"#devices-changed","title":"Devices Changed"},{"url":"#alternatives","title":"Alternatives"},{"url":"#to-conclude","title":"To conclude"}]},"timeToRead":null,"featured":null,"protected":null,"thumbnailText":null,"date":"July 29, 2024","category":{"id":"0fde40c1-42e7-595e-8ce3-5969b3416bbd","name":"dev","slug":"/category/dev/","color":null,"icon":"/static/93c9c75517e1a6e95deaecabf3d1d050/dev.svg"},"author":{"id":"a1ce6965-86d7-5de2-8e55-c593e5fcc1bb","name":"Olivier Anguenot","slug":"/author/olivier-anguenot/","title":"Your WebRTC copilot","description":"Technical leader at Alcatel-Lucent Enterprise. Father of 2. Working on WebRTC the week-end","skills":["WebRTC","Javascript"],"social":[{"name":"Github","url":"https://github.com/oanguenot"},{"name":"Twitter","url":"https://twitter.com/oanguenot"},{"name":"Linkedin","url":"https://www.linkedin.com/in/olivier-anguenot-99503a33/"}],"thumbnail":{"__typename":"ImageSharp","ImageSharp_small":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAMC/9oADAMBAAIQAxAAAAGnnu5IA1YwqPrSBCZxZ//EAB4QAAIBAwUAAAAAAAAAAAAAAAIDBAABEhMUIiMy/9oACAEBAAEFApJ6YDJYt9ShzB1u4GZC3xM4O3JiX//EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiIx/9oACAEDAQE/AQKqOL//xAAXEQEAAwAAAAAAAAAAAAAAAAAQAjFB/9oACAECAQE/AdJWf//EAB0QAAEEAwEBAAAAAAAAAAAAAAEAAhEhEEFRAxP/2gAIAQEABj8CogE7OkGu9fo13dY6oAuozI5KcIFFf//EABsQAQADAQEBAQAAAAAAAAAAAAEAESExQWGB/9oACAEBAAE/IV0go4fUuXXwX9FRdnZEF4THRoEMWx77FSfyYe1NSoaVOM//2gAMAwEAAgADAAAAENQQ/v/EABYRAQEBAAAAAAAAAAAAAAAAAAEQMf/aAAgBAwEBPxA1M3n/xAAYEQEBAAMAAAAAAAAAAAAAAAABABARMf/aAAgBAgEBPxBUw42r/8QAHBABAQACAwEBAAAAAAAAAAAAAREAITFRYUGB/9oACAEBAAE/EPP3jAVR9gaO0yZtyEswQGrNOHWGkTpItJhhgmRRO/ZgdzdI7xOWryw0rIHbeVZgFon45//Z"},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg 48w,\n/static/8702446d6b785251d5977565e717b101/73f48/olivier-anguenot.jpg 96w","sizes":"48px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/a3542/olivier-anguenot.webp 48w,\n/static/8702446d6b785251d5977565e717b101/0f66d/olivier-anguenot.webp 96w","type":"image/webp","sizes":"48px"}]},"width":48,"height":48},"ImageSharp_regular":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYFBP/EABYBAQEBAAAAAAAAAAAAAAAAAAMCBP/aAAwDAQACEAMQAAABtJOlgc2i6Zii3oAheUIP/8QAHhAAAgEDBQAAAAAAAAAAAAAAAgMEAQUSABQiJDP/2gAIAQEAAQUCnMqpa5bFSa11cBzXJHsLbkL/ADuXCRuzEv/EABcRAQEBAQAAAAAAAAAAAAAAAAIQETH/2gAIAQMBAT8BJ07Byf/EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiEx/9oACAECAQE/ASbUtX//xAAfEAACAgIBBQAAAAAAAAAAAAABEQACAzFBEBMhIlH/2gAIAQEABj8C9SATyeJWmTN3aX+7HTTEAARQUZ3DGNpy4VfBn//EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQVFxgdH/2gAIAQEAAT8hyi+jX2ZZooUQs5K4mSbdBeCUEaBjpO4x+RHSephcZl3KVcUyP2f/2gAMAwEAAgADAAAAEOfng//EABcRAAMBAAAAAAAAAAAAAAAAAAEQMUH/2gAIAQMBAT8QAXSuv//EABgRAAMBAQAAAAAAAAAAAAAAAAABERAx/9oACAECAQE/EGKc5kP/xAAdEAEBAAMAAgMAAAAAAAAAAAABEQAhMUFRYaGx/9oACAEBAAE/EANSSJgqnmBo9pjwNyCUHB0mk5zArBQJUtFpMMHKxFH2n5j0myRreLplXr5mGnYC7YnsNaEJ2DP/2Q=="},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg 128w","sizes":"128px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/9e357/olivier-anguenot.webp 128w","type":"image/webp","sizes":"128px"}]},"width":150,"height":150}}},"body":"\nTo have good WebRTC conversations, you first have to offer the user the right devices to use.\n\nImagine you're on a video call with a friend and you can't hear him because the microphone isn't the right one. Or you can't see him because he's sharing a virtual camera... It's no fun, is it?\n\nTo avoid these situations, it's important to manage devices correctly in your WebRTC application. And that's not always easy, especially when you're connecting and disconnecting devices on the fly or when you're pairing a new device like AirPods.\n\nWhy isn't it easy? Because each browser implements device management differently, leading to inconsistencies and difficulties in device management between different browsers.\n\nWhat's worse is that this API was designed in 2013 and more than 10 years later, we're still having problems with it.\n\nIn this article, I'll explore how to manage devices in WebRTC applications.\n\n\n## Introduction\n\nManaging devices in a WebRTC application involves several key steps:\n\n1. **Authorisation** : The first step in device management is to request and obtain permission from the user to access their media devices (camera, microphone). This is usually done using the `navigator.mediaDevices.getUserMedia()` method, which asks the user for permission to access their camera and/or microphone.\n\n2. **Enumeration**: Once access has been granted, the next step is to enumerate the available media devices. This can be done using the `navigator.mediaDevices.enumerateDevices()` method. In return, you get a list of available devices, including their IDs, labels and types (i.e. `audioinput`, `audiooutput`, `videoinput`).\n\n3. **Selection**: Having listed the devices, the user should be able to select the desired device for their audio and video inputs. Again, this can be done using the `navigator.mediaDevices.getUserMedia()` method, but this time with constraints specifying the IDs of the desired devices.\n\n4. **Detection**: The final step is to detect changes in the available devices, for example when a new device is connected or an existing device is disconnected. This can be done by listening for the `devicechange` event on the navigator.mediaDevices object.\n\n\n## Permissions\n\n### No common rules?\n\nThis step is mandatory: The application asks the user for the permission to access the devices for the Website or for the application (SPA).\n\nWhy do you need this? Because you don't want an application to access your camera and microphone without your consent. It's a question of privacy. For the camera, it is easy to see if it being used, but for the microphone, it is not so easy. How to know if an application is listening to you if you don't pay attention to the browser toolbar or the system toolbar?\n\nRequesting the permission is done by calling the method `navigator.mediaDevices.getUserMedia()` with the type of media you want to get: audio, video or both. The point to understand is that if you don't request for a specific device, the browser will choose for you (Chrome/Safari) or allow you to select which one to use (Firefox).\n\nSo, the way each browser handles the permission is not exactly the same. What they all have in common is that authorization relates to a domain.\n\n- In Chrome, by default, you request authorization for all devices of the type you want. Not for a particular device. So once you have access to a camera, you don't need another permission to use another camera. Additionally, you can authorize for a single session or permanently. You can also block the permission.\n\n- In Safari, this is per domain too. But every time you reload the page, you have to ask for the permission again..\n\n- In Firefox, you always give the permission for a specific device. If you want to use another device, you have to ask for the permission again. However, Firefox has recently added the option to authorize all devices of the same type (i.e. all cameras or all microphones).\n\n> Depending on the choice of the user, the experience may be different when the user wants to switch to a different device.\n\n### System permissions\n\nPlease note that the operating system such as MacOS requires an extra permission (the first time you are using the browser) to give globally the permission to the browser to access the devices.\n\nNote that this permission only concerns browsers other than Safari...\n\nOnce the authorisation has been accepted, the system will no longer ask you for it.\n\nBut what happens if by mistake you refuse this permission?\n\nWhen `getUserMedia` is called, even if the user authorizes the permission, the application cannot access the device. The error received will be different:\n\n- In Firefox, it will generate a `DOMException: The object can not be found here`.\n\n- In Chrome, it will be the error `NotAllowedError: Permission denied by system`.\n\n> In Chrome, you can deduce that the permission has been refused by the system. In Firefox, it is not so clear.\n\n### Permissions API\n\nAt any time, you can query this permission thanks to the [**Permissions API**](https://www.w3.org/TR/permissions/).\n\nBe careful, Firefox is still not managing permissions for the `microphone` and the `camera` So this API is not working in all browsers.\n\nHere is an example in the latest Chrome Canary 129:\n\n```js\ntry {\n  const permission = await navigator.permissions.query({ name: 'camera' });\n  console.log(permission.state);\n  // granted, denied, prompt\n} catch(err) {\n  // Handle the error\n}\n```\n\n_Note_: At this time (last update from March'24), only the following permissions have been standardized: `geolocation`, `notifications`, `push` and `web-share`. Others are still in the draft.\n\n### Remove or reset permissions\n\nAt any time, a permission can be removed. Not by the application but by the user.\n\n- Going to the system settings (on MacOS) can remove globally the browser's authorization to access the devices for browsers other than Safari.\n\n- From the browser settings, you can remove or reset any permissions given for a specific domain.\n\nAs previously, if by mistake, the user declines the authorization, your application can detect it and propose to the user to ask for the permission again.\n\n- In Chrome, the application receives the error `DOMException: Permission denied`\n\n- In Firefox, the application receives the error `DOMException: The request is not allowed by the user agent or the platform in the current context`.\n\n- In Safari: this is the error `NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.`\n\n> Detecting this error can be useful to propose to the user a way to reset the permission.\n\n\n### To resume\n\nThe `getUserMedia` API is an \"all-in-one\" API meaning that in case of success, you get a stream (of type `RTCMediaStream`) containing the tracks (of type `RTCMediaStreamTrack`), you've asked (i.e. audio, video or both).\n\nSo, if you already ask with specific constraints, you don't need to do extra things. You can directly use the stream.\n\nIf you want more information on how to use this API, please refer to this article [GetUserMedia Constraints Explained](https://www.webrtc-developers.com/getusermedia-constraints-explained/). It is mainly around constraints, but it gives you a good overview of how to use this API.\n\nHere is a simple example of how to ask for the permission to access the camera and the microphone:\n\n```js\n  const constraints = {\n    audio: true,\n    video: true,\n  };\n\n  try {\n    const stream = await navigator.mediaDevices.getUserMedia(constraints);\n  } catch(err) {\n    // Handle the error\n  }\n```\n\n## Devices enumeration\n\nOnce the permission is granted, you can list the devices available on the system. This is done by calling the method `navigator.mediaDevices.enumerateDevices()`.\n\nThis method returns a promise that resolves with an array of `MediaDeviceInfo` objects. Each object represents a media input or output device such as a microphone, camera, or speaker. The `MediaDeviceInfo` object contains information about the device, including its `deviceId`, `groupId`, `kind` (i.e. `audioinput`, `audiooutput`, `videoinput`) and `label`.\n\nHere is the result of the enumeration after asking for the same basic constraints (e.i. audio and video) in the different browsers on my machine:\n\n| Browser | Total  |                      Audio Input                       | Audio Output                                           | Video Input                            |\n|---------|:------:|:------------------------------------------------------:|--------------------------------------------------------|----------------------------------------|\n| Chrome  | **24** | Default<br/>+3 physical devices<br/>+7 virtual devices | Default<br/>+ 5 physical devices<br/>5 virtual devices | 1 physical device<br/>1 virtual device |\n| Firefox | **19** |       +3 physical devices<br/>+7 virtual devices       | + 2 physical devices<br/>5 virtual devices             | 1 physical device<br/>1 virtual device |\n| Safari  | **12** |       +3 physical devices<br/>+7 virtual devices       | -                                                      | 1 physical device<br/>1 virtual device |\n\nThe main differences are:\n- Chrome adds the **default** devices (input and output) to the list of devices. In fact, default devices are existing devices with the id that have been replaced by `default`. If you don't ask for a specific device, Chrome will use this default device, whereas Firefox/Safari take the first one in the list.\n- Safari still doesn't support **output devices**\n- Firefox does not display the **built-in speakers**: The one integrated to my Mac Mini and those integrated to my 2 monitors (HDMI and DisplayPort).\n\n## Grouping devices together\n\nThere are devices capable of simultaneously managing audio and video or audio input and output. For example, a webcam with a built-in microphone or a microphone with built-in speakers such as the equipment used in a meeting room.\n\nIt is interesting in this case to group these devices to allow the user to select them as a single device which means that selecting one with automatically select the other device of the same group.\n\nThe association is possible thanks to the `groupId` attribute of the `MediaDeviceInfo` object. This attribute is a unique identifier for the group of devices to which the device belongs.\n\n> Two devices have the same group identifier if they belong to the same physical device; for example, a monitor with both a built-in camera and microphone [MDN](https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo/groupId).\n\nAs usual, behavior in browsers is different:\n- Firefox groups devices as well as all virtual devices\n- Chrome groups devices and not all virtual devices (e.g. ok for Teams audio devices but not for the Rode Connect virtual devices)\n- Safari doesn't care about grouping devices... (not yet?)\n\n## Input devices selection\n\nOnce you have listed the devices, you can allow the user to select the desired devices for audio and video input. This can be done by specifying the device IDs in the constraints object passed to the `getUserMedia()` method.\n\nThis article explains how to do that this article [GetUserMedia Constraints Explained](https://www.webrtc-developers.com/getusermedia-constraints-explained/)\n\nHere is an example of selecting a microphone\n\n```js\nconst constraints = {\n  audio: {\n    deviceId: {\n      exact: \"0e05387a88dec20949ff8d8d18ee288ed4d7271a8d4380b497feb1432300c4bd\",\n    },\n  },\n};\n\ntry {\n  const stream = await navigator.mediaDevices.getUserMedia(constraints);\n} catch(err) {\n  // Handle the error\n}\n```\n\n_Note_: Remember to catch the error in case the user denies the permission or the device is not available.\n\n## Output devices selection\n\nIn Firefox and Chrome, you can select the speaker by using the `setSinkId()` method on the `HTMLMediaElement` object. This method expects the `deviceId` of an `audioOutput` media device.\n\nHere is an example of how to use the `setSinkId()` method:\n\n```js\nconst audio = document.querySelector('#audio');\naudio.setSinkId(\"51D9CC25B5DFDD54160FC1E357577D50116FDA89\");\n```\n\nFirefox goes a step further by implementing the API `navigator.mediaDevices.selectAudioOutput`. This API allows the user to select the output device from a pop-up window displaying all the devices.\n\nI tested it on Firefox Nightly (130) and this API also offers the built-in speakers.\n\nPlease note that this API is not yet completely standardized and requires a gesture from the user to work (for example, by clicking on a button). This is to prevent an application from sending the media to an external speaker without your consent.\n\nThis specification is available here: [Audio Output Devices API](https://w3c.github.io/mediacapture-output/)\n\n## Devices Changed\n\nThe interesting part...\n\nFrom the specification:\n> The set of media devices, available to the User Agent, has changed. The current list of devices is available in the devices attribute\n\nCurrently, the browsers don't implement this event as defined in the specification.\n\nHere is what I observed:\n\n| Browser | Event fired when                                   | devices attribute |\n|---------|:---------------------------------------------------|:-----------------:|\n| Chrome  | The default device is changed at System level (OS) |        NO         |\n|         | A new device is paired (1x or 2x)                  |        NO         |\n|         | A device is removed (1x or 2x)                     |        NO         |\n| Firefox | A new device is paired (1x)                        |        NO         |\n|         | A device is removed (1x)                           |        NO         |\n| Safari  | The default device is changed at System level (OS) |        NO         |\n|         | A new device is paired (1x)                        |        NO         |\n|         | A device is removed (1x)                           |        NO         |\n\nThe main things to remember are:\n- Firefox seems not to fire events when the default device is changed at the system level.\n- Firefox fires events only when the browser is active. Else, the event is fired as soon as the browser gets the focus.\n- Chrome fires events for each type of device added or removed (i.e. `audioinput`, `audiooutput`, `videoinput`). For example, if you pair your AirPods, you will see two events: one for the input and one for the output.\n- None of the browsers fires events with the `devices` attribute as defined in the specification.\n\n### Firefox case\n\nAs Firefox is not firing events when the default device is changed at the system level (as least on MacOS), your application can be desynchronized mainly in terms of speakers used. This is the main issue I see with Firefox.\n\nThe way I decided to prevent this issue is to call `enumerateDevices` regularly and to compare with the current list of devices.\n\nBy using this way, I can detect when I plug or unplug a device and display a banner to let the user confirm to switch to the new device.\n\n### Chrome double event\n\nHere, the problem is different. So I choose to wait some milliseconds (i.e. up to 500ms) once receiving a `devicechange` event to not capture the second one. As there is no `devices` attribute, this second event is not helpful except that you know that they've been two changes.\n\nAfter this delay, I call `enumerateDevices` to get the list of devices and update the UI accordingly.\n\n```js\nnavigator.mediaDevices.addEventListener('devicechange', async () => {\n  if (!hasChanged) {\n    // Avoid to do something on the second event\n    hasChanged = true;\n    setTimeout(async () => {\n      hasChanged = false;\n      // do something once the 2 events have been fired\n    }, 500);\n  }\n});\n```\n\n### Managing AirPods\n\nWhen you open the case to take your AirPods, they're automatically paired with your Mac. All browsers detect the new devices and add them to the list of devices.\n\nWhat is interesting is that as long as the AirPods aren't in your ears, the device is only added to the list of devices.\n\nIf you put the AirPods in your ears, Chrome and Safari fire a new `devicechange` event. Why? Because the AirPods are now used as the default device for input and output.\n\nIf you call `enumerateDevices` again, you will see that in Chrome, the `default` device changed and in Safari, the AirPods are now the first `audioinput` device.\n\nSo, don't take for granted that `devicechange` means that at least a device is added or removed. No, it can also mean that the default device is changed. As when this is done manually from the macOS settings.\n\n## Alternatives\n\n### Input devices used\n\nAssuming you have a `MediaStream` stream, you can get the devices used from its tracks.\n\n```js\nconst devices = await navigator.mediaDevices.enumerateDevices();\n\n// Get the tracks\nconst tracks = stream.getTracks();\n\n// Get the deviceId associated to each track from the settings\nconst devicesId = tracks.map(track => track.getSettings().deviceId);\n\n// Compare this id to the list of devices your application knows to find the right ones\nconst devicesUsed = devices.filter(device => devicesId.includes(device.deviceId));\n\nconsole.log(devicesUsed);\n// [ { deviceId: \"51D9CC25B5DFDD54160FC1E357577D50116FDA89\", kind: \"audioinput\", label: \"Rode NT-Usb\", groupId:... }, { deviceId: \"E2BF4D17BF7BD448FE0CF9C1141924A9B4FC5237\", kind: \"videoinput\", label: \"StreamCam\", groupId: ... } ]\n```\n\n### Output devices used\n\nThe way I found to confirm which speaker is used is to use the `sinkId` property of the &lt;audio&gt; or &lt;video&gt; element.\n\nFirst, find this element in the DOM using a function such as `getElementsByTagName` and then if an **HTMLAudioElement**  or **HTMLVideoElement** exists, get the id of the device used from the `sinkId` property.\n\nIt should match with an `audioinput` device.\n\n> In some circumstances, this can be a way to confirm the devices used.\n\n## To conclude\n\nFrom what has been described here, the main points to consider are:\n\n- a) Detect any permissions denied to help the user as soon as possible to resolve this case: Use the `query` API or the `getUserMedia` API.\n\n- b) Show the current or default devices, the ones the user will use for his next call: Store the devices used previously and compare them with the current list of devices, detect if devices is still available of not.\n\n- b) Select the new device when the user plugs or pairs a new device, because most probably he wants to use it: rely on the `devicechange` event and on the `enumerateDevices` API.\n\n- c) Group devices when applicable: Use the `groupId` attribute and in case of a new device plugged or paired, switch to it globally (audio and video or input and output).\n\nIn all cases, **feedbacks are the key** to helping the user understand what's going on.\n\nWhat you don't want is the user having to reload the page to get the new devices available...\n\nDon't hesitate to share your views on this topic!\n","keywords":null,"tags":[{"id":"ed8e58df-33d1-54a6-9d36-4ec7f3f8fb05","name":"#getUserMedia","slug":"/tag/getusermedia/"},{"id":"c3022941-a3b9-53c3-b74f-3dedddbdf091","name":"#microphone","slug":"/tag/microphone/"},{"id":"93511dcd-50b3-5ad7-92e4-6abcc09eb0fb","name":"#camera","slug":"/tag/camera/"}],"thumbnail":{"__typename":"ImageSharp","ImageSharp_vertical":{"layout":"constrained","backgroundColor":"#080808","images":{"fallback":{"src":"/static/6592ede592afdc5a96c53b4cbb8f02ce/144fe/photo.jpg","srcSet":"/static/6592ede592afdc5a96c53b4cbb8f02ce/9d7b9/photo.jpg 190w,\n/static/6592ede592afdc5a96c53b4cbb8f02ce/144fe/photo.jpg 380w","sizes":"(min-width: 380px) 380px, 100vw"},"sources":[{"srcSet":"/static/6592ede592afdc5a96c53b4cbb8f02ce/228d6/photo.webp 190w,\n/static/6592ede592afdc5a96c53b4cbb8f02ce/6b99c/photo.webp 380w","type":"image/webp","sizes":"(min-width: 380px) 380px, 100vw"}]},"width":380,"height":290},"ImageSharp_hero":{"layout":"constrained","backgroundColor":"#080808","images":{"fallback":{"src":"/static/6592ede592afdc5a96c53b4cbb8f02ce/5e493/photo.jpg","srcSet":"/static/6592ede592afdc5a96c53b4cbb8f02ce/696c0/photo.jpg 800w,\n/static/6592ede592afdc5a96c53b4cbb8f02ce/5e493/photo.jpg 1600w","sizes":"(min-width: 1600px) 1600px, 100vw"},"sources":[{"srcSet":"/static/6592ede592afdc5a96c53b4cbb8f02ce/c9f06/photo.webp 800w,\n/static/6592ede592afdc5a96c53b4cbb8f02ce/f47df/photo.webp 1600w","type":"image/webp","sizes":"(min-width: 1600px) 1600px, 100vw"}]},"width":1600,"height":650}}},"tagCategoryPosts":{"nodes":[]},"tagPosts":{"nodes":[{"id":"789ad339-eaa0-539d-b557-ce0e76028261","title":"GetUserMedia Constraints explained","slug":"/getusermedia-constraints-explained/","link":null,"excerpt":"The getUserMedia API was the first API released when WebRTC landed in the browser: Here is the…","timeToRead":null,"featured":null,"thumbnailText":null,"date":"April 24, 2023","category":{"id":"c34c6d61-c795-5b85-b658-d6d481e7e379","name":"api","slug":"/category/api/","color":null,"icon":"/static/35c6c4f7d744541f08be2bbd2770c8db/api.svg"},"author":{"id":"a1ce6965-86d7-5de2-8e55-c593e5fcc1bb","name":"Olivier Anguenot","slug":"/author/olivier-anguenot/","title":"Your WebRTC copilot","description":"Technical leader at Alcatel-Lucent Enterprise. Father of 2. Working on WebRTC the week-end","skills":["WebRTC","Javascript"],"social":[{"name":"Github","url":"https://github.com/oanguenot"},{"name":"Twitter","url":"https://twitter.com/oanguenot"},{"name":"Linkedin","url":"https://www.linkedin.com/in/olivier-anguenot-99503a33/"}],"thumbnail":{"__typename":"ImageSharp","ImageSharp_small":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAMC/9oADAMBAAIQAxAAAAGnnu5IA1YwqPrSBCZxZ//EAB4QAAIBAwUAAAAAAAAAAAAAAAIDBAABEhMUIiMy/9oACAEBAAEFApJ6YDJYt9ShzB1u4GZC3xM4O3JiX//EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiIx/9oACAEDAQE/AQKqOL//xAAXEQEAAwAAAAAAAAAAAAAAAAAQAjFB/9oACAECAQE/AdJWf//EAB0QAAEEAwEBAAAAAAAAAAAAAAEAAhEhEEFRAxP/2gAIAQEABj8CogE7OkGu9fo13dY6oAuozI5KcIFFf//EABsQAQADAQEBAQAAAAAAAAAAAAEAESExQWGB/9oACAEBAAE/IV0go4fUuXXwX9FRdnZEF4THRoEMWx77FSfyYe1NSoaVOM//2gAMAwEAAgADAAAAENQQ/v/EABYRAQEBAAAAAAAAAAAAAAAAAAEQMf/aAAgBAwEBPxA1M3n/xAAYEQEBAAMAAAAAAAAAAAAAAAABABARMf/aAAgBAgEBPxBUw42r/8QAHBABAQACAwEBAAAAAAAAAAAAAREAITFRYUGB/9oACAEBAAE/EPP3jAVR9gaO0yZtyEswQGrNOHWGkTpItJhhgmRRO/ZgdzdI7xOWryw0rIHbeVZgFon45//Z"},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg 48w,\n/static/8702446d6b785251d5977565e717b101/73f48/olivier-anguenot.jpg 96w","sizes":"48px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/a3542/olivier-anguenot.webp 48w,\n/static/8702446d6b785251d5977565e717b101/0f66d/olivier-anguenot.webp 96w","type":"image/webp","sizes":"48px"}]},"width":48,"height":48},"ImageSharp_regular":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYFBP/EABYBAQEBAAAAAAAAAAAAAAAAAAMCBP/aAAwDAQACEAMQAAABtJOlgc2i6Zii3oAheUIP/8QAHhAAAgEDBQAAAAAAAAAAAAAAAgMEAQUSABQiJDP/2gAIAQEAAQUCnMqpa5bFSa11cBzXJHsLbkL/ADuXCRuzEv/EABcRAQEBAQAAAAAAAAAAAAAAAAIQETH/2gAIAQMBAT8BJ07Byf/EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiEx/9oACAECAQE/ASbUtX//xAAfEAACAgIBBQAAAAAAAAAAAAABEQACAzFBEBMhIlH/2gAIAQEABj8C9SATyeJWmTN3aX+7HTTEAARQUZ3DGNpy4VfBn//EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQVFxgdH/2gAIAQEAAT8hyi+jX2ZZooUQs5K4mSbdBeCUEaBjpO4x+RHSephcZl3KVcUyP2f/2gAMAwEAAgADAAAAEOfng//EABcRAAMBAAAAAAAAAAAAAAAAAAEQMUH/2gAIAQMBAT8QAXSuv//EABgRAAMBAQAAAAAAAAAAAAAAAAABERAx/9oACAECAQE/EGKc5kP/xAAdEAEBAAMAAgMAAAAAAAAAAAABEQAhMUFRYaGx/9oACAEBAAE/EANSSJgqnmBo9pjwNyCUHB0mk5zArBQJUtFpMMHKxFH2n5j0myRreLplXr5mGnYC7YnsNaEJ2DP/2Q=="},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg 128w","sizes":"128px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/9e357/olivier-anguenot.webp 128w","type":"image/webp","sizes":"128px"}]},"width":150,"height":150}}},"thumbnail":{"__typename":"ImageSharp","ImageSharp_vertical":{"layout":"constrained","backgroundColor":"#d8d8e8","images":{"fallback":{"src":"/static/5da4c282d20d80ddc7cc179bde1cb25a/144fe/photo.jpg","srcSet":"/static/5da4c282d20d80ddc7cc179bde1cb25a/9d7b9/photo.jpg 190w,\n/static/5da4c282d20d80ddc7cc179bde1cb25a/144fe/photo.jpg 380w","sizes":"(min-width: 380px) 380px, 100vw"},"sources":[{"srcSet":"/static/5da4c282d20d80ddc7cc179bde1cb25a/228d6/photo.webp 190w,\n/static/5da4c282d20d80ddc7cc179bde1cb25a/6b99c/photo.webp 380w","type":"image/webp","sizes":"(min-width: 380px) 380px, 100vw"}]},"width":380,"height":290},"ImageSharp_hero":{"layout":"constrained","backgroundColor":"#d8d8e8","images":{"fallback":{"src":"/static/5da4c282d20d80ddc7cc179bde1cb25a/5e493/photo.jpg","srcSet":"/static/5da4c282d20d80ddc7cc179bde1cb25a/696c0/photo.jpg 800w,\n/static/5da4c282d20d80ddc7cc179bde1cb25a/5e493/photo.jpg 1600w","sizes":"(min-width: 1600px) 1600px, 100vw"},"sources":[{"srcSet":"/static/5da4c282d20d80ddc7cc179bde1cb25a/c9f06/photo.webp 800w,\n/static/5da4c282d20d80ddc7cc179bde1cb25a/f47df/photo.webp 1600w","type":"image/webp","sizes":"(min-width: 1600px) 1600px, 100vw"}]},"width":1600,"height":650}}}]},"categoryPosts":{"nodes":[{"id":"54c224aa-adb8-5fe4-a403-3b6d8f3033e9","title":"Nailing the WebRTC Call Start","slug":"/nailing-the-webrtc-call-start/","link":null,"excerpt":"Starting a WebRTC call often feels like magic. You click a button, and suddenly you’re seeing and…","timeToRead":null,"featured":null,"thumbnailText":null,"date":"February 28, 2026","category":{"id":"0fde40c1-42e7-595e-8ce3-5969b3416bbd","name":"dev","slug":"/category/dev/","color":null,"icon":"/static/93c9c75517e1a6e95deaecabf3d1d050/dev.svg"},"author":{"id":"a1ce6965-86d7-5de2-8e55-c593e5fcc1bb","name":"Olivier Anguenot","slug":"/author/olivier-anguenot/","title":"Your WebRTC copilot","description":"Technical leader at Alcatel-Lucent Enterprise. Father of 2. Working on WebRTC the week-end","skills":["WebRTC","Javascript"],"social":[{"name":"Github","url":"https://github.com/oanguenot"},{"name":"Twitter","url":"https://twitter.com/oanguenot"},{"name":"Linkedin","url":"https://www.linkedin.com/in/olivier-anguenot-99503a33/"}],"thumbnail":{"__typename":"ImageSharp","ImageSharp_small":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAMC/9oADAMBAAIQAxAAAAGnnu5IA1YwqPrSBCZxZ//EAB4QAAIBAwUAAAAAAAAAAAAAAAIDBAABEhMUIiMy/9oACAEBAAEFApJ6YDJYt9ShzB1u4GZC3xM4O3JiX//EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiIx/9oACAEDAQE/AQKqOL//xAAXEQEAAwAAAAAAAAAAAAAAAAAQAjFB/9oACAECAQE/AdJWf//EAB0QAAEEAwEBAAAAAAAAAAAAAAEAAhEhEEFRAxP/2gAIAQEABj8CogE7OkGu9fo13dY6oAuozI5KcIFFf//EABsQAQADAQEBAQAAAAAAAAAAAAEAESExQWGB/9oACAEBAAE/IV0go4fUuXXwX9FRdnZEF4THRoEMWx77FSfyYe1NSoaVOM//2gAMAwEAAgADAAAAENQQ/v/EABYRAQEBAAAAAAAAAAAAAAAAAAEQMf/aAAgBAwEBPxA1M3n/xAAYEQEBAAMAAAAAAAAAAAAAAAABABARMf/aAAgBAgEBPxBUw42r/8QAHBABAQACAwEBAAAAAAAAAAAAAREAITFRYUGB/9oACAEBAAE/EPP3jAVR9gaO0yZtyEswQGrNOHWGkTpItJhhgmRRO/ZgdzdI7xOWryw0rIHbeVZgFon45//Z"},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg 48w,\n/static/8702446d6b785251d5977565e717b101/73f48/olivier-anguenot.jpg 96w","sizes":"48px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/a3542/olivier-anguenot.webp 48w,\n/static/8702446d6b785251d5977565e717b101/0f66d/olivier-anguenot.webp 96w","type":"image/webp","sizes":"48px"}]},"width":48,"height":48},"ImageSharp_regular":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYFBP/EABYBAQEBAAAAAAAAAAAAAAAAAAMCBP/aAAwDAQACEAMQAAABtJOlgc2i6Zii3oAheUIP/8QAHhAAAgEDBQAAAAAAAAAAAAAAAgMEAQUSABQiJDP/2gAIAQEAAQUCnMqpa5bFSa11cBzXJHsLbkL/ADuXCRuzEv/EABcRAQEBAQAAAAAAAAAAAAAAAAIQETH/2gAIAQMBAT8BJ07Byf/EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiEx/9oACAECAQE/ASbUtX//xAAfEAACAgIBBQAAAAAAAAAAAAABEQACAzFBEBMhIlH/2gAIAQEABj8C9SATyeJWmTN3aX+7HTTEAARQUZ3DGNpy4VfBn//EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQVFxgdH/2gAIAQEAAT8hyi+jX2ZZooUQs5K4mSbdBeCUEaBjpO4x+RHSephcZl3KVcUyP2f/2gAMAwEAAgADAAAAEOfng//EABcRAAMBAAAAAAAAAAAAAAAAAAEQMUH/2gAIAQMBAT8QAXSuv//EABgRAAMBAQAAAAAAAAAAAAAAAAABERAx/9oACAECAQE/EGKc5kP/xAAdEAEBAAMAAgMAAAAAAAAAAAABEQAhMUFRYaGx/9oACAEBAAE/EANSSJgqnmBo9pjwNyCUHB0mk5zArBQJUtFpMMHKxFH2n5j0myRreLplXr5mGnYC7YnsNaEJ2DP/2Q=="},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg 128w","sizes":"128px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/9e357/olivier-anguenot.webp 128w","type":"image/webp","sizes":"128px"}]},"width":150,"height":150}}},"thumbnail":{"__typename":"ImageSharp","ImageSharp_vertical":{"layout":"constrained","backgroundColor":"#f8f8f8","images":{"fallback":{"src":"/static/4548f4cf8fc5ccdb400929098ac40235/144fe/photo.jpg","srcSet":"/static/4548f4cf8fc5ccdb400929098ac40235/9d7b9/photo.jpg 190w,\n/static/4548f4cf8fc5ccdb400929098ac40235/144fe/photo.jpg 380w","sizes":"(min-width: 380px) 380px, 100vw"},"sources":[{"srcSet":"/static/4548f4cf8fc5ccdb400929098ac40235/228d6/photo.webp 190w,\n/static/4548f4cf8fc5ccdb400929098ac40235/6b99c/photo.webp 380w","type":"image/webp","sizes":"(min-width: 380px) 380px, 100vw"}]},"width":380,"height":290},"ImageSharp_hero":{"layout":"constrained","backgroundColor":"#f8f8f8","images":{"fallback":{"src":"/static/4548f4cf8fc5ccdb400929098ac40235/5e493/photo.jpg","srcSet":"/static/4548f4cf8fc5ccdb400929098ac40235/696c0/photo.jpg 800w,\n/static/4548f4cf8fc5ccdb400929098ac40235/5e493/photo.jpg 1600w","sizes":"(min-width: 1600px) 1600px, 100vw"},"sources":[{"srcSet":"/static/4548f4cf8fc5ccdb400929098ac40235/c9f06/photo.webp 800w,\n/static/4548f4cf8fc5ccdb400929098ac40235/f47df/photo.webp 1600w","type":"image/webp","sizes":"(min-width: 1600px) 1600px, 100vw"}]},"width":1600,"height":650}}},{"id":"ccb10ab4-98e6-56d9-b149-180cf3da571c","title":"Setup and troubleshoot your rtcStats-server","slug":"/setup-and-troubleshoot-your-rtcstats-server/","link":null,"excerpt":"If you spend any time in the WebRTC space, chances are you’ve heard of rtcStats.com, the solution we…","timeToRead":null,"featured":null,"thumbnailText":null,"date":"December 09, 2025","category":{"id":"0fde40c1-42e7-595e-8ce3-5969b3416bbd","name":"dev","slug":"/category/dev/","color":null,"icon":"/static/93c9c75517e1a6e95deaecabf3d1d050/dev.svg"},"author":{"id":"a1ce6965-86d7-5de2-8e55-c593e5fcc1bb","name":"Olivier Anguenot","slug":"/author/olivier-anguenot/","title":"Your WebRTC copilot","description":"Technical leader at Alcatel-Lucent Enterprise. Father of 2. Working on WebRTC the week-end","skills":["WebRTC","Javascript"],"social":[{"name":"Github","url":"https://github.com/oanguenot"},{"name":"Twitter","url":"https://twitter.com/oanguenot"},{"name":"Linkedin","url":"https://www.linkedin.com/in/olivier-anguenot-99503a33/"}],"thumbnail":{"__typename":"ImageSharp","ImageSharp_small":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAMC/9oADAMBAAIQAxAAAAGnnu5IA1YwqPrSBCZxZ//EAB4QAAIBAwUAAAAAAAAAAAAAAAIDBAABEhMUIiMy/9oACAEBAAEFApJ6YDJYt9ShzB1u4GZC3xM4O3JiX//EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiIx/9oACAEDAQE/AQKqOL//xAAXEQEAAwAAAAAAAAAAAAAAAAAQAjFB/9oACAECAQE/AdJWf//EAB0QAAEEAwEBAAAAAAAAAAAAAAEAAhEhEEFRAxP/2gAIAQEABj8CogE7OkGu9fo13dY6oAuozI5KcIFFf//EABsQAQADAQEBAQAAAAAAAAAAAAEAESExQWGB/9oACAEBAAE/IV0go4fUuXXwX9FRdnZEF4THRoEMWx77FSfyYe1NSoaVOM//2gAMAwEAAgADAAAAENQQ/v/EABYRAQEBAAAAAAAAAAAAAAAAAAEQMf/aAAgBAwEBPxA1M3n/xAAYEQEBAAMAAAAAAAAAAAAAAAABABARMf/aAAgBAgEBPxBUw42r/8QAHBABAQACAwEBAAAAAAAAAAAAAREAITFRYUGB/9oACAEBAAE/EPP3jAVR9gaO0yZtyEswQGrNOHWGkTpItJhhgmRRO/ZgdzdI7xOWryw0rIHbeVZgFon45//Z"},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg 48w,\n/static/8702446d6b785251d5977565e717b101/73f48/olivier-anguenot.jpg 96w","sizes":"48px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/a3542/olivier-anguenot.webp 48w,\n/static/8702446d6b785251d5977565e717b101/0f66d/olivier-anguenot.webp 96w","type":"image/webp","sizes":"48px"}]},"width":48,"height":48},"ImageSharp_regular":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYFBP/EABYBAQEBAAAAAAAAAAAAAAAAAAMCBP/aAAwDAQACEAMQAAABtJOlgc2i6Zii3oAheUIP/8QAHhAAAgEDBQAAAAAAAAAAAAAAAgMEAQUSABQiJDP/2gAIAQEAAQUCnMqpa5bFSa11cBzXJHsLbkL/ADuXCRuzEv/EABcRAQEBAQAAAAAAAAAAAAAAAAIQETH/2gAIAQMBAT8BJ07Byf/EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiEx/9oACAECAQE/ASbUtX//xAAfEAACAgIBBQAAAAAAAAAAAAABEQACAzFBEBMhIlH/2gAIAQEABj8C9SATyeJWmTN3aX+7HTTEAARQUZ3DGNpy4VfBn//EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQVFxgdH/2gAIAQEAAT8hyi+jX2ZZooUQs5K4mSbdBeCUEaBjpO4x+RHSephcZl3KVcUyP2f/2gAMAwEAAgADAAAAEOfng//EABcRAAMBAAAAAAAAAAAAAAAAAAEQMUH/2gAIAQMBAT8QAXSuv//EABgRAAMBAQAAAAAAAAAAAAAAAAABERAx/9oACAECAQE/EGKc5kP/xAAdEAEBAAMAAgMAAAAAAAAAAAABEQAhMUFRYaGx/9oACAEBAAE/EANSSJgqnmBo9pjwNyCUHB0mk5zArBQJUtFpMMHKxFH2n5j0myRreLplXr5mGnYC7YnsNaEJ2DP/2Q=="},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg 128w","sizes":"128px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/9e357/olivier-anguenot.webp 128w","type":"image/webp","sizes":"128px"}]},"width":150,"height":150}}},"thumbnail":{"__typename":"ImageSharp","ImageSharp_vertical":{"layout":"constrained","backgroundColor":"#f8e8d8","images":{"fallback":{"src":"/static/48b533642df0d1c7a32481da4cef220b/144fe/photo.jpg","srcSet":"/static/48b533642df0d1c7a32481da4cef220b/9d7b9/photo.jpg 190w,\n/static/48b533642df0d1c7a32481da4cef220b/144fe/photo.jpg 380w","sizes":"(min-width: 380px) 380px, 100vw"},"sources":[{"srcSet":"/static/48b533642df0d1c7a32481da4cef220b/228d6/photo.webp 190w,\n/static/48b533642df0d1c7a32481da4cef220b/6b99c/photo.webp 380w","type":"image/webp","sizes":"(min-width: 380px) 380px, 100vw"}]},"width":380,"height":290},"ImageSharp_hero":{"layout":"constrained","backgroundColor":"#f8e8d8","images":{"fallback":{"src":"/static/48b533642df0d1c7a32481da4cef220b/5e493/photo.jpg","srcSet":"/static/48b533642df0d1c7a32481da4cef220b/696c0/photo.jpg 800w,\n/static/48b533642df0d1c7a32481da4cef220b/5e493/photo.jpg 1600w","sizes":"(min-width: 1600px) 1600px, 100vw"},"sources":[{"srcSet":"/static/48b533642df0d1c7a32481da4cef220b/c9f06/photo.webp 800w,\n/static/48b533642df0d1c7a32481da4cef220b/f47df/photo.webp 1600w","type":"image/webp","sizes":"(min-width: 1600px) 1600px, 100vw"}]},"width":1600,"height":650}}},{"id":"d9148f0e-bcdc-5b37-b8f8-5587aa35a80c","title":"Anatomy of a WebRTC Connection","slug":"/anatomy-of-a-webrtc-connection/","link":null,"excerpt":"WebRTC provides powerful capabilities for direct peer-to-peer audio, video, and data exchange within…","timeToRead":null,"featured":null,"thumbnailText":null,"date":"June 30, 2025","category":{"id":"0fde40c1-42e7-595e-8ce3-5969b3416bbd","name":"dev","slug":"/category/dev/","color":null,"icon":"/static/93c9c75517e1a6e95deaecabf3d1d050/dev.svg"},"author":{"id":"a1ce6965-86d7-5de2-8e55-c593e5fcc1bb","name":"Olivier Anguenot","slug":"/author/olivier-anguenot/","title":"Your WebRTC copilot","description":"Technical leader at Alcatel-Lucent Enterprise. Father of 2. Working on WebRTC the week-end","skills":["WebRTC","Javascript"],"social":[{"name":"Github","url":"https://github.com/oanguenot"},{"name":"Twitter","url":"https://twitter.com/oanguenot"},{"name":"Linkedin","url":"https://www.linkedin.com/in/olivier-anguenot-99503a33/"}],"thumbnail":{"__typename":"ImageSharp","ImageSharp_small":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAMC/9oADAMBAAIQAxAAAAGnnu5IA1YwqPrSBCZxZ//EAB4QAAIBAwUAAAAAAAAAAAAAAAIDBAABEhMUIiMy/9oACAEBAAEFApJ6YDJYt9ShzB1u4GZC3xM4O3JiX//EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiIx/9oACAEDAQE/AQKqOL//xAAXEQEAAwAAAAAAAAAAAAAAAAAQAjFB/9oACAECAQE/AdJWf//EAB0QAAEEAwEBAAAAAAAAAAAAAAEAAhEhEEFRAxP/2gAIAQEABj8CogE7OkGu9fo13dY6oAuozI5KcIFFf//EABsQAQADAQEBAQAAAAAAAAAAAAEAESExQWGB/9oACAEBAAE/IV0go4fUuXXwX9FRdnZEF4THRoEMWx77FSfyYe1NSoaVOM//2gAMAwEAAgADAAAAENQQ/v/EABYRAQEBAAAAAAAAAAAAAAAAAAEQMf/aAAgBAwEBPxA1M3n/xAAYEQEBAAMAAAAAAAAAAAAAAAABABARMf/aAAgBAgEBPxBUw42r/8QAHBABAQACAwEBAAAAAAAAAAAAAREAITFRYUGB/9oACAEBAAE/EPP3jAVR9gaO0yZtyEswQGrNOHWGkTpItJhhgmRRO/ZgdzdI7xOWryw0rIHbeVZgFon45//Z"},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg 48w,\n/static/8702446d6b785251d5977565e717b101/73f48/olivier-anguenot.jpg 96w","sizes":"48px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/a3542/olivier-anguenot.webp 48w,\n/static/8702446d6b785251d5977565e717b101/0f66d/olivier-anguenot.webp 96w","type":"image/webp","sizes":"48px"}]},"width":48,"height":48},"ImageSharp_regular":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYFBP/EABYBAQEBAAAAAAAAAAAAAAAAAAMCBP/aAAwDAQACEAMQAAABtJOlgc2i6Zii3oAheUIP/8QAHhAAAgEDBQAAAAAAAAAAAAAAAgMEAQUSABQiJDP/2gAIAQEAAQUCnMqpa5bFSa11cBzXJHsLbkL/ADuXCRuzEv/EABcRAQEBAQAAAAAAAAAAAAAAAAIQETH/2gAIAQMBAT8BJ07Byf/EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiEx/9oACAECAQE/ASbUtX//xAAfEAACAgIBBQAAAAAAAAAAAAABEQACAzFBEBMhIlH/2gAIAQEABj8C9SATyeJWmTN3aX+7HTTEAARQUZ3DGNpy4VfBn//EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQVFxgdH/2gAIAQEAAT8hyi+jX2ZZooUQs5K4mSbdBeCUEaBjpO4x+RHSephcZl3KVcUyP2f/2gAMAwEAAgADAAAAEOfng//EABcRAAMBAAAAAAAAAAAAAAAAAAEQMUH/2gAIAQMBAT8QAXSuv//EABgRAAMBAQAAAAAAAAAAAAAAAAABERAx/9oACAECAQE/EGKc5kP/xAAdEAEBAAMAAgMAAAAAAAAAAAABEQAhMUFRYaGx/9oACAEBAAE/EANSSJgqnmBo9pjwNyCUHB0mk5zArBQJUtFpMMHKxFH2n5j0myRreLplXr5mGnYC7YnsNaEJ2DP/2Q=="},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg 128w","sizes":"128px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/9e357/olivier-anguenot.webp 128w","type":"image/webp","sizes":"128px"}]},"width":150,"height":150}}},"thumbnail":{"__typename":"ImageSharp","ImageSharp_vertical":{"layout":"constrained","backgroundColor":"#885828","images":{"fallback":{"src":"/static/c253db2e9d1115c92c10268784d54fea/144fe/photo.jpg","srcSet":"/static/c253db2e9d1115c92c10268784d54fea/9d7b9/photo.jpg 190w,\n/static/c253db2e9d1115c92c10268784d54fea/144fe/photo.jpg 380w","sizes":"(min-width: 380px) 380px, 100vw"},"sources":[{"srcSet":"/static/c253db2e9d1115c92c10268784d54fea/228d6/photo.webp 190w,\n/static/c253db2e9d1115c92c10268784d54fea/6b99c/photo.webp 380w","type":"image/webp","sizes":"(min-width: 380px) 380px, 100vw"}]},"width":380,"height":290},"ImageSharp_hero":{"layout":"constrained","backgroundColor":"#885828","images":{"fallback":{"src":"/static/c253db2e9d1115c92c10268784d54fea/5e493/photo.jpg","srcSet":"/static/c253db2e9d1115c92c10268784d54fea/696c0/photo.jpg 800w,\n/static/c253db2e9d1115c92c10268784d54fea/5e493/photo.jpg 1600w","sizes":"(min-width: 1600px) 1600px, 100vw"},"sources":[{"srcSet":"/static/c253db2e9d1115c92c10268784d54fea/c9f06/photo.webp 800w,\n/static/c253db2e9d1115c92c10268784d54fea/f47df/photo.webp 1600w","type":"image/webp","sizes":"(min-width: 1600px) 1600px, 100vw"}]},"width":1600,"height":650}}},{"id":"0d39fb21-e1c1-5466-972f-3346cad6f5e7","title":"Comparison of WebRTC Codecs for Video and Screen Sharing","slug":"/comparison-of-webrtc-codecs-for-video-and-screen-sharing/","link":null,"excerpt":"This article marks my first in-depth exploration of video codec performance, driven by significant…","timeToRead":null,"featured":null,"thumbnailText":null,"date":"April 16, 2025","category":{"id":"0fde40c1-42e7-595e-8ce3-5969b3416bbd","name":"dev","slug":"/category/dev/","color":null,"icon":"/static/93c9c75517e1a6e95deaecabf3d1d050/dev.svg"},"author":{"id":"a1ce6965-86d7-5de2-8e55-c593e5fcc1bb","name":"Olivier Anguenot","slug":"/author/olivier-anguenot/","title":"Your WebRTC copilot","description":"Technical leader at Alcatel-Lucent Enterprise. Father of 2. Working on WebRTC the week-end","skills":["WebRTC","Javascript"],"social":[{"name":"Github","url":"https://github.com/oanguenot"},{"name":"Twitter","url":"https://twitter.com/oanguenot"},{"name":"Linkedin","url":"https://www.linkedin.com/in/olivier-anguenot-99503a33/"}],"thumbnail":{"__typename":"ImageSharp","ImageSharp_small":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAMC/9oADAMBAAIQAxAAAAGnnu5IA1YwqPrSBCZxZ//EAB4QAAIBAwUAAAAAAAAAAAAAAAIDBAABEhMUIiMy/9oACAEBAAEFApJ6YDJYt9ShzB1u4GZC3xM4O3JiX//EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiIx/9oACAEDAQE/AQKqOL//xAAXEQEAAwAAAAAAAAAAAAAAAAAQAjFB/9oACAECAQE/AdJWf//EAB0QAAEEAwEBAAAAAAAAAAAAAAEAAhEhEEFRAxP/2gAIAQEABj8CogE7OkGu9fo13dY6oAuozI5KcIFFf//EABsQAQADAQEBAQAAAAAAAAAAAAEAESExQWGB/9oACAEBAAE/IV0go4fUuXXwX9FRdnZEF4THRoEMWx77FSfyYe1NSoaVOM//2gAMAwEAAgADAAAAENQQ/v/EABYRAQEBAAAAAAAAAAAAAAAAAAEQMf/aAAgBAwEBPxA1M3n/xAAYEQEBAAMAAAAAAAAAAAAAAAABABARMf/aAAgBAgEBPxBUw42r/8QAHBABAQACAwEBAAAAAAAAAAAAAREAITFRYUGB/9oACAEBAAE/EPP3jAVR9gaO0yZtyEswQGrNOHWGkTpItJhhgmRRO/ZgdzdI7xOWryw0rIHbeVZgFon45//Z"},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg 48w,\n/static/8702446d6b785251d5977565e717b101/73f48/olivier-anguenot.jpg 96w","sizes":"48px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/a3542/olivier-anguenot.webp 48w,\n/static/8702446d6b785251d5977565e717b101/0f66d/olivier-anguenot.webp 96w","type":"image/webp","sizes":"48px"}]},"width":48,"height":48},"ImageSharp_regular":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYFBP/EABYBAQEBAAAAAAAAAAAAAAAAAAMCBP/aAAwDAQACEAMQAAABtJOlgc2i6Zii3oAheUIP/8QAHhAAAgEDBQAAAAAAAAAAAAAAAgMEAQUSABQiJDP/2gAIAQEAAQUCnMqpa5bFSa11cBzXJHsLbkL/ADuXCRuzEv/EABcRAQEBAQAAAAAAAAAAAAAAAAIQETH/2gAIAQMBAT8BJ07Byf/EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiEx/9oACAECAQE/ASbUtX//xAAfEAACAgIBBQAAAAAAAAAAAAABEQACAzFBEBMhIlH/2gAIAQEABj8C9SATyeJWmTN3aX+7HTTEAARQUZ3DGNpy4VfBn//EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQVFxgdH/2gAIAQEAAT8hyi+jX2ZZooUQs5K4mSbdBeCUEaBjpO4x+RHSephcZl3KVcUyP2f/2gAMAwEAAgADAAAAEOfng//EABcRAAMBAAAAAAAAAAAAAAAAAAEQMUH/2gAIAQMBAT8QAXSuv//EABgRAAMBAQAAAAAAAAAAAAAAAAABERAx/9oACAECAQE/EGKc5kP/xAAdEAEBAAMAAgMAAAAAAAAAAAABEQAhMUFRYaGx/9oACAEBAAE/EANSSJgqnmBo9pjwNyCUHB0mk5zArBQJUtFpMMHKxFH2n5j0myRreLplXr5mGnYC7YnsNaEJ2DP/2Q=="},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg 128w","sizes":"128px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/9e357/olivier-anguenot.webp 128w","type":"image/webp","sizes":"128px"}]},"width":150,"height":150}}},"thumbnail":{"__typename":"ImageSharp","ImageSharp_vertical":{"layout":"constrained","backgroundColor":"#080808","images":{"fallback":{"src":"/static/b772911bb90907a4d83f5f1ed378cc85/144fe/photo.jpg","srcSet":"/static/b772911bb90907a4d83f5f1ed378cc85/9d7b9/photo.jpg 190w,\n/static/b772911bb90907a4d83f5f1ed378cc85/144fe/photo.jpg 380w","sizes":"(min-width: 380px) 380px, 100vw"},"sources":[{"srcSet":"/static/b772911bb90907a4d83f5f1ed378cc85/228d6/photo.webp 190w,\n/static/b772911bb90907a4d83f5f1ed378cc85/6b99c/photo.webp 380w","type":"image/webp","sizes":"(min-width: 380px) 380px, 100vw"}]},"width":380,"height":290},"ImageSharp_hero":{"layout":"constrained","backgroundColor":"#080808","images":{"fallback":{"src":"/static/b772911bb90907a4d83f5f1ed378cc85/5e493/photo.jpg","srcSet":"/static/b772911bb90907a4d83f5f1ed378cc85/696c0/photo.jpg 800w,\n/static/b772911bb90907a4d83f5f1ed378cc85/5e493/photo.jpg 1600w","sizes":"(min-width: 1600px) 1600px, 100vw"},"sources":[{"srcSet":"/static/b772911bb90907a4d83f5f1ed378cc85/c9f06/photo.webp 800w,\n/static/b772911bb90907a4d83f5f1ed378cc85/f47df/photo.webp 1600w","type":"image/webp","sizes":"(min-width: 1600px) 1600px, 100vw"}]},"width":1600,"height":650}}},{"id":"091b0bc9-f682-54a0-b8f6-103866f257e1","title":"How to calculate MOS?","slug":"/how-to-calculate-mos/","link":null,"excerpt":"In WebRTC (Web Real-Time Communication) development, understanding the quality of audio and video…","timeToRead":null,"featured":null,"thumbnailText":null,"date":"November 13, 2024","category":{"id":"0fde40c1-42e7-595e-8ce3-5969b3416bbd","name":"dev","slug":"/category/dev/","color":null,"icon":"/static/93c9c75517e1a6e95deaecabf3d1d050/dev.svg"},"author":{"id":"a1ce6965-86d7-5de2-8e55-c593e5fcc1bb","name":"Olivier Anguenot","slug":"/author/olivier-anguenot/","title":"Your WebRTC copilot","description":"Technical leader at Alcatel-Lucent Enterprise. Father of 2. Working on WebRTC the week-end","skills":["WebRTC","Javascript"],"social":[{"name":"Github","url":"https://github.com/oanguenot"},{"name":"Twitter","url":"https://twitter.com/oanguenot"},{"name":"Linkedin","url":"https://www.linkedin.com/in/olivier-anguenot-99503a33/"}],"thumbnail":{"__typename":"ImageSharp","ImageSharp_small":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAMC/9oADAMBAAIQAxAAAAGnnu5IA1YwqPrSBCZxZ//EAB4QAAIBAwUAAAAAAAAAAAAAAAIDBAABEhMUIiMy/9oACAEBAAEFApJ6YDJYt9ShzB1u4GZC3xM4O3JiX//EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiIx/9oACAEDAQE/AQKqOL//xAAXEQEAAwAAAAAAAAAAAAAAAAAQAjFB/9oACAECAQE/AdJWf//EAB0QAAEEAwEBAAAAAAAAAAAAAAEAAhEhEEFRAxP/2gAIAQEABj8CogE7OkGu9fo13dY6oAuozI5KcIFFf//EABsQAQADAQEBAQAAAAAAAAAAAAEAESExQWGB/9oACAEBAAE/IV0go4fUuXXwX9FRdnZEF4THRoEMWx77FSfyYe1NSoaVOM//2gAMAwEAAgADAAAAENQQ/v/EABYRAQEBAAAAAAAAAAAAAAAAAAEQMf/aAAgBAwEBPxA1M3n/xAAYEQEBAAMAAAAAAAAAAAAAAAABABARMf/aAAgBAgEBPxBUw42r/8QAHBABAQACAwEBAAAAAAAAAAAAAREAITFRYUGB/9oACAEBAAE/EPP3jAVR9gaO0yZtyEswQGrNOHWGkTpItJhhgmRRO/ZgdzdI7xOWryw0rIHbeVZgFon45//Z"},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg 48w,\n/static/8702446d6b785251d5977565e717b101/73f48/olivier-anguenot.jpg 96w","sizes":"48px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/a3542/olivier-anguenot.webp 48w,\n/static/8702446d6b785251d5977565e717b101/0f66d/olivier-anguenot.webp 96w","type":"image/webp","sizes":"48px"}]},"width":48,"height":48},"ImageSharp_regular":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYFBP/EABYBAQEBAAAAAAAAAAAAAAAAAAMCBP/aAAwDAQACEAMQAAABtJOlgc2i6Zii3oAheUIP/8QAHhAAAgEDBQAAAAAAAAAAAAAAAgMEAQUSABQiJDP/2gAIAQEAAQUCnMqpa5bFSa11cBzXJHsLbkL/ADuXCRuzEv/EABcRAQEBAQAAAAAAAAAAAAAAAAIQETH/2gAIAQMBAT8BJ07Byf/EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiEx/9oACAECAQE/ASbUtX//xAAfEAACAgIBBQAAAAAAAAAAAAABEQACAzFBEBMhIlH/2gAIAQEABj8C9SATyeJWmTN3aX+7HTTEAARQUZ3DGNpy4VfBn//EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQVFxgdH/2gAIAQEAAT8hyi+jX2ZZooUQs5K4mSbdBeCUEaBjpO4x+RHSephcZl3KVcUyP2f/2gAMAwEAAgADAAAAEOfng//EABcRAAMBAAAAAAAAAAAAAAAAAAEQMUH/2gAIAQMBAT8QAXSuv//EABgRAAMBAQAAAAAAAAAAAAAAAAABERAx/9oACAECAQE/EGKc5kP/xAAdEAEBAAMAAgMAAAAAAAAAAAABEQAhMUFRYaGx/9oACAEBAAE/EANSSJgqnmBo9pjwNyCUHB0mk5zArBQJUtFpMMHKxFH2n5j0myRreLplXr5mGnYC7YnsNaEJ2DP/2Q=="},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg 128w","sizes":"128px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/9e357/olivier-anguenot.webp 128w","type":"image/webp","sizes":"128px"}]},"width":150,"height":150}}},"thumbnail":{"__typename":"ImageSharp","ImageSharp_vertical":{"layout":"constrained","backgroundColor":"#583828","images":{"fallback":{"src":"/static/98c9516b80401fc06101772a128796e3/144fe/photo.jpg","srcSet":"/static/98c9516b80401fc06101772a128796e3/9d7b9/photo.jpg 190w,\n/static/98c9516b80401fc06101772a128796e3/144fe/photo.jpg 380w","sizes":"(min-width: 380px) 380px, 100vw"},"sources":[{"srcSet":"/static/98c9516b80401fc06101772a128796e3/228d6/photo.webp 190w,\n/static/98c9516b80401fc06101772a128796e3/6b99c/photo.webp 380w","type":"image/webp","sizes":"(min-width: 380px) 380px, 100vw"}]},"width":380,"height":290},"ImageSharp_hero":{"layout":"constrained","backgroundColor":"#583828","images":{"fallback":{"src":"/static/98c9516b80401fc06101772a128796e3/5e493/photo.jpg","srcSet":"/static/98c9516b80401fc06101772a128796e3/696c0/photo.jpg 800w,\n/static/98c9516b80401fc06101772a128796e3/5e493/photo.jpg 1600w","sizes":"(min-width: 1600px) 1600px, 100vw"},"sources":[{"srcSet":"/static/98c9516b80401fc06101772a128796e3/c9f06/photo.webp 800w,\n/static/98c9516b80401fc06101772a128796e3/f47df/photo.webp 1600w","type":"image/webp","sizes":"(min-width: 1600px) 1600px, 100vw"}]},"width":1600,"height":650}}},{"id":"94d2401e-b3ae-5994-96a8-246914a8210d","title":"Debugging WebRTC on your iPad","slug":"/debugging-webrtc-on-your-ipad/","link":null,"excerpt":"Debugging a WebRTC Web application on mobile or tablet devices, particularly on an iPad, remains a…","timeToRead":null,"featured":null,"thumbnailText":null,"date":"September 25, 2024","category":{"id":"0fde40c1-42e7-595e-8ce3-5969b3416bbd","name":"dev","slug":"/category/dev/","color":null,"icon":"/static/93c9c75517e1a6e95deaecabf3d1d050/dev.svg"},"author":{"id":"a1ce6965-86d7-5de2-8e55-c593e5fcc1bb","name":"Olivier Anguenot","slug":"/author/olivier-anguenot/","title":"Your WebRTC copilot","description":"Technical leader at Alcatel-Lucent Enterprise. Father of 2. Working on WebRTC the week-end","skills":["WebRTC","Javascript"],"social":[{"name":"Github","url":"https://github.com/oanguenot"},{"name":"Twitter","url":"https://twitter.com/oanguenot"},{"name":"Linkedin","url":"https://www.linkedin.com/in/olivier-anguenot-99503a33/"}],"thumbnail":{"__typename":"ImageSharp","ImageSharp_small":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAMC/9oADAMBAAIQAxAAAAGnnu5IA1YwqPrSBCZxZ//EAB4QAAIBAwUAAAAAAAAAAAAAAAIDBAABEhMUIiMy/9oACAEBAAEFApJ6YDJYt9ShzB1u4GZC3xM4O3JiX//EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiIx/9oACAEDAQE/AQKqOL//xAAXEQEAAwAAAAAAAAAAAAAAAAAQAjFB/9oACAECAQE/AdJWf//EAB0QAAEEAwEBAAAAAAAAAAAAAAEAAhEhEEFRAxP/2gAIAQEABj8CogE7OkGu9fo13dY6oAuozI5KcIFFf//EABsQAQADAQEBAQAAAAAAAAAAAAEAESExQWGB/9oACAEBAAE/IV0go4fUuXXwX9FRdnZEF4THRoEMWx77FSfyYe1NSoaVOM//2gAMAwEAAgADAAAAENQQ/v/EABYRAQEBAAAAAAAAAAAAAAAAAAEQMf/aAAgBAwEBPxA1M3n/xAAYEQEBAAMAAAAAAAAAAAAAAAABABARMf/aAAgBAgEBPxBUw42r/8QAHBABAQACAwEBAAAAAAAAAAAAAREAITFRYUGB/9oACAEBAAE/EPP3jAVR9gaO0yZtyEswQGrNOHWGkTpItJhhgmRRO/ZgdzdI7xOWryw0rIHbeVZgFon45//Z"},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/ac0cb/olivier-anguenot.jpg 48w,\n/static/8702446d6b785251d5977565e717b101/73f48/olivier-anguenot.jpg 96w","sizes":"48px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/a3542/olivier-anguenot.webp 48w,\n/static/8702446d6b785251d5977565e717b101/0f66d/olivier-anguenot.webp 96w","type":"image/webp","sizes":"48px"}]},"width":48,"height":48},"ImageSharp_regular":{"layout":"fixed","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYFBP/EABYBAQEBAAAAAAAAAAAAAAAAAAMCBP/aAAwDAQACEAMQAAABtJOlgc2i6Zii3oAheUIP/8QAHhAAAgEDBQAAAAAAAAAAAAAAAgMEAQUSABQiJDP/2gAIAQEAAQUCnMqpa5bFSa11cBzXJHsLbkL/ADuXCRuzEv/EABcRAQEBAQAAAAAAAAAAAAAAAAIQETH/2gAIAQMBAT8BJ07Byf/EABgRAAIDAAAAAAAAAAAAAAAAAAEQAiEx/9oACAECAQE/ASbUtX//xAAfEAACAgIBBQAAAAAAAAAAAAABEQACAzFBEBMhIlH/2gAIAQEABj8C9SATyeJWmTN3aX+7HTTEAARQUZ3DGNpy4VfBn//EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQVFxgdH/2gAIAQEAAT8hyi+jX2ZZooUQs5K4mSbdBeCUEaBjpO4x+RHSephcZl3KVcUyP2f/2gAMAwEAAgADAAAAEOfng//EABcRAAMBAAAAAAAAAAAAAAAAAAEQMUH/2gAIAQMBAT8QAXSuv//EABgRAAMBAQAAAAAAAAAAAAAAAAABERAx/9oACAECAQE/EGKc5kP/xAAdEAEBAAMAAgMAAAAAAAAAAAABEQAhMUFRYaGx/9oACAEBAAE/EANSSJgqnmBo9pjwNyCUHB0mk5zArBQJUtFpMMHKxFH2n5j0myRreLplXr5mGnYC7YnsNaEJ2DP/2Q=="},"images":{"fallback":{"src":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg","srcSet":"/static/8702446d6b785251d5977565e717b101/132ea/olivier-anguenot.jpg 128w","sizes":"128px"},"sources":[{"srcSet":"/static/8702446d6b785251d5977565e717b101/9e357/olivier-anguenot.webp 128w","type":"image/webp","sizes":"128px"}]},"width":150,"height":150}}},"thumbnail":{"__typename":"ImageSharp","ImageSharp_vertical":{"layout":"constrained","backgroundColor":"#282828","images":{"fallback":{"src":"/static/6b907edc7c52f83bd8370bb472a86f82/144fe/photo.jpg","srcSet":"/static/6b907edc7c52f83bd8370bb472a86f82/9d7b9/photo.jpg 190w,\n/static/6b907edc7c52f83bd8370bb472a86f82/144fe/photo.jpg 380w","sizes":"(min-width: 380px) 380px, 100vw"},"sources":[{"srcSet":"/static/6b907edc7c52f83bd8370bb472a86f82/228d6/photo.webp 190w,\n/static/6b907edc7c52f83bd8370bb472a86f82/6b99c/photo.webp 380w","type":"image/webp","sizes":"(min-width: 380px) 380px, 100vw"}]},"width":380,"height":290},"ImageSharp_hero":{"layout":"constrained","backgroundColor":"#282828","images":{"fallback":{"src":"/static/6b907edc7c52f83bd8370bb472a86f82/5e493/photo.jpg","srcSet":"/static/6b907edc7c52f83bd8370bb472a86f82/696c0/photo.jpg 800w,\n/static/6b907edc7c52f83bd8370bb472a86f82/5e493/photo.jpg 1600w","sizes":"(min-width: 1600px) 1600px, 100vw"},"sources":[{"srcSet":"/static/6b907edc7c52f83bd8370bb472a86f82/c9f06/photo.webp 800w,\n/static/6b907edc7c52f83bd8370bb472a86f82/f47df/photo.webp 1600w","type":"image/webp","sizes":"(min-width: 1600px) 1600px, 100vw"}]},"width":1600,"height":650}}}]},"previous":{"id":"86bb49e3-d5c3-522e-876a-42c95067218c","slug":"/webrtc-api-update-q2-2024/","title":"WebRTC API update Q2 2024"},"next":{"id":"94d2401e-b3ae-5994-96a8-246914a8210d","slug":"/debugging-webrtc-on-your-ipad/","title":"Debugging WebRTC on your iPad"}},"pageContext":{"id":"296be325-9ce0-59fe-b746-bdc5e26a06a5","categoryId":"0fde40c1-42e7-595e-8ce3-5969b3416bbd","tagsIds":["ed8e58df-33d1-54a6-9d36-4ec7f3f8fb05","c3022941-a3b9-53c3-b74f-3dedddbdf091","93511dcd-50b3-5ad7-92e4-6abcc09eb0fb"],"hasTags":true,"previousId":"86bb49e3-d5c3-522e-876a-42c95067218c","nextId":"94d2401e-b3ae-5994-96a8-246914a8210d","paginatePostsPage":true,"basePath":"/","services":{"algolia":false,"mailchimp":false,"disqus":true,"graphComment":false,"facebookComment":false},"siteUrl":"https://www.webrtc-developers.com","darkMode":false,"includeExcerpt":true,"includeTimeToRead":true,"includeTableOfContents":true,"imageQuality":75,"frontmatter":{"title":"Managing Devices in WebRTC","category":"dev","author":"Olivier Anguenot","tags":["#getUserMedia","#microphone","#camera"],"date":"2024-07-29T00:00:00.000Z","thumbnail":"photo.jpg"}}},"staticQueryHashes":["1992822086","2409295108","267426511","2918496967","4235339838","4240507859"],"slicesMap":{}}