From 1da838f568338ed126caa617d5b8e3aba69e5952 Mon Sep 17 00:00:00 2001 From: yj <1336058017@qq.com> Date: Fri, 27 Sep 2024 15:36:50 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E5=BD=95=E5=88=B6=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=9B=9E=E6=98=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.js | 56 --------------------------- src/page/Meeting/index.tsx | 79 ++++++++++++-------------------------- 2 files changed, 25 insertions(+), 110 deletions(-) diff --git a/main.js b/main.js index 5a92cf7..4609203 100644 --- a/main.js +++ b/main.js @@ -12,7 +12,6 @@ const { } = require('electron'); const path = require('node:path') const fs = require('fs'); -const https = require('https'); const Registry = require('winreg'); const { autoUpdater, CancellationToken } = require('electron-updater'); const cancellationToken = new CancellationToken() @@ -300,24 +299,6 @@ app.on('ready', () => { }) }); }); - // 监听渲染进程请求应用数据目录 - ipcMain.handle('get-user-data-path', () => { - return app.getPath('userData'); - }); - // 用户数据目录路径 - const userDataPath = app.getPath('userData'); // 全局变量 - console.log('User Data Path:', userDataPath); - // 检查并下载 ffmpeg - checkAndDownloadFFmpeg(userDataPath) - .then(() => { - console.log('FFmpeg is ready for use.'); - // 在这里执行任何依赖于 ffmpeg 的操作 - }) - .catch(error => { - console.error('Failed to ensure ffmpeg is available:', error); - app.quit(); - }); - } }); // 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写 @@ -386,40 +367,3 @@ function cancleDownloadUpdate() { function quitAndInstall() { autoUpdater.quitAndInstall(); } - -// 下载文件 -function downloadFile(url, dest) { - return new Promise((resolve, reject) => { - const file = fs.createWriteStream(dest); - https.get(url, function (response) { - response.pipe(file); - file.on('finish', function () { - file.close(resolve); - }); - }).on('error', function (err) { - fs.unlink(dest, () => reject(err)); - }); - }); -} - -// 检查并下载ffmpeg -function checkAndDownloadFFmpeg(appPath) { - const ffmpegPath = path.join(appPath, 'ffmpeg.exe'); - return new Promise((resolve, reject) => { - if (!fs.existsSync(ffmpegPath)) { - console.log(`ffmpeg.exe not found at ${ffmpegPath}, downloading...`); - downloadFile('https://meeting-api.23544.com/meeting/update/ffmpeg.exe', ffmpegPath) - .then(() => { - console.log('ffmpeg.exe downloaded successfully.'); - resolve(); - }) - .catch(error => { - console.error('Error downloading ffmpeg.exe:', error); - reject(error); - }); - } else { - console.log(`ffmpeg.exe found at ${ffmpegPath}.`); - resolve(); - } - }); -} \ No newline at end of file diff --git a/src/page/Meeting/index.tsx b/src/page/Meeting/index.tsx index dd3dfe0..4af1721 100644 --- a/src/page/Meeting/index.tsx +++ b/src/page/Meeting/index.tsx @@ -21,8 +21,7 @@ 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 * as path from 'path'; +import { fixWebmDuration } from "webm-duration-fix-buffer"; const { confirm } = Modal; const { exec } = require('child_process'); const fs = require('fs').promises; @@ -563,60 +562,32 @@ const Meeting: React.FC = () => { useEffect(() => { if (recorder) { recorder.start(); - recorder.ondataavailable = (event: any) => { - const blob = new Blob([event.data], { - type: 'video/webm', - }); + recorder.ondataavailable = async (event: any) => { + const blob = await fixWebmDuration(event.data); 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 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) => { - if (error) { - return; + const setting = await JSON.parse(storage.getItem('setting') as string) + const buffer = Buffer.from(reader.result); + await fs.writeFile(`${setting.recordingFilesPath}会议录制_${state.roomName}_${state.channelId}_${+new Date()}.webm`, buffer, {}); + confirm({ + title: '提示', + icon: , + content: `录制成功!文件已保存至:${setting.recordingFilesPath}`, + centered: true, + okText: '打开文件夹', + cancelText: '关闭', + async onOk() { + await fs.access(setting.recordingFilesPath, fs.constants.F_OK); + if (process.platform === 'win32') { + exec(`explorer "${setting.recordingFilesPath}"`); + } else if (process.platform === 'darwin') { + exec(`open "${setting.recordingFilesPath}"`); } - // 删除输入文件 - fs.unlink(inputFilePath); - confirm({ - title: '提示', - icon: , - content: `录制成功!文件已保存至:${setting.recordingFilesPath}`, - centered: true, - okText: '打开文件夹', - cancelText: '关闭', - async onOk() { - await fs.access(setting.recordingFilesPath, fs.constants.F_OK); - if (process.platform === 'win32') { - exec(`explorer "${setting.recordingFilesPath}"`); - } else if (process.platform === 'darwin') { - exec(`open "${setting.recordingFilesPath}"`); - } - }, - onCancel() { - } - }) - }); - } catch (err) { - - } - } + }, + onCancel() { + } + }) + }; reader.readAsArrayBuffer(blob); } }; @@ -748,7 +719,7 @@ const Meeting: React.FC = () => { setCurrentEffective(0) break; default: - setCurrentEffective(storage.getItem('reconnect') =='true'? 4 : 0) + setCurrentEffective(storage.getItem('reconnect') === 'true' ? 4 : 0) break; } } From 72a42c8836a32d6f64c48515184007f3a757b7eb Mon Sep 17 00:00:00 2001 From: yj <1336058017@qq.com> Date: Fri, 27 Sep 2024 15:57:57 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=90=8D=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/Meeting/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/page/Meeting/index.tsx b/src/page/Meeting/index.tsx index 5316514..efff682 100644 --- a/src/page/Meeting/index.tsx +++ b/src/page/Meeting/index.tsx @@ -568,7 +568,8 @@ const Meeting: React.FC = () => { reader.onload = async () => { const setting = await JSON.parse(storage.getItem('setting') as string) const buffer = Buffer.from(reader.result); - await fs.writeFile(`${setting.recordingFilesPath}会议录制_${state.roomName}_${state.channelId}_${+new Date()}.webm`, buffer, {}); + const mp4Path = `${setting.recordingFilesPath}会议录制_${state.roomName}_${state.channelId}_${dayjs().format('YYYY年MM月DD日HH时mm分')}.webm`; + await fs.writeFile(mp4Path, buffer, {}); confirm({ title: '提示', icon: , From 932d8e82856082a58321bcfab683bded45be4070 Mon Sep 17 00:00:00 2001 From: yj <1336058017@qq.com> Date: Fri, 27 Sep 2024 16:11:07 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/Meeting/index.tsx | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/page/Meeting/index.tsx b/src/page/Meeting/index.tsx index efff682..27c8ee6 100644 --- a/src/page/Meeting/index.tsx +++ b/src/page/Meeting/index.tsx @@ -160,7 +160,7 @@ const Meeting: React.FC = () => { const [noViewChatList, setNoViewChatList] = useState(0) const [currentLookUserAccount, setCurrentLookUserAccount] = useState('') const [recorder, setRecorder] = useState('') - const [mediaStream, setMediaStream] = useState('') + const [_mediaStream, setMediaStream] = useState('') const [isShare, setIsShare] = useState(null) const [isSharePopConfirm, setIsSharePopConfirm] = useState(false) const [isShareUser, setIsShareUser] = useState(null) @@ -570,6 +570,8 @@ const Meeting: React.FC = () => { const buffer = Buffer.from(reader.result); const mp4Path = `${setting.recordingFilesPath}会议录制_${state.roomName}_${state.channelId}_${dayjs().format('YYYY年MM月DD日HH时mm分')}.webm`; await fs.writeFile(mp4Path, buffer, {}); + setRecorder('') + setMediaStream('') confirm({ title: '提示', icon: , @@ -1071,7 +1073,6 @@ const Meeting: React.FC = () => { 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({ @@ -1167,16 +1168,20 @@ const Meeting: React.FC = () => { } // 停止录制 const stopRecorderMedia = async (): Promise => { - if (recorder) { - await recorder.stop(); - } - if (mediaStream) { - await mediaStream.getTracks().forEach((track: any) => { - track.stop() - }); - } - setRecorder('') - setMediaStream('') + setRecorder((res: any) => { + if (res) { + res.stop(); + } + return res + }) + setMediaStream((res: any) => { + if (res) { + res.getTracks().forEach((track: any) => { + track.stop() + }); + } + return res + }) } // 退出房间 const leaveChannel = async (bool: boolean = true): Promise => { From 88c19a327daed4c3a4d12c1d1d58dec5b5598bd0 Mon Sep 17 00:00:00 2001 From: yj <1336058017@qq.com> Date: Fri, 27 Sep 2024 16:41:42 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/Meeting/index.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/page/Meeting/index.tsx b/src/page/Meeting/index.tsx index 27c8ee6..2e66fb9 100644 --- a/src/page/Meeting/index.tsx +++ b/src/page/Meeting/index.tsx @@ -1193,11 +1193,13 @@ const Meeting: React.FC = () => { } catch (error) { } await agora.leaveChannel() - if (user.isAnonymous) { - storage.setItem('userLogin', false) - } else { - navigate('/home/index') - } + setTimeout(() => { + if (user.isAnonymous) { + storage.setItem('userLogin', false) + } else { + navigate('/home/index') + } + }, 0) } // 分享屏幕 const clickSharedScreen = async (): Promise => {