[mirotalksfu] - #33 allow recording participants audio

هذا الالتزام موجود في:
Miroslav Pejic
2023-09-29 10:22:01 +02:00
الأصل 65651f07de
التزام 6b88afddb4
2 ملفات معدلة مع 77 إضافات و16 حذوفات

عرض الملف

@@ -838,6 +838,18 @@ function startServer() {
room.broadCast(socket.id, 'setVideoOff', data); room.broadCast(socket.id, 'setVideoOff', data);
}); });
socket.on('recordingAction', async (dataObject) => {
if (!roomList.has(socket.room_id)) return;
const data = checkXSS(dataObject);
log.debug('Recording action', data);
const room = roomList.get(socket.room_id);
room.broadCast(data.peer_id, 'recordingAction', data);
});
socket.on('join', async (dataObject, cb) => { socket.on('join', async (dataObject, cb) => {
if (!roomList.has(socket.room_id)) { if (!roomList.has(socket.room_id)) {
return cb({ return cb({

عرض الملف

@@ -693,6 +693,14 @@ class RoomClient {
}.bind(this), }.bind(this),
); );
this.socket.on(
'recordingAction',
function (data) {
console.log('Recording action:', data);
this.handleRecordingAction(data);
}.bind(this),
);
this.socket.on( this.socket.on(
'connect', 'connect',
function () { function () {
@@ -3291,9 +3299,17 @@ class RoomClient {
console.log('MediaRecorder supported options', options); console.log('MediaRecorder supported options', options);
options = { mimeType: options[0] }; options = { mimeType: options[0] };
try { try {
// get all participants audio tracks
const audioTracks = this.getAudioTracksFromAudioElements();
//
if (this.isMobileDevice) { if (this.isMobileDevice) {
// on mobile devices recording camera + audio console.log('INIT CAM RECORDING', {
let newStream = this.getNewStream(this.localVideoStream, this.localAudioStream); localAudioStream: this.localAudioStream,
localVideoStream: this.localVideoStream,
audioTracks: audioTracks,
});
// on mobile devices recording camera + all audio tracks
let newStream = new MediaStream([...this.localVideoStream.getTracks(), ...audioTracks]);
this.mediaRecorder = new MediaRecorder(newStream, options); this.mediaRecorder = new MediaRecorder(newStream, options);
console.log('Created MediaRecorder', this.mediaRecorder, 'with options', options); console.log('Created MediaRecorder', this.mediaRecorder, 'with options', options);
this.getId('swapCameraButton').className = 'hidden'; this.getId('swapCameraButton').className = 'hidden';
@@ -3302,17 +3318,24 @@ class RoomClient {
this.event(_EVENTS.startRec); this.event(_EVENTS.startRec);
this.sound('recStart'); this.sound('recStart');
} else { } else {
// on desktop devices recording screen/window... + audio // on desktop devices recording screen/window... + all audio tracks
const constraints = { video: true }; const constraints = { video: true };
navigator.mediaDevices navigator.mediaDevices
.getDisplayMedia(constraints) .getDisplayMedia(constraints)
.then((screenStream) => { .then((screenStream) => {
this.recScreenStream = this.getNewStream(screenStream, this.localAudioStream); console.log('INIT SCREEN - WINDOW RECORDING', {
screenStream: screenStream,
localAudioStream: this.localAudioStream,
localVideoStream: this.localVideoStream,
audioTracks: audioTracks,
});
this.recScreenStream = new MediaStream([...screenStream.getTracks(), ...audioTracks]);
this.mediaRecorder = new MediaRecorder(this.recScreenStream, options); this.mediaRecorder = new MediaRecorder(this.recScreenStream, options);
console.log('Created MediaRecorder', this.mediaRecorder, 'with options', options); console.log('Created MediaRecorder', this.mediaRecorder, 'with options', options);
this._isRecording = true; this._isRecording = true;
this.handleMediaRecorder(); this.handleMediaRecorder();
this.event(_EVENTS.startRec); this.event(_EVENTS.startRec);
this.recordingAction('Start recording');
this.sound('recStart'); this.sound('recStart');
}) })
.catch((err) => { .catch((err) => {
@@ -3326,18 +3349,28 @@ class RoomClient {
} }
} }
getNewStream(videoStream, audioStream) { getAudioTracksFromAudioElements() {
let newStream = null; const audioElements = document.querySelectorAll('audio');
let videoStreamTrack = videoStream ? videoStream.getVideoTracks()[0] : undefined; const audioTracks = [];
let audioStreamTrack = audioStream ? audioStream.getAudioTracks()[0] : undefined; audioElements.forEach((audio) => {
if (videoStreamTrack && audioStreamTrack) { const audioTrack = audio.srcObject.getAudioTracks()[0];
newStream = new MediaStream([videoStreamTrack, audioStreamTrack]); if (audioTrack) {
} else if (videoStreamTrack) { audioTracks.push(audioTrack);
newStream = new MediaStream([videoStreamTrack]); }
} else if (audioStreamTrack) { });
newStream = new MediaStream([audioStreamTrack]); return audioTracks;
} }
return newStream;
getAudioStreamFromAudioElements() {
const audioElements = document.querySelectorAll('audio');
const audioStream = new MediaStream();
audioElements.forEach((audio) => {
const audioTrack = audio.srcObject.getAudioTracks()[0];
if (audioTrack) {
audioStream.addTrack(audioTrack);
}
});
return audioStream;
} }
handleMediaRecorder() { handleMediaRecorder() {
@@ -3417,6 +3450,7 @@ class RoomClient {
this._isRecording = false; this._isRecording = false;
this.mediaRecorder.pause(); this.mediaRecorder.pause();
this.event(_EVENTS.pauseRec); this.event(_EVENTS.pauseRec);
this.recordingAction('Pause recording');
} }
} }
@@ -3425,6 +3459,7 @@ class RoomClient {
this._isRecording = true; this._isRecording = true;
this.mediaRecorder.resume(); this.mediaRecorder.resume();
this.event(_EVENTS.resumeRec); this.event(_EVENTS.resumeRec);
this.recordingAction('Resume recording');
} }
} }
@@ -3439,10 +3474,24 @@ class RoomClient {
} }
if (this.isMobileDevice) this.getId('swapCameraButton').className = ''; if (this.isMobileDevice) this.getId('swapCameraButton').className = '';
this.event(_EVENTS.stopRec); this.event(_EVENTS.stopRec);
this.recordingAction('Stop recording');
this.sound('recStop'); this.sound('recStop');
} }
} }
recordingAction(action) {
if (!this.thereIsParticipants()) return;
this.socket.emit('recordingAction', {
peer_name: this.peer_name,
peer_id: this.peer_id,
action: action,
});
}
handleRecordingAction(data) {
this.userLog('warning', `${icons.recording} ${data.peer_name} ${data.action}`, 'top-end');
}
// #################################################### // ####################################################
// FILE SHARING // FILE SHARING
// #################################################### // ####################################################