I'm facing this trouble with popup. When I select "get audio from desktop" and click "Start Recording" , another popup of browser appears , asking me for another decision ( It is about selecting the screen and sharing audio .I realize if I select "Sharing Audio" and click the blue button "share" . It starts to record and a modal appears : "website is sharing the screen and audio " but If I stop the recording with clicking "Stop Capture" button , the modal of "Website is sharing ... " still appearing . Could someone help me or explaining me if that is possible to disappear that modal when I click "Stop Capture" . Thanks.
I leave the codepen link, the design is a bit disorder but It has the code about the functionality, thanks.
https://codepen.io/gian1599/pen/QWpabWK?editors=1011
Images: 1, 2, 3. I wrote carefully about the workflow, thanks.
new Vue({
el: "#app",
vuetify: new Vuetify(),
data() {
return {
valueMicAudioToggle: false,
valueAudioToggle: false,
valuestopBtn: true,
valueCaptureBtn: false,
valueStart: false,
stream: "",
rec: ""
};
},
methods: {
startBtn() {
let blobs;
let blob;
const videoElement = document.getElementById("videoElement");
const startBtn = document.getElementById("startBtn");
const mergeAudioStreams = (desktopStream, voiceStream) => {
const context = new AudioContext();
const destination = context.createMediaStreamDestination();
let hasDesktop = false;
let hasVoice = false;
if (desktopStream && desktopStream.getAudioTracks().length > 0) {
// If you don't want to share Audio from the desktop it should still work with just the voice.
const source1 = context.createMediaStreamSource(desktopStream);
const desktopGain = context.createGain();
desktopGain.gain.value = 0.7;
source1.connect(desktopGain).connect(destination);
hasDesktop = true;
}
if (voiceStream && voiceStream.getAudioTracks().length > 0) {
const source2 = context.createMediaStreamSource(voiceStream);
const voiceGain = context.createGain();
voiceGain.gain.value = 0.7;
source2.connect(voiceGain).connect(destination);
hasVoice = true;
}
return hasDesktop || hasVoice
? destination.stream.getAudioTracks()
: [];
};
let voiceStream;
let desktopStream;
// const captureBtn = document.getElementById("captureBtn");
const download = document.getElementById("download");
const audioToggle = document.getElementById("audioToggle");
const micAudioToggle = document.getElementById("micAudioToggle");
const self = this;
const captureBtn = async () => {
download.style.display = "none";
const audio = audioToggle.checked || false;
const mic = micAudioToggle.checked || false;
desktopStream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio: audio
});
if (mic === true) {
voiceStream = await navigator.mediaDevices.getUserMedia({
video: false,
audio: mic
});
}
const tracks = [
...desktopStream.getVideoTracks(),
...mergeAudioStreams(desktopStream, voiceStream)
];
console.log("Tracks to add to stream", tracks);
self.stream = new MediaStream(tracks);
console.log("Stream", self.stream);
videoElement.srcObject = self.stream;
videoElement.muted = true;
blobs = [];
self.rec = new MediaRecorder(self.stream, {
mimeType: "video/webm; codecs=vp8,opus"
});
self.rec.ondataavailable = (e) => blobs.push(e.data);
self.rec.onstop = async () => {
// blobs.push(MediaRecorder.requestData());
blob = new Blob(blobs, { type: "video/webm" });
const url = window.URL.createObjectURL(blob);
download.href = url;
download.download = "test.webm";
download.style.display = "block";
};
this.valuestopBtn = false;
this.valueStart = true;
this.valueCaptureBtn = true;
this.valueAudioToggle = true;
this.valueMicAudioToggle = true;
// this.stopBtn = true
this.rec.start();
};
captureBtn();
},
// const startBtn = document.getElementById('startBtn')
// const stopBtn = document.getElementById('stopBtn')
stop() {
const videoElement = document.getElementById("videoElement");
// this.startBtn = true
// this.stopBtn = false
this.valueAudioToggle = false;
this.valueMicAudioToggle = false;
this.valueStart = false;
// this.stopBtn = true
this.valuestopBtn = true;
// const self = this
this.rec.stop();
this.stream.getTracks().forEach((s) => s.stop());
videoElement.srcObject = null;
this.stream = null;
}
}
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<div class="pointer video-list__container">
<video id="videoElement" autoplay controls loop muted />
</div>
<div>
<v-row>
<v-col class="d-flex justify-center" cols="6">
<v-checkbox id="audioToggle" :disabled="valueAudioToggle" label="Get Audio from Desktop" />
<!-- <input
id="audioToggle"
:disabled="valueAudioToggle"
type="checkbox"
>
<label for="audioToggle">Capture Audio from Desktop</label> -->
</v-col>
<v-col class="d-flex justify-center" cols="6">
<v-checkbox id="micAudioToggle" :disabled="valueMicAudioToggle" label="Get Audio from Microphone" />
<!-- <input
id="micAudioToggle"
:disabled="valueMicAudioToggle"
type="checkbox"
>
<label for="micAudioToggle">Capture Audio from Microphone</label> -->
</v-col>
</v-row>
<v-container>
<v-row>
<v-col class="d-flex justify-center" cols="12" />
<v-btn id="download" class="accent-3 blue px-10" :disabled="buttonStateDownload">
<a id="download1" align="center">Download</a>
</v-btn>
</v-col>
</v-row>
</v-container>
<v-container>
<v-row>
<v-col class="d-flex justify-center" cols="12" />
<v-col class="d-flex justify-center ml-0" cols="12">
<p id="message" />
</v-col>
</v-row>
</v-container>
</div>
<v-row>
<v-col class="d-flex justify-center" cols="6">
<v-btn id="startBtn" class="accent-3 blue" :disabled="valueStart" @click="startBtn">
Start Recording
</v-btn>
</v-col>
<v-col class="d-flex justify-center" cols="6">
<v-btn id="stopBtn" class="accent-3 blue" :disabled="valuestopBtn" @click="stop">
Stop Capture
</v-btn>
</v-col>
</v-row>
</div>
</div>
In your stop
function, you stop all the tracks on this.stream
. That includes the video tracks from the desktop stream, but only the audio tracks from the merged audio stream. The original, individual audio tracks from the desktop and the mic are not stopped, so as far as the browser knows they are still active.
Here is one way to stop the original streams:
new Vue({
// ...
data () {
return {
// ...
individualAudioStreams: [],
// ...
}
},
methods: {
startBtn() {
// ...
const mergeAudioStreams = (desktopStream, voiceStream) => {
// ...
if (desktopStream && desktopStream.getAudioTracks().length > 0) {
// ...
this.individualAudioStreams.push(desktopStream)
}
if (voiceStream && voiceStream.getAudioTracks().length > 0) {
// ...
this.individualAudioStreams.push(voiceStream)
}
// ...
}
// ...
},
stop() {
// ...
this.individualAudioStreams.forEach(s => s.getTracks().forEach(t => t.stop()))
this.individualAudioStreams = []
// ...
}
},
})