修复录屏麦克风问题

This commit is contained in:
youngq 2024-09-21 01:34:53 +08:00
parent 27d3a59438
commit 1ecec388ce
1 changed files with 98 additions and 47 deletions

View File

@ -174,6 +174,7 @@ const Meeting: React.FC = () => {
}
});
const [isVideoFullScreen, setIsVideoFullScreen] = useState<boolean>(false)
const [observer, setObserver] = useState<IntersectionObserver>()
let userInfo = JSON.parse(storage.getItem('user') as string)
const msgTips = '您不是管理员或发言人,无法开启此功能!'
useEffect(() => {
@ -583,6 +584,33 @@ const Meeting: React.FC = () => {
return () => clearTimeout(timer);
}, [isClicked]);
useEffect(() => {
const elements = document.querySelectorAll('.intersectionObserver-view');
if (elements.length && currentVideoId) {
elements.forEach(element => {
observer?.unobserve(element);
});
const observerObject = new IntersectionObserver(async (entries: IntersectionObserverEntry[], _observer: IntersectionObserver) => {
entries.forEach(async (entry) => {
if (entry.target.id !== user.uid) {
await agora.muteRemoteVideoStreamEx(Number(entry.target.id), !entry.isIntersecting)
}
});
await agora.muteRemoteVideoStreamEx(Number(currentVideoId), false)
}, { threshold: 0, root: document.getElementById('videoView') });
setObserver(observerObject)
elements.forEach(element => {
observerObject.observe(element);
});
}
return () => {
elements.forEach(element => {
observer?.unobserve(element);
});
observer?.disconnect();
}
}, [roomUserList, currentVideoId]);
// 声网初始化
const agoraInit = async () => {
await agora.init(true)
@ -990,52 +1018,75 @@ 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((sources: any) => {
const screenId = sources[0].id;
navigator.mediaDevices.getUserMedia({
audio: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: screenId,
}
} as any,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: screenId,
}
} as any
}).then(async (steam) => {
try {
const audioTracks = await navigator.mediaDevices
.getUserMedia({ audio: true, video: false })
.then(audioStream => audioStream.getAudioTracks()[0]);
steam.addTrack(audioTracks);
} catch (error) {
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,
}
setMediaStream(steam)
setRecorder(new MediaRecorder(steam))
})
},
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: screenId,
}
}
});
// 获取所有音频输入设备
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.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 } }});
const micSoundSource = audioCtx.createMediaStreamSource(micStream);
micSoundSource.connect(systemSoundDestination);
})
} catch (error: any) {
if (error.code === 'ENOENT') {
message.error({
content: <div> <span style={{ color: '#606fc7', cursor: 'pointer' }} onClick={() => {
stupWizardRef.current.changeModal(3)
}}></span></div>
})
return
} else {
message.error(error)
}
// 合并音频流与视频流
const combinedSource = new MediaStream([...stream.getVideoTracks(), ...systemSoundDestination.stream.getAudioTracks()]);
// 开始录制
const recorder = new MediaRecorder(combinedSource, {
mimeType: 'video/webm;codecs=vp9,opus',
videoBitsPerSecond: 1.5e6,
});
setMediaStream(combinedSource);
setRecorder(recorder);
});
} catch (error: any) {
if (error.code === 'ENOENT') {
message.error({
content: <div> <span style={{ color: '#606fc7', cursor: 'pointer' }} onClick={() => {
stupWizardRef.current.changeModal(3);
}}></span></div>
});
return;
} else {
message.error(error);
}
}
break;
case '录制中':
footerListTemplate[itemIndex][rowIndex].title = '录制'
@ -1510,7 +1561,7 @@ const Meeting: React.FC = () => {
{roomUserList.map((item: any, index: number) => {
return (index <= 19 && item.isRoom && item.isAdmin ? <div
id={item.uid}
className={`${styles.meetingContentSwiperCard}`}
className={`${styles.meetingContentSwiperCard} intersectionObserver-view`}
key={index}
onClick={() => {
if (String(isShare) === item.screenShareId) {