[mirotalksfu] - #33 allow recording participants audio
هذا الالتزام موجود في:
@@ -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
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم