Add device picker for webcams and microphones to the settings modal
This commit is contained in:
parent
f4568b9087
commit
55b17f62c4
|
@ -277,11 +277,12 @@ const app = Vue.createApp({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
"webcam.videoScale": () => {
|
"webcam.videoScale": function() {
|
||||||
document.querySelectorAll(".video-feeds > .feed").forEach(node => {
|
document.querySelectorAll(".video-feeds > .feed").forEach(node => {
|
||||||
node.style.width = null;
|
node.style.width = null;
|
||||||
node.style.height = null;
|
node.style.height = null;
|
||||||
});
|
});
|
||||||
|
localStorage.videoScale = this.webcam.videoScale;
|
||||||
},
|
},
|
||||||
fontSizeClass() {
|
fontSizeClass() {
|
||||||
// Store the setting persistently.
|
// Store the setting persistently.
|
||||||
|
@ -357,6 +358,10 @@ const app = Vue.createApp({
|
||||||
this.fontSizeClass = localStorage.fontSizeClass;
|
this.fontSizeClass = localStorage.fontSizeClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (localStorage.videoScale != undefined) {
|
||||||
|
this.webcam.videoScale = localStorage.videoScale;
|
||||||
|
}
|
||||||
|
|
||||||
// Webcam mutality preferences from last broadcast.
|
// Webcam mutality preferences from last broadcast.
|
||||||
if (localStorage.videoMutual === "true") {
|
if (localStorage.videoMutual === "true") {
|
||||||
this.webcam.mutual = true;
|
this.webcam.mutual = true;
|
||||||
|
@ -1127,7 +1132,9 @@ const app = Vue.createApp({
|
||||||
},
|
},
|
||||||
|
|
||||||
// Start broadcasting my webcam.
|
// Start broadcasting my webcam.
|
||||||
startVideo(force) {
|
// - force=true to skip the NSFW modal prompt (this param is passed by the button in that modal)
|
||||||
|
// - changeCamera=true to re-negotiate WebRTC connections with a new camera device (invoked by the Settings modal)
|
||||||
|
startVideo({force=false, changeCamera=false}) {
|
||||||
if (this.webcam.busy) return;
|
if (this.webcam.busy) return;
|
||||||
|
|
||||||
// If we are running in PermitNSFW mode, show the user the modal.
|
// If we are running in PermitNSFW mode, show the user the modal.
|
||||||
|
@ -1136,11 +1143,24 @@ const app = Vue.createApp({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.webcam.busy = true;
|
let mediaParams = {
|
||||||
navigator.mediaDevices.getUserMedia({
|
|
||||||
audio: true,
|
audio: true,
|
||||||
video: true,
|
video: {
|
||||||
}).then(stream => {
|
width: { max: 1280 },
|
||||||
|
height: { max: 720 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (changeCamera) {
|
||||||
|
// Name the specific devices chosen by the user.
|
||||||
|
mediaParams.video.deviceId = { exact: this.webcam.videoDeviceID };
|
||||||
|
mediaParams.audio = {
|
||||||
|
deviceId: { exact: this.webcam.audioDeviceID },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.webcam.busy = true;
|
||||||
|
navigator.mediaDevices.getUserMedia(mediaParams).then(stream => {
|
||||||
this.webcam.active = true;
|
this.webcam.active = true;
|
||||||
this.webcam.elem.srcObject = stream;
|
this.webcam.elem.srcObject = stream;
|
||||||
this.webcam.stream = stream;
|
this.webcam.stream = stream;
|
||||||
|
@ -1159,6 +1179,11 @@ const app = Vue.createApp({
|
||||||
|
|
||||||
// Collect video and audio devices to let the user change them in their settings.
|
// Collect video and audio devices to let the user change them in their settings.
|
||||||
this.getDevices();
|
this.getDevices();
|
||||||
|
|
||||||
|
// If we have changed devices, reconnect everybody's WebRTC channels for your existing watchers.
|
||||||
|
if (changeCamera) {
|
||||||
|
this.updateWebRTCStreams();
|
||||||
|
}
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
this.ChatClient(`Webcam error: ${err}`);
|
this.ChatClient(`Webcam error: ${err}`);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
|
@ -1177,11 +1202,13 @@ const app = Vue.createApp({
|
||||||
this.webcam.audioDevices = [];
|
this.webcam.audioDevices = [];
|
||||||
devices.forEach(device => {
|
devices.forEach(device => {
|
||||||
if (device.kind === 'videoinput') {
|
if (device.kind === 'videoinput') {
|
||||||
|
// console.log(`Video device ${device.deviceId} ${device.label}`);
|
||||||
this.webcam.videoDevices.push({
|
this.webcam.videoDevices.push({
|
||||||
id: device.deviceId,
|
id: device.deviceId,
|
||||||
label: device.label,
|
label: device.label,
|
||||||
});
|
});
|
||||||
} else if (device.kind === 'audioinput') {
|
} else if (device.kind === 'audioinput') {
|
||||||
|
// console.log(`Audio device ${device.deviceId} ${device.label}`);
|
||||||
this.webcam.audioDevices.push({
|
this.webcam.audioDevices.push({
|
||||||
id: device.deviceId,
|
id: device.deviceId,
|
||||||
label: device.label,
|
label: device.label,
|
||||||
|
@ -1193,6 +1220,36 @@ const app = Vue.createApp({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Replace your video/audio streams for your watchers (on camera changes)
|
||||||
|
updateWebRTCStreams() {
|
||||||
|
console.log("Re-negotiating video and audio channels to your watchers.");
|
||||||
|
for (let username of Object.keys(this.WebRTC.pc)) {
|
||||||
|
let pc = this.WebRTC.pc[username];
|
||||||
|
if (pc.answerer != undefined) {
|
||||||
|
let oldTracks = pc.answerer.getSenders();
|
||||||
|
let newTracks = this.webcam.stream.getTracks();
|
||||||
|
|
||||||
|
// Remove and replace the tracks.
|
||||||
|
for (let old of oldTracks) {
|
||||||
|
if (old.track.kind === 'audio') {
|
||||||
|
for (let replace of newTracks) {
|
||||||
|
if (replace.kind === 'audio') {
|
||||||
|
old.replaceTrack(replace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (old.track.kind === 'video') {
|
||||||
|
for (let replace of newTracks) {
|
||||||
|
if (replace.kind === 'video') {
|
||||||
|
old.replaceTrack(replace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Begin connecting to someone else's webcam.
|
// Begin connecting to someone else's webcam.
|
||||||
openVideo(user, force) {
|
openVideo(user, force) {
|
||||||
if (user.username === this.username) {
|
if (user.username === this.username) {
|
||||||
|
|
|
@ -114,13 +114,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Under construction
|
|
||||||
<div class="columns is-mobile" v-if="webcam.videoDevices.length > 0 || webcam.audioDevices.length > 0">
|
<div class="columns is-mobile" v-if="webcam.videoDevices.length > 0 || webcam.audioDevices.length > 0">
|
||||||
|
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<label class="label">Video source</label>
|
<label class="label">Video source</label>
|
||||||
<div class="select is-fullwidth">
|
<div class="select is-fullwidth">
|
||||||
<select v-model="webcam.videoDeviceID">
|
<select v-model="webcam.videoDeviceID" @change="startVideo({changeCamera: true, force: true})">
|
||||||
<option v-for="(d, i) in webcam.videoDevices"
|
<option v-for="(d, i) in webcam.videoDevices"
|
||||||
:value="d.id">
|
:value="d.id">
|
||||||
[[ d.label || `Camera ${i}` ]]
|
[[ d.label || `Camera ${i}` ]]
|
||||||
|
@ -132,7 +131,7 @@
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<label class="label">Audio source</label>
|
<label class="label">Audio source</label>
|
||||||
<div class="select is-fullwidth">
|
<div class="select is-fullwidth">
|
||||||
<select v-model="webcam.audioDeviceID">
|
<select v-model="webcam.audioDeviceID" @change="startVideo({changeCamera: true, force: true})">
|
||||||
<option v-for="(d, i) in webcam.audioDevices"
|
<option v-for="(d, i) in webcam.audioDevices"
|
||||||
:value="d.id">
|
:value="d.id">
|
||||||
[[ d.label || `Microphone ${i}` ]]
|
[[ d.label || `Microphone ${i}` ]]
|
||||||
|
@ -141,7 +140,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
-->
|
|
||||||
|
|
||||||
<h3 class="subtitle mb-2">Sounds</h3>
|
<h3 class="subtitle mb-2">Sounds</h3>
|
||||||
|
|
||||||
|
@ -360,7 +358,7 @@
|
||||||
<div class="control has-text-centered">
|
<div class="control has-text-centered">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="button is-link mr-4"
|
class="button is-link mr-4"
|
||||||
@click="startVideo(true); nsfwModalCast.visible=false">Start webcam</button>
|
@click="startVideo({force: true}); nsfwModalCast.visible=false">Start webcam</button>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="button"
|
class="button"
|
||||||
@click="nsfwModalCast.visible=false">Cancel</button>
|
@click="nsfwModalCast.visible=false">Cancel</button>
|
||||||
|
@ -442,7 +440,7 @@
|
||||||
<button type="button"
|
<button type="button"
|
||||||
v-else
|
v-else
|
||||||
class="button is-small is-success px-1"
|
class="button is-small is-success px-1"
|
||||||
@click="startVideo()"
|
@click="startVideo({})"
|
||||||
:disabled="webcam.busy">
|
:disabled="webcam.busy">
|
||||||
<i class="fa fa-video mr-2"></i>
|
<i class="fa fa-video mr-2"></i>
|
||||||
Share webcam
|
Share webcam
|
||||||
|
|
Loading…
Reference in New Issue
Block a user