diff --git a/plugin/WebRTC/api.js b/plugin/WebRTC/api.js
index e5bcffac50..6cd4741915 100644
--- a/plugin/WebRTC/api.js
+++ b/plugin/WebRTC/api.js
@@ -166,12 +166,8 @@ async function startWebRTC({ videoDeviceId = null, audioDeviceId = null, useScre
// Constraints for selected devices or default devices
const isLandscape = window.screen.orientation.type.startsWith('landscape');
- const videoConstraints = {
- width: { ideal: 1280 },
- height: { ideal: 720 },
- frameRate: { ideal: 30 },
- aspectRatio: isLandscape ? 16 / 9 : 9 / 16,
- };
+ const videoConstraints = buildVideoConstraints(videoDeviceId);
+ videoConstraints.aspectRatio = isLandscape ? 16 / 9 : 9 / 16;
console.log('videoConstraints', isLandscape, videoConstraints);
@@ -273,6 +269,66 @@ function unlockScreenOrientation() {
}
}
+// Populate the video/audio source dropdowns
+async function populateSources() {
+ try {
+ // Request camera access to get labels in mobile browsers (required in iOS/Android)
+ await navigator.mediaDevices.getUserMedia({ video: true, audio: false });
+
+ const devices = await navigator.mediaDevices.enumerateDevices();
+
+ // Clear existing options
+ $('#videoSource').empty().append('');
+ $('#audioSource').empty().append('');
+
+ const videoInputs = devices.filter(device => device.kind === 'videoinput');
+ const audioInputs = devices.filter(device => device.kind === 'audioinput');
+
+ // Populate video sources
+ videoInputs.forEach((device, index) => {
+ $('#videoSource').append(
+ ``
+ );
+ });
+
+ // If only 1 camera is available or labels are missing, add facingMode fallback options
+ if (videoInputs.length <= 1) {
+ $('#videoSource').append('');
+ $('#videoSource').append('');
+ }
+
+ // Populate audio sources
+ audioInputs.forEach((device, index) => {
+ $('#audioSource').append(
+ ``
+ );
+ });
+
+ } catch (error) {
+ console.error('Error populating media sources:', error);
+ }
+}
+
+// Build video constraints, supporting facingMode fallback
+function buildVideoConstraints(deviceIdOrFacingMode) {
+ const base = {
+ width: { ideal: 1280 },
+ height: { ideal: 720 },
+ frameRate: { ideal: 30 }
+ };
+
+ if (!deviceIdOrFacingMode) return base;
+
+ if (deviceIdOrFacingMode === 'facing-user') {
+ return { ...base, facingMode: { exact: 'user' } };
+ } else if (deviceIdOrFacingMode === 'facing-environment') {
+ return { ...base, facingMode: { exact: 'environment' } };
+ } else {
+ return { ...base, deviceId: { exact: deviceIdOrFacingMode } };
+ }
+}
+
+
window.addEventListener('orientationchange', () => {
console.log('Orientation changed.');
if (isLive) {
@@ -286,28 +342,6 @@ window.addEventListener('orientationchange', () => {
$(document).ready(function () {
- // Populate Video and Audio Sources
- function populateSources() {
- navigator.mediaDevices.enumerateDevices().then((devices) => {
- // Clear existing options
- $('#videoSource').empty().append('');
- $('#audioSource').empty().append('');
-
- devices.forEach((device) => {
- if (device.kind === 'videoinput') {
- $('#videoSource').append(
- ``
- );
- } else if (device.kind === 'audioinput') {
- $('#audioSource').append(
- ``
- );
- }
- });
- }).catch((error) => console.error('Error enumerating devices:', error));
- }
-
- // Initialize sources on load
populateSources();
// Start Screen Sharing