
diff --git a/src/page/Meeting/index.tsx b/src/page/Meeting/index.tsx
index 0d72e1a..0c00895 100644
--- a/src/page/Meeting/index.tsx
+++ b/src/page/Meeting/index.tsx
@@ -20,8 +20,8 @@ import SharedFilesModel from '@/components/SharedFilesModel';
import StupWizard from '@/components/StupWizard';
import EquipmentManagement from '@/components/EquipmentManagement';
import UserVideo from '@/components/UserVideo';
-import { role } from '@/config/role';
-const { ipcRenderer } = require('electron');
+import { role } from '@/config/role';
+const { ipcRenderer } = require('electron');
import * as path from 'path';
const { confirm } = Modal;
@@ -549,46 +549,30 @@ const Meeting: React.FC = () => {
const reader = new FileReader() as any;
reader.onload = async () => {
try {
- const userDataPath = await ipcRenderer.invoke('get-user-data-path');
-
- // 获取当前日期并格式化
- const date = new Date();
- const year = date.getFullYear();
- const month = date.getMonth() + 1; // JavaScript月份从0开始
- const day = date.getDate();
- const hours = date.getHours();
- const minutes = date.getMinutes();
- const formattedDate = `${year}年${month}月${day}日${hours}时${minutes}分`;
-
-
- const setting = await JSON.parse(storage.getItem('setting') as string)
- const buffer = Buffer.from(reader.result);
- const mp4Path=`${setting.recordingFilesPath}会议录制_${state.roomName}_${state.channelId}_${formattedDate}_beforehanlder.mp4`;
- await fs.writeFile(mp4Path, buffer);
-
- // 获取应用程序安装路径
- const ffmpegPath = path.join(userDataPath, "ffmpeg.exe");
-
+ const userDataPath = await ipcRenderer.invoke('get-user-data-path');
+ // 获取当前日期并格式化
+ const date = new Date();
+ const year = date.getFullYear();
+ const month = date.getMonth() + 1; // JavaScript月份从0开始
+ const day = date.getDate();
+ const hours = date.getHours();
+ const minutes = date.getMinutes();
+ const formattedDate = `${year}年${month}月${day}日${hours}时${minutes}分`;
+ const setting = await JSON.parse(storage.getItem('setting') as string)
+ const buffer = Buffer.from(reader.result);
+ const mp4Path = `${setting.recordingFilesPath}会议录制_${state.roomName}_${state.channelId}_${formattedDate}_beforehanlder.mp4`;
+ await fs.writeFile(mp4Path, buffer);
+ // 获取应用程序安装路径
+ const ffmpegPath = path.join(userDataPath, "ffmpeg.exe");
const inputFilePath = mp4Path; // 输入文件路径
- const outputFilePath = mp4Path.replace('_beforehanlder',''); // 输出文件路径
- const command = `${ffmpegPath} -i "${inputFilePath}" -vcodec copy -acodec copy "${outputFilePath}"`;
-
- exec(command, (error:any, stdout:any, stderr:any) => {
+ const outputFilePath = mp4Path.replace('_beforehanlder', ''); // 输出文件路径
+ const command = `${ffmpegPath} -i "${inputFilePath}" -vcodec copy -acodec copy "${outputFilePath}"`;
+ exec(command, (error: any, _stdout: any, _stderr: any) => {
if (error) {
- console.error('Error executing ffmpeg command:', error);
return;
}
-
- // 删除输入文件
- fs.unlink(inputFilePath, (err:any) => {
- if (err) {
- console.error('Error deleting input file:', err);
- } else {
- console.log('Input file deleted successfully.');
- }
- });
-
-
+ // 删除输入文件
+ fs.unlink(inputFilePath);
confirm({
title: '提示',
icon:
,
@@ -606,15 +590,12 @@ const Meeting: React.FC = () => {
},
onCancel() {
}
- })
-
+ })
});
} catch (err) {
- console.error('处理录制时出错:', err);
- }
+ }
}
-
reader.readAsArrayBuffer(blob);
}
};
@@ -640,8 +621,6 @@ const Meeting: React.FC = () => {
});
const observerObject = new IntersectionObserver(async (entries: IntersectionObserverEntry[], _observer: IntersectionObserver) => {
entries.forEach(async (entry) => {
- console.log(entry.isIntersecting,entry.target.id);
-
if (entry.target.id !== user.uid) {
await agora.muteRemoteVideoStreamEx(Number(entry.target.id), !entry.isIntersecting)
}
@@ -659,7 +638,7 @@ const Meeting: React.FC = () => {
});
observer?.disconnect();
}
- }, [roomUserList, currentVideoId,footerList]);
+ }, [roomUserList, currentVideoId, footerList]);
// 声网初始化
const agoraInit = async () => {
@@ -751,11 +730,11 @@ const Meeting: React.FC = () => {
if (res.list.length) {
footerListTemplate[0][1].title = item.enableCamera ? '关闭视频' : '开启视频'
footerListTemplate[0][1].active = !item.enableCamera
- await agora.muteLocalVideoStream(r, item.enableMicr,item.enableCamera)
+ await agora.muteLocalVideoStream(r, item.enableMicr, item.enableCamera)
} else {
footerListTemplate[0][1].title = '开启视频'
footerListTemplate[0][1].active = true
- await agora.muteLocalVideoStream(r, item.enableMicr,false)
+ await agora.muteLocalVideoStream(r, item.enableMicr, false)
}
})
})
@@ -764,11 +743,11 @@ const Meeting: React.FC = () => {
if (res.ecordingList.length) {
footerListTemplate[0][0].title = item.enableMicr ? '静音' : '解除静音'
footerListTemplate[0][0].active = !item.enableMicr
- await agora.muteLocalAudioStream(r, item.enableMicr,item.enableCamera)
+ await agora.muteLocalAudioStream(r, item.enableMicr, item.enableCamera)
} else {
footerListTemplate[0][0].title = '解除静音'
footerListTemplate[0][0].active = true
- await agora.muteLocalAudioStream(r, false,item.enableCamera)
+ await agora.muteLocalAudioStream(r, false, item.enableCamera)
}
})
})
@@ -1069,70 +1048,70 @@ const Meeting: React.FC = () => {
}
})
break;
- case '录制':
- const setting = await JSON.parse(storage.getItem('setting') as string);
- try {
- await fs.access(setting.recordingFilesPath, fs.constants.F_OK);
- footerListTemplate[itemIndex][rowIndex].title = '录制中';
- footerListTemplate[itemIndex][rowIndex].active = true;
- setFooterList(footerListTemplate);
-
- window.electron.getSources().then(async (sources: any) => {
- const screenId = sources[0].id;
- const stream = await navigator.mediaDevices.getUserMedia({
- audio: {
- mandatory: {
- chromeMediaSource: 'desktop',
- chromeMediaSourceId: screenId,
- }
- } as any,
- video: {
- mandatory: {
- chromeMediaSource: 'desktop',
- chromeMediaSourceId: screenId,
- }
- } as any
- });
- // 获取所有音频输入设备
- const devices = await navigator.mediaDevices.enumerateDevices();
- const audioInputDevices = devices.filter(device => device.kind === 'audioinput' &&
- device.deviceId !== 'default' &&
- device.deviceId !== 'communications');
- // 使用Web Audio API来捕获系统声音和麦克风声音,将它们合并到同一个MediaStream中。
- const audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)();
- const systemSoundSource = audioCtx.createMediaStreamSource(stream);
- const systemSoundDestination = audioCtx.createMediaStreamDestination();
- systemSoundSource.connect(systemSoundDestination);
- // 录制所有音频输入设备
- audioInputDevices.forEach(async device => {
- const micStream = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: { exact: device.deviceId } } });
- setMediaStream(micStream);
- const micSoundSource = audioCtx.createMediaStreamSource(micStream);
- micSoundSource.connect(systemSoundDestination);
- })
- // 合并音频流与视频流
- const combinedSource = new MediaStream([...stream.getVideoTracks(), ...systemSoundDestination.stream.getAudioTracks()]);
- // 开始录制
- const mediaRecorder = new MediaRecorder(combinedSource, {
- mimeType: 'video/webm;codecs=vp9,opus',
- videoBitsPerSecond: 1.5e6,
- });
- setRecorder(mediaRecorder);
+ case '录制':
+ const setting = await JSON.parse(storage.getItem('setting') as string);
+ try {
+ await fs.access(setting.recordingFilesPath, fs.constants.F_OK);
+ footerListTemplate[itemIndex][rowIndex].title = '录制中';
+ footerListTemplate[itemIndex][rowIndex].active = true;
+ setFooterList(footerListTemplate);
+
+ window.electron.getSources().then(async (sources: any) => {
+ const screenId = sources[0].id;
+ const stream = await navigator.mediaDevices.getUserMedia({
+ audio: {
+ mandatory: {
+ chromeMediaSource: 'desktop',
+ chromeMediaSourceId: screenId,
+ }
+ } as any,
+ video: {
+ mandatory: {
+ chromeMediaSource: 'desktop',
+ chromeMediaSourceId: screenId,
+ }
+ } as any
});
- } catch (error: any) {
- if (error.code === 'ENOENT') {
- message.error({
- content:
文件夹不存在 {
- stupWizardRef.current.changeModal(3);
- }}>前往设置
- });
- return;
- } else {
- message.error(error);
- }
+ // 获取所有音频输入设备
+ const devices = await navigator.mediaDevices.enumerateDevices();
+ const audioInputDevices = devices.filter(device => device.kind === 'audioinput' &&
+ device.deviceId !== 'default' &&
+ device.deviceId !== 'communications');
+ // 使用Web Audio API来捕获系统声音和麦克风声音,将它们合并到同一个MediaStream中。
+ const audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)();
+ const systemSoundSource = audioCtx.createMediaStreamSource(stream);
+ const systemSoundDestination = audioCtx.createMediaStreamDestination();
+ systemSoundSource.connect(systemSoundDestination);
+ // 录制所有音频输入设备
+ audioInputDevices.forEach(async device => {
+ const micStream = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: { exact: device.deviceId } } });
+ setMediaStream(micStream);
+ const micSoundSource = audioCtx.createMediaStreamSource(micStream);
+ micSoundSource.connect(systemSoundDestination);
+ })
+ // 合并音频流与视频流
+ const combinedSource = new MediaStream([...stream.getVideoTracks(), ...systemSoundDestination.stream.getAudioTracks()]);
+ // 开始录制
+ const mediaRecorder = new MediaRecorder(combinedSource, {
+ mimeType: 'video/webm;codecs=vp9,opus',
+ videoBitsPerSecond: 1.5e6,
+ });
+ setRecorder(mediaRecorder);
+ });
+ } catch (error: any) {
+ if (error.code === 'ENOENT') {
+ message.error({
+ content:
文件夹不存在 {
+ stupWizardRef.current.changeModal(3);
+ }}>前往设置
+ });
+ return;
+ } else {
+ message.error(error);
}
-
- break;
+ }
+
+ break;
case '录制中':
footerListTemplate[itemIndex][rowIndex].title = '录制'
footerListTemplate[itemIndex][rowIndex].active = false
@@ -1338,7 +1317,7 @@ const Meeting: React.FC = () => {
}
})
}
-
+
// 开关麦克风
const postOpenMicrApi = async (enableMicr: boolean, uid: string, isAll: boolean, isMessage: boolean = false): Promise
=> {
diff --git a/src/utils/package/agora.ts b/src/utils/package/agora.ts
index 0e5c8fb..f49bb29 100644
--- a/src/utils/package/agora.ts
+++ b/src/utils/package/agora.ts
@@ -321,7 +321,7 @@ export const agora = {
rtcEngine.enableLoopbackRecording(false)
},
// 取消或恢复发布本地音频流
- muteLocalAudioStream: async (data: any, publishMicrophoneTrack: boolean,publishCameraTrack:boolean) => {
+ muteLocalAudioStream: async (data: any, publishMicrophoneTrack: boolean, publishCameraTrack: boolean) => {
// await rtcEngine.muteLocalAudioStream(mute)
await rtcEngine.updateChannelMediaOptions({
clientRoleType: data ? ClientRoleType.ClientRoleBroadcaster : ClientRoleType.ClientRoleAudience, //用户角色 ClientRoleBroadcaster 主播 ClientRoleAudience 观众
@@ -333,7 +333,7 @@ export const agora = {
})
},
// 取消或恢复发布本地视频流
- muteLocalVideoStream: async (data: any, publishMicrophoneTrack: boolean,publishCameraTrack:boolean) => {
+ muteLocalVideoStream: async (data: any, publishMicrophoneTrack: boolean, publishCameraTrack: boolean) => {
// await rtcEngine.muteLocalVideoStream(mute)
await rtcEngine.updateChannelMediaOptions({
clientRoleType: data ? ClientRoleType.ClientRoleBroadcaster : ClientRoleType.ClientRoleAudience, //用户角色 ClientRoleBroadcaster 主播 ClientRoleAudience 观众