From a27588511513d8979755ad0a26e17dbb8ba6d845 Mon Sep 17 00:00:00 2001 From: yj <1336058017@qq.com> Date: Fri, 26 Jul 2024 11:03:48 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/StupWizard/index.module.scss | 115 ++++++++- src/components/StupWizard/index.tsx | 247 ++++++++++++++++---- src/utils/package/agora.ts | 148 +++++------- src/utils/styles/App.scss | 4 + 4 files changed, 375 insertions(+), 139 deletions(-) diff --git a/src/components/StupWizard/index.module.scss b/src/components/StupWizard/index.module.scss index 1588780..e7d3c53 100644 --- a/src/components/StupWizard/index.module.scss +++ b/src/components/StupWizard/index.module.scss @@ -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; + } + } } \ No newline at end of file diff --git a/src/components/StupWizard/index.tsx b/src/components/StupWizard/index.tsx index c449e0d..53dda2f 100644 --- a/src/components/StupWizard/index.tsx +++ b/src/components/StupWizard/index.tsx @@ -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({ - 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 ( <> { {list.map((row: any, index: number) => { return (
{ - 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() }}> {row.title} @@ -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 ?
- - +
+ +
:
} @@ -170,7 +149,6 @@ const VideoComponents = () => { item: e }) agora.setVideoDeviceManager(e) - agora.startPreview('videoPreview', e) }} />;
@@ -179,31 +157,214 @@ const VideoComponents = () => { ) } const AudioComponents = () => { + const [audioDeviceManager, setAudioDeviceManager] = useState({ + 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 ( <>
音频 -
+
+
+
+ 麦克风: + { + setAudioDeviceManager({ + ...audioDeviceManager, + playBackItem: e + }) + agora.setPlaybackDevice(e) + }} />; + {audioDeviceManager.playBackActive ?
{ + agora.stopPlaybackDeviceTest() + setAudioDeviceManager({ + ...audioDeviceManager, + playBackActive: false, + ecordingActive: false, + }) + }}>结束
:
{ + agora.stopRecordingDeviceTest() + agora.startPlaybackDeviceTest() + setAudioDeviceManager({ + ...audioDeviceManager, + playBackActive: true, + ecordingActive: false, + }) + }}>测试
} +
+ {audioDeviceManager.playBackActive ?
+ +
+ +
+ +
+
+
: null} +
+ 输出音量: + { + agora.setPlaybackDeviceVolume(e) + setAudioDeviceManager({ + ...audioDeviceManager, + playBackVolume: e, + }) + }} disabled={!audioDeviceManager.playBackItem} /> +
+
+
) } const RecordingComponents = () => { + const [filePath, setFilePath] = useState('') return ( <>
录制 -
+
+ 本地录制 +
+ 本地录制文件路径 + { + setFilePath(e.target.value) + }} + /> + +
+
) } const FileComponents = () => { + const [filePath, setFilePath] = useState('') return ( <>
共享文件 -
+
+ 文件下载 +
+ 保存位置 + { + setFilePath(e.target.value) + }} + /> + +
+
+ { + + }}>下载前询问每个文件保存位置 +
+
) diff --git a/src/utils/package/agora.ts b/src/utils/package/agora.ts index 65faefc..6d92513 100644 --- a/src/utils/package/agora.ts +++ b/src/utils/package/agora.ts @@ -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 => { - 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 => { + 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() + }, } diff --git a/src/utils/styles/App.scss b/src/utils/styles/App.scss index 4d1353b..78caaf5 100644 --- a/src/utils/styles/App.scss +++ b/src/utils/styles/App.scss @@ -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 {