我从 getdisplaymedia 获取屏幕视频和系统声音流,从 getusermedia 获取麦克风流,并使用 MediaRecorder 录制这些流。麦克风和屏幕录制都很好,所有系统声音都来了,但 jitsi 参与者的声音没有录制。这是我的代码:
函数 openShareScreen() {
navigator.mediaDevices.getDisplayMedia({
video: { displaySurface: "browser" },
audio: true
}).then((desktopStream) => {
let screenAudioTrack = desktopStream.getAudioTracks()[0];
if (screenAudioTrack === undefined) {
confirmSwalMessageConfirmOnly("Ses Paylaşımı Yapılmadı!", "Görüşme kaydı için lütfen görüntü ve ses paylaşımına izin veriniz!", "warning", openShareScreen);
//recording = false;
desktopStream.getTracks()
.forEach(track => track.stop())
return null;
}
var finalStream = new MediaStream();
navigator.mediaDevices.getUserMedia({
video: false, audio: true
}).then((voiceStream) => {
//Kamera ve mikrofon izin kontrolü yapılıyor
navigator.permissions.query(
{ name: 'camera' },
{ name: 'microphone' }
).then(function (permissionStatus) {
// granted, denied, prompt
if (permissionStatus.state !== 'granted') {
confirmSwalMessageConfirmOnly("Mikrofon/Kamera izni verilmedi!", "Görüşme kaydı için internet tarayıcınıza mikrofon ve kameraya erişim izni veriniz!", "warning", openShareScreen);
//recording = false;
desktopStream.getTracks().forEach(track => track.stop())
voiceStream.getTracks().forEach(track => track.stop());
return null;
}
})
// important: we must convert multiple audio tracks into single audio track
var mixedAudioStream = getMixedAudioStreamXYZ([voiceStream, desktopStream]) || microphone;
mixedAudioStream.getAudioTracks().forEach(function (audioTrack) {
finalStream.addTrack(audioTrack);
});
desktopStream.getVideoTracks().forEach(function (videoTrack) {
finalStream.addTrack(videoTrack);
});
//Verilen time out interval süresinde kaydı başla
var timeOutStopRecorder;
recordLoop();
function recordLoop() {
recorder = new MediaRecorder(finalStream, { mimeType: 'video/webm', videoBitsPerSecond: glbVideoBitsPerSecond });
recorder.ondataavailable = e => {
if (e.data && e.data.size > 0) {
recordingData = [];
recordingData.push(e.data);
}
};
recorder.onstop = () => {
saveRecordDone = false;
clearTimeout(timeOutStopRecorder);
var blob = new Blob(recordingData, { type: 'video/webm' })
console.log("Kayıt Diske Yazıldı:" + getDateTimeNow());
SaveRecord(blob);
recordLoop();
};
console.log("Kayıt Başladı:" + getDateTimeNow());
recorder.start();
timeOutStopRecorder = setTimeout(() => {
console.log("Kayıt Durdu:" + getDateTimeNow());
recorder.stop();
}
, 60000);
}
//recorder = RecordRTC(finalStream, {
// type: 'video',
// mimeType: "video/webm;codecs=vp8,opus",
// videoBitsPerSecond: glbVideoBitsPerSecond
//});
//recorder.startRecording();
//recording = true;
finalStream.getVideoTracks()[0].addEventListener('ended', () => {
//stopRecordingAndSave();
recorder.stop();
confirmSwalMessageConfirmOnly("Paylaşım durduruldu!", "Görüşme kaydı için lütfen görüntü ve ses paylaşımına izin veriniz!", "warning", openShareScreen);
//recording = false;
});
}).catch(err => {
console.warn(err);
confirmSwalMessageConfirmOnly("Mikrofon/Kamera izni verilmedi!", "Görüşme kaydı için internet tarayıcınıza mikrofon ve kameraya erişim izni veriniz!", "warning", openShareScreen);
//recording = false;
});
}).catch(err => {
confirmSwalMessageConfirmOnly("Uyarı!", "Görüşme kaydı için lütfen görüntü ve ses paylaşımına izin veriniz!", "warning", openShareScreen);
//recording = false;
});
}
函数getMixedAudioStreamXYZ(arrayOfAudioStreams){
var audioContext = new AudioContext();
var audioSources = [];
var gainNode = audioContext.createGain();
gainNode.connect(audioContext.destination);
gainNode.gain.value = 0; // don't hear self
var audioTracksLength = 0;
arrayOfAudioStreams.forEach(function (stream) {
if (!stream.getAudioTracks().length) {
return;
}
audioTracksLength++;
var audioSource = audioContext.createMediaStreamSource(stream);
audioSource.connect(gainNode);
audioSources.push(audioSource);
});
if (!audioTracksLength) {
return;
}
audioDestination = audioContext.createMediaStreamDestination();
audioSources.forEach(function (audioSource) {
audioSource.connect(audioDestination);
});
return audioDestination.stream;
}