Compare commits
No commits in common. "75ff6089adec67d3e744753ba620cf09f18616d8" and "ab8dc3dc8124f93f2e84cf6af5050ce73647c595" have entirely different histories.
75ff6089ad
...
ab8dc3dc81
56
main.js
56
main.js
|
|
@ -12,6 +12,7 @@ const {
|
||||||
} = require('electron');
|
} = require('electron');
|
||||||
const path = require('node:path')
|
const path = require('node:path')
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const https = require('https');
|
||||||
const Registry = require('winreg');
|
const Registry = require('winreg');
|
||||||
const { autoUpdater, CancellationToken } = require('electron-updater');
|
const { autoUpdater, CancellationToken } = require('electron-updater');
|
||||||
const cancellationToken = new CancellationToken()
|
const cancellationToken = new CancellationToken()
|
||||||
|
|
@ -299,6 +300,24 @@ 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事件触发后的操作自行编写
|
// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
|
||||||
|
|
@ -367,3 +386,40 @@ function cancleDownloadUpdate() {
|
||||||
function quitAndInstall() {
|
function quitAndInstall() {
|
||||||
autoUpdater.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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -21,7 +21,8 @@ import StupWizard from '@/components/StupWizard';
|
||||||
import EquipmentManagement from '@/components/EquipmentManagement';
|
import EquipmentManagement from '@/components/EquipmentManagement';
|
||||||
import UserVideo from '@/components/UserVideo';
|
import UserVideo from '@/components/UserVideo';
|
||||||
import { role } from '@/config/role';
|
import { role } from '@/config/role';
|
||||||
import { fixWebmDuration } from "webm-duration-fix-buffer";
|
const { ipcRenderer } = require('electron');
|
||||||
|
import * as path from 'path';
|
||||||
const { confirm } = Modal;
|
const { confirm } = Modal;
|
||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
const fs = require('fs').promises;
|
const fs = require('fs').promises;
|
||||||
|
|
@ -160,7 +161,7 @@ const Meeting: React.FC = () => {
|
||||||
const [noViewChatList, setNoViewChatList] = useState(0)
|
const [noViewChatList, setNoViewChatList] = useState(0)
|
||||||
const [currentLookUserAccount, setCurrentLookUserAccount] = useState<any>('')
|
const [currentLookUserAccount, setCurrentLookUserAccount] = useState<any>('')
|
||||||
const [recorder, setRecorder] = useState<any>('')
|
const [recorder, setRecorder] = useState<any>('')
|
||||||
const [_mediaStream, setMediaStream] = useState<any>('')
|
const [mediaStream, setMediaStream] = useState<any>('')
|
||||||
const [isShare, setIsShare] = useState<any>(null)
|
const [isShare, setIsShare] = useState<any>(null)
|
||||||
const [isSharePopConfirm, setIsSharePopConfirm] = useState<any>(false)
|
const [isSharePopConfirm, setIsSharePopConfirm] = useState<any>(false)
|
||||||
const [isShareUser, setIsShareUser] = useState<any>(null)
|
const [isShareUser, setIsShareUser] = useState<any>(null)
|
||||||
|
|
@ -562,16 +563,37 @@ const Meeting: React.FC = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (recorder) {
|
if (recorder) {
|
||||||
recorder.start();
|
recorder.start();
|
||||||
recorder.ondataavailable = async (event: any) => {
|
recorder.ondataavailable = (event: any) => {
|
||||||
const blob = await fixWebmDuration(event.data);
|
const blob = new Blob([event.data], {
|
||||||
|
type: 'video/webm',
|
||||||
|
});
|
||||||
const reader = new FileReader() as any;
|
const reader = new FileReader() as any;
|
||||||
reader.onload = async () => {
|
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 setting = await JSON.parse(storage.getItem('setting') as string)
|
||||||
const buffer = Buffer.from(reader.result);
|
const buffer = Buffer.from(reader.result);
|
||||||
const mp4Path = `${setting.recordingFilesPath}会议录制_${state.roomName}_${state.channelId}_${dayjs().format('YYYY年MM月DD日HH时mm分')}.webm`;
|
const mp4Path = `${setting.recordingFilesPath}会议录制_${state.roomName}_${state.channelId}_${formattedDate}_beforehanlder.mp4`;
|
||||||
await fs.writeFile(mp4Path, buffer, {});
|
await fs.writeFile(mp4Path, buffer);
|
||||||
setRecorder('')
|
// 获取应用程序安装路径
|
||||||
setMediaStream('')
|
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;
|
||||||
|
}
|
||||||
|
// 删除输入文件
|
||||||
|
fs.unlink(inputFilePath);
|
||||||
confirm({
|
confirm({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
icon: <ExclamationCircleFilled />,
|
icon: <ExclamationCircleFilled />,
|
||||||
|
|
@ -590,7 +612,11 @@ const Meeting: React.FC = () => {
|
||||||
onCancel() {
|
onCancel() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
});
|
||||||
|
} catch (err) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
reader.readAsArrayBuffer(blob);
|
reader.readAsArrayBuffer(blob);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -722,7 +748,7 @@ const Meeting: React.FC = () => {
|
||||||
setCurrentEffective(0)
|
setCurrentEffective(0)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
setCurrentEffective(storage.getItem('reconnect') === 'true' ? 4 : 0)
|
setCurrentEffective(storage.getItem('reconnect') =='true'? 4 : 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1073,6 +1099,7 @@ const Meeting: React.FC = () => {
|
||||||
footerListTemplate[itemIndex][rowIndex].title = '录制中';
|
footerListTemplate[itemIndex][rowIndex].title = '录制中';
|
||||||
footerListTemplate[itemIndex][rowIndex].active = true;
|
footerListTemplate[itemIndex][rowIndex].active = true;
|
||||||
setFooterList(footerListTemplate);
|
setFooterList(footerListTemplate);
|
||||||
|
|
||||||
window.electron.getSources().then(async (sources: any) => {
|
window.electron.getSources().then(async (sources: any) => {
|
||||||
const screenId = sources[0].id;
|
const screenId = sources[0].id;
|
||||||
const stream = await navigator.mediaDevices.getUserMedia({
|
const stream = await navigator.mediaDevices.getUserMedia({
|
||||||
|
|
@ -1168,20 +1195,16 @@ const Meeting: React.FC = () => {
|
||||||
}
|
}
|
||||||
// 停止录制
|
// 停止录制
|
||||||
const stopRecorderMedia = async (): Promise<void> => {
|
const stopRecorderMedia = async (): Promise<void> => {
|
||||||
setRecorder((res: any) => {
|
if (recorder) {
|
||||||
if (res) {
|
await recorder.stop();
|
||||||
res.stop();
|
|
||||||
}
|
}
|
||||||
return res
|
if (mediaStream) {
|
||||||
})
|
await mediaStream.getTracks().forEach((track: any) => {
|
||||||
setMediaStream((res: any) => {
|
|
||||||
if (res) {
|
|
||||||
res.getTracks().forEach((track: any) => {
|
|
||||||
track.stop()
|
track.stop()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return res
|
setRecorder('')
|
||||||
})
|
setMediaStream('')
|
||||||
}
|
}
|
||||||
// 退出房间
|
// 退出房间
|
||||||
const leaveChannel = async (bool: boolean = true): Promise<void> => {
|
const leaveChannel = async (bool: boolean = true): Promise<void> => {
|
||||||
|
|
@ -1193,13 +1216,11 @@ const Meeting: React.FC = () => {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
}
|
}
|
||||||
await agora.leaveChannel()
|
await agora.leaveChannel()
|
||||||
setTimeout(() => {
|
|
||||||
if (user.isAnonymous) {
|
if (user.isAnonymous) {
|
||||||
storage.setItem('userLogin', false)
|
storage.setItem('userLogin', false)
|
||||||
} else {
|
} else {
|
||||||
navigate('/home/index')
|
navigate('/home/index')
|
||||||
}
|
}
|
||||||
}, 0)
|
|
||||||
}
|
}
|
||||||
// 分享屏幕
|
// 分享屏幕
|
||||||
const clickSharedScreen = async (): Promise<void> => {
|
const clickSharedScreen = async (): Promise<void> => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue