This commit is contained in:
yj 2024-07-26 11:03:48 +08:00
parent 51582be3e0
commit a275885115
4 changed files with 375 additions and 139 deletions

View File

@ -76,7 +76,7 @@
border: 1px #292E33 solid;
position: relative;
>video {
>div {
width: 100%;
height: 100%;
z-index: 1;
@ -96,4 +96,117 @@
color: white;
}
}
}
.audioComponents {
>div {
padding-bottom: 20px;
border-bottom: 1px solid #292E33;
margin-bottom: 20px;
&:last-child {
padding-bottom: 0px;
margin-bottom: 0px;
border: none;
}
}
.audioComponentsSelect {
display: flex;
align-items: center;
margin-bottom: 10px;
>span {
color: #878787;
flex-shrink: 0;
}
>div {
color: #5575F2;
flex-shrink: 0;
cursor: pointer;
}
}
.audioComponentsVolume {
display: flex;
align-items: center;
margin-bottom: 10px;
>img {
margin-right: 20px;
height: 26px;
}
>div {
height: 40px;
position: relative;
>img {
height: 100%;
}
>div {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 0%;
overflow: hidden;
>img {
height: 100%;
}
}
}
}
.audioComponentsSlider {
display: flex;
align-items: center;
margin-bottom: 10px;
>span {
color: #878787;
}
}
}
.recordingComponents {
>span {
color: #bfbfbf;
font-size: 16px;
}
>div {
display: flex;
align-items: center;
margin-top: 10px;
>span {
color: #878787;
white-space: nowrap;
}
}
}
.fileComponents {
>span {
color: #bfbfbf;
font-size: 16px;
}
>div {
display: flex;
align-items: center;
margin-top: 10px;
>span {
color: #878787;
white-space: nowrap;
}
}
}

View File

@ -1,17 +1,16 @@
import styles from '@/components/StupWizard/index.module.scss'
import ImageUrl from '@/utils/package/ImageUrl';
import { Button, Empty, message, Modal, Select, Slider } from 'antd';
import { Button, Checkbox, Empty, Input, message, Modal, Select, Slider } from 'antd';
import { useState, useImperativeHandle, forwardRef, useEffect } from "react";
import agora from '@/utils/package/agora'
import { CloseOutlined, LoadingOutlined } from '@ant-design/icons';
import { storage } from '@/utils';
let userInfo = JSON.parse(storage.getItem('user') as string)
const StupWizard = forwardRef((props: any, ref: any) => {
useImperativeHandle(ref, () => ({
changeModal: () => {
agora.init()
setIsStupWizard(true)
// getAudioMediaList(true)
// agora.startPlaybackDeviceTest()
// agora.setPlaybackDeviceVolume(100)
}
}))
const [list, setList] = useState([
@ -41,25 +40,6 @@ const StupWizard = forwardRef((props: any, ref: any) => {
}
])
const [isStupWizard, setIsStupWizard] = useState(false);
const [audioDeviceManager, setAudioDeviceManager] = useState<any>({
currentDevices: [],
currentDevice: {},
currentVolume: 0,
});
// agora.startRecordingDeviceTest(200)
const getAudioMediaList = (bool: boolean): void => {
const { currentDevices, currentVolume, currentDevice } = agora.getAudioMediaList(bool);
setAudioDeviceManager({
currentDevices: currentDevices.map((row: any) => {
return {
value: row.deviceId,
label: row.deviceName
}
}),
currentDevice: currentDevice.deviceId,
currentVolume,
})
}
return (
<>
<Modal
@ -76,13 +56,12 @@ const StupWizard = forwardRef((props: any, ref: any) => {
{list.map((row: any, index: number) => {
return (
<div key={index} className={`${row.active ? styles.active : ''}`} onClick={async () => {
const newList = [...list]
newList.forEach(item => item.active = false)
const newList = [...list];
newList.forEach(item => item.active = false);
newList[index].active = true;
if (newList[index].title !== '视频') {
await agora.stopVideoDevice('videoPreview')
}
setList(newList)
agora.stopPlaybackDeviceTest()
agora.stopRecordingDeviceTest()
}}>
<img src={row.active ? row.iconActive : row.icon} alt="" />
<span>{row.title}</span>
@ -99,7 +78,7 @@ const StupWizard = forwardRef((props: any, ref: any) => {
cursor: 'pointer'
}}
onClick={() => {
agora.stopVideoDevice('videoPreview')
agora.release()
setIsStupWizard(false)
}}
/>
@ -135,8 +114,7 @@ const VideoComponents = () => {
item: item ? item : null,
})
if (item) {
await agora.stopVideoDevice('videoPreview')
agora.startPreview('videoPreview', item)
agora.startPreview('videoPreview', Number(userInfo.account))
}
})
}
@ -148,14 +126,15 @@ const VideoComponents = () => {
{
videoDeviceManager.item ?
<div>
<video id='videoPreview'></video>
<LoadingOutlined style={{
position: 'absolute',
color: 'white',
right: '50%',
fontSize: '30px',
top: '50%',
}} />
<div id='videoPreview'>
<LoadingOutlined style={{
position: 'absolute',
color: 'white',
right: '50%',
fontSize: '30px',
top: '50%',
}} />
</div>
</div> :
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}><Empty description={'未检测到摄像头'} /></div>
}
@ -170,7 +149,6 @@ const VideoComponents = () => {
item: e
})
agora.setVideoDeviceManager(e)
agora.startPreview('videoPreview', e)
}} />;
</div>
</div>
@ -179,31 +157,214 @@ const VideoComponents = () => {
)
}
const AudioComponents = () => {
const [audioDeviceManager, setAudioDeviceManager] = useState<any>({
playBackList: [],
ecordingList: [],
playBackItem: null,
ecordingItem: null,
playBackVolume: 127,
playBackActive: false,
ecordingActive: false,
ecordingVolume: 0,
});
useEffect(() => {
getAudioMediaList()
agora.registerEventHandler({
onAudioVolumeIndication: (percentage: number) => {
const dom = document.getElementById('deviceTest') as any;
if (dom) {
dom.style.width = `${percentage}%`
}
}
})
}, []);
const getAudioMediaList = (): void => {
const { playBackList, ecordingList, playBackItem, ecordingItem, ecordingVolume } = agora.getAudioMediaList();
setAudioDeviceManager({
...audioDeviceManager,
playBackList: playBackList.map((row: any) => {
return {
value: row.deviceId,
label: row.deviceName
}
}),
ecordingList: ecordingList.map((row: any) => {
return {
value: row.deviceId,
label: row.deviceName
}
}),
playBackItem: playBackItem.deviceId ? playBackItem.deviceId : null,
ecordingItem: ecordingItem.deviceId ? ecordingItem.deviceId : null,
ecordingVolume,
})
}
return (
<>
<div>
<span></span>
<div></div>
<div className={styles.audioComponents}>
<div>
<div className={styles.audioComponentsSelect}>
<span></span>
<Select
placeholder={audioDeviceManager.ecordingList.length ? '请选择设备' : '未检测到麦克风'}
options={audioDeviceManager.ecordingList} style={{ flexGrow: 1 }}
value={audioDeviceManager.ecordingItem} onChange={(e) => {
setAudioDeviceManager({
...audioDeviceManager,
ecordingItem: e
})
agora.setRecordingDevice(e)
}} />;
{audioDeviceManager.ecordingActive ? <div onClick={() => {
agora.stopRecordingDeviceTest()
setAudioDeviceManager({
...audioDeviceManager,
playBackActive: false,
ecordingActive: false,
})
}}></div> : <div onClick={() => {
agora.stopPlaybackDeviceTest()
agora.startRecordingDeviceTest(100)
setAudioDeviceManager({
...audioDeviceManager,
playBackActive: false,
ecordingActive: true,
})
}}></div>}
</div>
{audioDeviceManager.ecordingActive ? <div className={styles.audioComponentsVolume}>
<img src={ImageUrl.icon36} alt="" />
<div>
<img src={ImageUrl.icon34} alt="" />
<div id='deviceTest'>
<img src={ImageUrl.icon35} alt="" />
</div>
</div>
</div> : null}
<div className={styles.audioComponentsSlider}>
<span></span>
<Slider value={audioDeviceManager.ecordingVolume} style={{ flexGrow: 1 }} max={255} onChange={(e) => {
agora.setRecordingDeviceVolume(e)
setAudioDeviceManager({
...audioDeviceManager,
ecordingVolume: e,
})
}} disabled={!audioDeviceManager.ecordingItem} />
</div>
<div>
<Checkbox onChange={() => {
}}></Checkbox>
</div>
</div>
<div>
<div className={styles.audioComponentsSelect}>
<span></span>
<Select
placeholder={audioDeviceManager.playBackList.length ? '请选择设备' : '未检测到麦克风'}
options={audioDeviceManager.playBackList} style={{ flexGrow: 1 }}
value={audioDeviceManager.playBackItem} onChange={(e) => {
setAudioDeviceManager({
...audioDeviceManager,
playBackItem: e
})
agora.setPlaybackDevice(e)
}} />;
{audioDeviceManager.playBackActive ? <div onClick={() => {
agora.stopPlaybackDeviceTest()
setAudioDeviceManager({
...audioDeviceManager,
playBackActive: false,
ecordingActive: false,
})
}}></div> : <div onClick={() => {
agora.stopRecordingDeviceTest()
agora.startPlaybackDeviceTest()
setAudioDeviceManager({
...audioDeviceManager,
playBackActive: true,
ecordingActive: false,
})
}}></div>}
</div>
{audioDeviceManager.playBackActive ? <div className={styles.audioComponentsVolume}>
<img src={ImageUrl.icon36} alt="" />
<div>
<img src={ImageUrl.icon34} alt="" />
<div id='deviceTest'>
<img src={ImageUrl.icon35} alt="" />
</div>
</div>
</div> : null}
<div className={styles.audioComponentsSlider}>
<span></span>
<Slider value={audioDeviceManager.playBackVolume} style={{ flexGrow: 1 }} max={255} onChange={(e) => {
agora.setPlaybackDeviceVolume(e)
setAudioDeviceManager({
...audioDeviceManager,
playBackVolume: e,
})
}} disabled={!audioDeviceManager.playBackItem} />
</div>
</div>
</div>
</div>
</>
)
}
const RecordingComponents = () => {
const [filePath, setFilePath] = useState('')
return (
<>
<div>
<span></span>
<div></div>
<div className={styles.recordingComponents}>
<span></span>
<div>
<span></span>
<Input
placeholder="请填入文件路径"
style={{ margin: '0 14px', flexGrow: 1 }}
value={filePath}
onChange={(e) => {
setFilePath(e.target.value)
}}
/>
<Button type="primary" onClick={() => { }} style={{ backgroundColor: '#31353A' }}></Button>
</div>
</div>
</div>
</>
)
}
const FileComponents = () => {
const [filePath, setFilePath] = useState('')
return (
<>
<div>
<span></span>
<div></div>
<div className={styles.fileComponents}>
<span></span>
<div>
<span></span>
<Input
placeholder="请填入保存目录"
style={{ margin: '0 14px', flexGrow: 1 }}
value={filePath}
onChange={(e) => {
setFilePath(e.target.value)
}}
/>
<Button type="primary" onClick={() => { }} style={{ backgroundColor: '#31353A' }}></Button>
</div>
<div>
<Checkbox onChange={() => {
}}></Checkbox>
</div>
</div>
</div>
</>
)

View File

@ -11,6 +11,7 @@ import {
MediaRecorderContainerFormat,
MediaRecorderStreamType
} from "agora-electron-sdk";
import { GetRoomRtcToken } from "@/api/Home/Index";
const option: any = {
appId: 'dcfc466a6ecb4a1f972630065dfb1e75',
token: '',
@ -28,9 +29,10 @@ const agora = {
rtcEngine.initialize({
appId: option.appId,
});
// console.log(rtcEngine.getAudioDeviceManager().enumeratePlaybackDevices());
},
// 事件回调
registerEventHandler: ({ onJoinChannelSuccess, onUserJoined, onUserOffline }: any) => {
registerEventHandler: ({ onJoinChannelSuccess, onUserJoined, onUserOffline, onAudioVolumeIndication }: any) => {
rtcEngine.registerEventHandler({
// 监听本地用户加入频道事件
onJoinChannelSuccess: async (info: any, elapsed: any) => {
@ -57,13 +59,10 @@ const agora = {
// }
// },
// // 用户音量提示回调。
// onAudioVolumeIndication: (connection: any, speakers: any, speakerNumber: any, totalVolume: any,) => {
// const percentage = (totalVolume / 255) * 100
// const dom = document.getElementById('recordingDeviceTest') as any;
// if (dom) {
// dom.style.width = `${percentage}%`
// }
// }
onAudioVolumeIndication: async (connection: any, speakers: any, speakerNumber: any, totalVolume: any,) => {
const percentage = (totalVolume / 255) * 100
await onAudioVolumeIndication(percentage)
}
});
},
// 本地加入
@ -109,6 +108,10 @@ const agora = {
},
);
},
// 销毁
release: () => {
rtcEngine.release()
},
// 离开频道
leaveChannel: async () => {
await rtcEngine.leaveChannel({
@ -117,7 +120,7 @@ const agora = {
stopMicrophoneRecording: true,
})
agora.stopScreenCapture()
rtcEngine.release()
agora.release()
},
// 加入频道
joinChannel: () => {
@ -275,97 +278,36 @@ const agora = {
rtcEngine.getVideoDeviceManager().setDevice(deviceIdUTF8)
},
// 开启本地视频预览
startPreview: async (id: string, deviceId: string): Promise<boolean> => {
return new Promise((resolve, reject) => {
navigator.mediaDevices.getUserMedia({
video: {
deviceId: { exact: deviceId }, // 指定设备ID
},
audio: true,
}).then((stream) => {
let dom = document.getElementById(id) as any;
dom.srcObject = stream;
dom.play()
resolve(true)
}).catch((error) => {
console.log(error);
message.error('无法获取摄像头!');
resolve(true)
startPreview: async (id: string, uid: number): Promise<void> => {
rtcEngine.enableVideo();
rtcEngine.startPreview();
await GetRoomRtcToken(`${+new Date()}`).then(async (res) => {
await rtcEngine.joinChannel(res.data, `${+new Date()}`, uid, {
channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting,
clientRoleType: ClientRoleType.ClientRoleBroadcaster,
publishMicrophoneTrack: true,
publishCameraTrack: true,
autoSubscribeAudio: true,
autoSubscribeVideo: true,
});
rtcEngine.setupLocalVideo({
sourceType: VideoSourceType.VideoSourceCameraPrimary,
uid,
view: document.getElementById(id),
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
});
})
},
stopVideoDevice: async (id: string) => {
let dom = document.getElementById(id) as any;
if (dom && dom.srcObject) {
const tracks = dom.srcObject.getTracks();
tracks.forEach((track: any) => {
track.stop();
});
dom.srcObject = null;
// 获取输入输出设备列表
getAudioMediaList: () => {
return {
playBackList: rtcEngine.getAudioDeviceManager().enumeratePlaybackDevices(),
ecordingList: rtcEngine.getAudioDeviceManager().enumerateRecordingDevices(),
playBackItem: rtcEngine.getAudioDeviceManager().getPlaybackDefaultDevice(),
ecordingItem: rtcEngine.getAudioDeviceManager().getRecordingDefaultDevice(),
ecordingVolume: rtcEngine.getAudioDeviceManager().getRecordingDeviceVolume(),
}
},
// 停止音频设备回路测试
stopAudioDeviceLoopbackTest: () => {
rtcEngine.getAudioDeviceManager().stopAudioDeviceLoopbackTest()
rtcEngine.getAudioDeviceManager().stopRecordingDeviceTest()
let video = document.getElementById('startPreview') as any;
if (video.srcObject) {
const tracks = video.srcObject.getTracks();
tracks.forEach((track: any) => {
track.stop();
});
video.srcObject = null;
}
let audio = document.getElementById('startAudio') as any;
if (audio.srcObject) {
const tracks = audio.srcObject.getTracks();
tracks.forEach((track: any) => {
track.stop();
});
audio.srcObject = null;
}
},
// 启动音频采集设备测试
startRecordingDeviceTest: (indicationInterval: number) => {
rtcEngine.getAudioDeviceManager().startRecordingDeviceTest(indicationInterval)
navigator.mediaDevices.getUserMedia({ audio: true })
.then((stream) => {
let dom = document.getElementById('startAudio') as any;
dom.srcObject = stream;
dom.play()
})
.catch((error) => {
message.error('无法获取麦克风!');
});
},
// 获取音频设备列表
getAudioMediaList: (bool: boolean) => {
if (bool) {
return {
currentDevices: rtcEngine.getAudioDeviceManager().enumeratePlaybackDevices(),
currentDevice: rtcEngine.getAudioDeviceManager().getPlaybackDefaultDevice(),
currentVolume: 100,
}
} else {
return {
currentDevices: rtcEngine.getAudioDeviceManager().enumerateRecordingDevices(),
currentDevice: rtcEngine.getAudioDeviceManager().getRecordingDefaultDevice(),
currentVolume: rtcEngine.getAudioDeviceManager().getRecordingDeviceVolume()
}
}
},
// 设置音频设备音量
setRecordingDeviceVolume: (volume: number) => {
rtcEngine.getAudioDeviceManager().setRecordingDeviceVolume(volume)
},
// 设置音频采集设备
setRecordingDevice: (deviceId: string) => {
rtcEngine.getAudioDeviceManager().setRecordingDevice(deviceId)
},
// 启动音频播放设备测试。
startPlaybackDeviceTest: () => {
rtcEngine.getAudioDeviceManager().startPlaybackDeviceTest('https://wgshare.oss-cn-chengdu.aliyuncs.com/TestAudio.mp3')
@ -382,6 +324,22 @@ const agora = {
setPlaybackDevice: (deviceId: string) => {
rtcEngine.getAudioDeviceManager().setPlaybackDevice(deviceId)
},
// 启动音频采集设备测试
startRecordingDeviceTest: (indicationInterval: number) => {
rtcEngine.getAudioDeviceManager().startRecordingDeviceTest(indicationInterval)
},
// 设置音频设备音量
setRecordingDeviceVolume: (volume: number) => {
rtcEngine.getAudioDeviceManager().setRecordingDeviceVolume(volume)
},
// 设置音频采集设备
setRecordingDevice: (deviceId: string) => {
rtcEngine.getAudioDeviceManager().setRecordingDevice(deviceId)
},
// 停止音频采集设备测试
stopRecordingDeviceTest: () => {
rtcEngine.getAudioDeviceManager().stopRecordingDeviceTest()
},
}

View File

@ -318,6 +318,10 @@ $pagination-hover-background-color: #5575F2;
}
}
:where(.css-dev-only-do-not-override-98ntnt).ant-slider.ant-slider-disabled .ant-slider-rail {
background-color: darken(#D9D9D9, 50%) !important;
}
// empty
.ant-empty {
.ant-empty-description {