Fixed cases of no Media Content, and swapping Media failing.
This commit is contained in:
@@ -11,23 +11,46 @@ const Media = {
|
|||||||
const cameraSelect = document.getElementById("cameraSelect");
|
const cameraSelect = document.getElementById("cameraSelect");
|
||||||
const micSelect = document.getElementById("micSelect");
|
const micSelect = document.getElementById("micSelect");
|
||||||
|
|
||||||
|
if (!cameraSelect || !micSelect) return;
|
||||||
|
|
||||||
|
const selectedCamera = cameraSelect.value;
|
||||||
|
const selectedMic = micSelect.value;
|
||||||
|
|
||||||
cameraSelect.innerHTML = "";
|
cameraSelect.innerHTML = "";
|
||||||
micSelect.innerHTML = "";
|
micSelect.innerHTML = "";
|
||||||
|
|
||||||
|
const noCamera = document.createElement("option");
|
||||||
|
noCamera.value = "";
|
||||||
|
noCamera.textContent = "No camera / audio only";
|
||||||
|
cameraSelect.appendChild(noCamera);
|
||||||
|
|
||||||
|
const defaultMic = document.createElement("option");
|
||||||
|
defaultMic.value = "";
|
||||||
|
defaultMic.textContent = "Default microphone";
|
||||||
|
micSelect.appendChild(defaultMic);
|
||||||
|
|
||||||
for (const camera of cameras) {
|
for (const camera of cameras) {
|
||||||
const option = document.createElement("option");
|
const option = document.createElement("option");
|
||||||
option.value = camera.deviceId;
|
option.value = camera.deviceId;
|
||||||
option.textContent = camera.label || `Camera ${cameraSelect.length + 1}`;
|
option.textContent = camera.label || `Camera ${cameraSelect.length}`;
|
||||||
cameraSelect.appendChild(option);
|
cameraSelect.appendChild(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const mic of mics) {
|
for (const mic of mics) {
|
||||||
const option = document.createElement("option");
|
const option = document.createElement("option");
|
||||||
option.value = mic.deviceId;
|
option.value = mic.deviceId;
|
||||||
option.textContent = mic.label || `Microphone ${micSelect.length + 1}`;
|
option.textContent = mic.label || `Microphone ${micSelect.length}`;
|
||||||
micSelect.appendChild(option);
|
micSelect.appendChild(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cameraSelect.value = [...cameraSelect.options].some(o => o.value === selectedCamera)
|
||||||
|
? selectedCamera
|
||||||
|
: "";
|
||||||
|
|
||||||
|
micSelect.value = [...micSelect.options].some(o => o.value === selectedMic)
|
||||||
|
? selectedMic
|
||||||
|
: "";
|
||||||
|
|
||||||
LogMessage(`Loaded devices: ${cameras.length} cameras, ${mics.length} mics`);
|
LogMessage(`Loaded devices: ${cameras.length} cameras, ${mics.length} mics`);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -39,8 +62,8 @@ const Media = {
|
|||||||
return localStream;
|
return localStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
const audioDeviceId = micSelect?.value;
|
const audioDeviceId = micSelect?.value || "";
|
||||||
const videoDeviceId = cameraSelect?.value;
|
const videoDeviceId = cameraSelect?.value || "";
|
||||||
|
|
||||||
const constraints = {
|
const constraints = {
|
||||||
audio: audioDeviceId
|
audio: audioDeviceId
|
||||||
@@ -48,12 +71,14 @@ const Media = {
|
|||||||
: true,
|
: true,
|
||||||
video: videoDeviceId
|
video: videoDeviceId
|
||||||
? { deviceId: { exact: videoDeviceId } }
|
? { deviceId: { exact: videoDeviceId } }
|
||||||
: true
|
: false
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
localStream = await navigator.mediaDevices.getUserMedia(constraints);
|
localStream = await navigator.mediaDevices.getUserMedia(constraints);
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
LogMessage("Selected media failed: " + err);
|
||||||
|
|
||||||
localStream = await navigator.mediaDevices.getUserMedia({
|
localStream = await navigator.mediaDevices.getUserMedia({
|
||||||
audio: audioDeviceId
|
audio: audioDeviceId
|
||||||
? { deviceId: { exact: audioDeviceId } }
|
? { deviceId: { exact: audioDeviceId } }
|
||||||
@@ -75,13 +100,13 @@ const Media = {
|
|||||||
const localMediaStatus = document.getElementById("localMediaStatus");
|
const localMediaStatus = document.getElementById("localMediaStatus");
|
||||||
const localVideoStatus = document.getElementById("localVideoStatus");
|
const localVideoStatus = document.getElementById("localVideoStatus");
|
||||||
|
|
||||||
if (localVideo) {
|
|
||||||
localVideo.srcObject = stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
const audioTracks = stream.getAudioTracks();
|
const audioTracks = stream.getAudioTracks();
|
||||||
const videoTracks = stream.getVideoTracks();
|
const videoTracks = stream.getVideoTracks();
|
||||||
|
|
||||||
|
if (localVideo) {
|
||||||
|
localVideo.srcObject = videoTracks.length > 0 ? stream : null;
|
||||||
|
}
|
||||||
|
|
||||||
if (localMediaStatus) {
|
if (localMediaStatus) {
|
||||||
localMediaStatus.textContent =
|
localMediaStatus.textContent =
|
||||||
audioTracks.length > 0
|
audioTracks.length > 0
|
||||||
@@ -97,6 +122,19 @@ const Media = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async restartLocalMedia() {
|
||||||
|
if (localStream) {
|
||||||
|
localStream.getTracks().forEach(track => track.stop());
|
||||||
|
localStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.ensureLocalMedia();
|
||||||
|
|
||||||
|
if (window.RelayRtc?.applyLocalStreamToAllPeerConnections) {
|
||||||
|
await window.RelayRtc.applyLocalStreamToAllPeerConnections();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
async refreshDevicesAndPreview() {
|
async refreshDevicesAndPreview() {
|
||||||
if (localStream) {
|
if (localStream) {
|
||||||
localStream.getTracks().forEach(track => track.stop());
|
localStream.getTracks().forEach(track => track.stop());
|
||||||
@@ -113,7 +151,6 @@ const Media = {
|
|||||||
|
|
||||||
async applyLocalStreamToPeerConnection(pc, username) {
|
async applyLocalStreamToPeerConnection(pc, username) {
|
||||||
const stream = await this.ensureLocalMedia();
|
const stream = await this.ensureLocalMedia();
|
||||||
|
|
||||||
const existingSenders = pc.getSenders();
|
const existingSenders = pc.getSenders();
|
||||||
|
|
||||||
for (const track of stream.getTracks()) {
|
for (const track of stream.getTracks()) {
|
||||||
@@ -123,12 +160,12 @@ const Media = {
|
|||||||
|
|
||||||
if (existingSender) {
|
if (existingSender) {
|
||||||
await existingSender.replaceTrack(track);
|
await existingSender.replaceTrack(track);
|
||||||
|
LogMessage(`Replaced local ${track.kind} track for ${username}`);
|
||||||
} else {
|
} else {
|
||||||
pc.addTrack(track, stream);
|
pc.addTrack(track, stream);
|
||||||
}
|
|
||||||
|
|
||||||
LogMessage(`Added local ${track.kind} track for ${username}`);
|
LogMessage(`Added local ${track.kind} track for ${username}`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async applyLocalStreamToAllPeerConnections() {
|
async applyLocalStreamToAllPeerConnections() {
|
||||||
@@ -146,21 +183,25 @@ const Media = {
|
|||||||
const video = tile.querySelector("video");
|
const video = tile.querySelector("video");
|
||||||
const status = tile.querySelector(".remote-media-status");
|
const status = tile.querySelector(".remote-media-status");
|
||||||
|
|
||||||
|
if (video) {
|
||||||
video.srcObject = stream;
|
video.srcObject = stream;
|
||||||
|
}
|
||||||
|
|
||||||
const audioTracks = stream.getAudioTracks();
|
const audioTracks = stream.getAudioTracks();
|
||||||
const videoTracks = stream.getVideoTracks();
|
const videoTracks = stream.getVideoTracks();
|
||||||
|
|
||||||
|
if (status) {
|
||||||
status.textContent =
|
status.textContent =
|
||||||
`${audioTracks.length > 0 ? "Audio" : "No audio"} / ` +
|
`${audioTracks.length > 0 ? "Audio" : "No audio"} / ` +
|
||||||
`${videoTracks.length > 0 ? "Video" : "No video"}`;
|
`${videoTracks.length > 0 ? "Video" : "No video"}`;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ensureRemoteTile(username) {
|
ensureRemoteTile(username) {
|
||||||
const container = document.getElementById("remoteMediaContainer");
|
const container = document.getElementById("remoteMediaContainer");
|
||||||
|
if (!container) return null;
|
||||||
|
|
||||||
let tile = document.getElementById(`remote-tile-${username}`);
|
let tile = document.getElementById(`remote-tile-${username}`);
|
||||||
|
|
||||||
if (tile) return tile;
|
if (tile) return tile;
|
||||||
|
|
||||||
tile = document.createElement("div");
|
tile = document.createElement("div");
|
||||||
@@ -204,14 +245,14 @@ const Media = {
|
|||||||
if (cameraSelect) {
|
if (cameraSelect) {
|
||||||
cameraSelect.addEventListener("change", async () => {
|
cameraSelect.addEventListener("change", async () => {
|
||||||
LogMessage("Camera changed");
|
LogMessage("Camera changed");
|
||||||
await this.refreshDevicesAndPreview();
|
await this.restartLocalMedia();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (micSelect) {
|
if (micSelect) {
|
||||||
micSelect.addEventListener("change", async () => {
|
micSelect.addEventListener("change", async () => {
|
||||||
LogMessage("Microphone changed");
|
LogMessage("Microphone changed");
|
||||||
await this.refreshDevicesAndPreview();
|
await this.restartLocalMedia();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user