WGShare.Client.Electron/src/utils/package/agora.ts

516 lines
20 KiB
TypeScript

import {
createAgoraRtcEngine,
ClientRoleType,
VideoSourceType,
VideoViewSetupMode,
ScreenCaptureSourceType,
RenderModeType,
ChannelProfileType,
AudioAinsMode,
SimulcastStreamMode,
VideoStreamType,
QualityType,
RtcConnection,
RtcStats,
AudioVolumeInfo,
UserOfflineReasonType,
ConnectionStateType,
ConnectionChangedReasonType,
LocalVideoStreamReason,
LocalVideoStreamState
} from "agora-electron-sdk";
import { GetRoomRtcToken, GetAgoraConf } from "@/api/Home/Index";
import { storage } from '@/utils';
import { role } from "@/config/role";
const option: any = {
appId: '',
token: '',
tokenA: '',
channelId: '',
uid: '',
screenShareId: '',
}
let rtcEngine: any = '';
export const agora = {
// 初始化
init: async (bool: boolean = false) => {
const { data } = await GetAgoraConf();
if (data) {
rtcEngine = createAgoraRtcEngine();
await rtcEngine.initialize({
appId: data,
});
if (bool) {
await agora.setDeviceManager()
}
}
},
// 获取rtcEngine
getRtcEngine: () => {
return rtcEngine
},
// 获取当前设备是否存在不存在就获取默认设备
setDeviceManager: async () => {
const setting = await JSON.parse(storage.getItem('setting') as string)
// 摄像头
if (setting.videoDeviceId) {
await agora.getVideoDeviceManager().then(async (res) => {
let item = res.list.find((item: any) => item.deviceId === setting.videoDeviceId);
if (item) {
await agora.setVideoDeviceManager(setting.videoDeviceId)
} else {
await agora.setVideoDeviceManager(await rtcEngine.getVideoDeviceManager().getDevice())
setting.videoDeviceId = await rtcEngine.getVideoDeviceManager().getDevice()
}
})
} else {
await agora.setVideoDeviceManager(await rtcEngine.getVideoDeviceManager().getDevice())
setting.videoDeviceId = await rtcEngine.getVideoDeviceManager().getDevice()
}
// 播放设备
if (setting.playBackDeviceId) {
await agora.getAudioMediaList().then(async (res) => {
let item = res.playBackList.find((item: any) => item.deviceId === setting.playBackDeviceId);
if (item) {
await agora.setPlaybackDevice(setting.playBackDeviceId)
} else {
await agora.setPlaybackDevice(res.playBackItem.deviceId)
setting.playBackDeviceId = res.playBackItem.deviceId
}
})
} else {
let deviceId = await rtcEngine.getAudioDeviceManager().getPlaybackDefaultDevice().deviceId;
await agora.setPlaybackDevice(deviceId)
setting.playBackDeviceId = deviceId
}
// 音频设备
if (setting.ecordingDeviceId) {
await agora.getAudioMediaList().then(async (res) => {
let item = res.ecordingList.find((item: any) => item.deviceId === setting.ecordingDeviceId);
if (item) {
await agora.setRecordingDevice(setting.ecordingDeviceId)
} else {
await agora.setRecordingDevice(res.ecordingItem.deviceId)
setting.ecordingDeviceId = res.ecordingItem.deviceId
}
})
} else {
let deviceId = await rtcEngine.getAudioDeviceManager().getRecordingDefaultDevice().deviceId;
await agora.setRecordingDevice(deviceId)
setting.ecordingDeviceId = deviceId
}
setTimeout(async () => {
storage.setItem('setting', JSON.stringify(setting))
const settingData = await JSON.parse(storage.getItem('setting') as string)
if (settingData.videoDeviceId) agora.setVideoDeviceManager(settingData.videoDeviceId) //指定摄像头头采集设备
if (settingData.playBackDeviceId) agora.setPlaybackDevice(settingData.playBackDeviceId) //指定播放设备
if (settingData.playBackVolume) agora.setPlaybackDeviceVolume(settingData.playBackVolume) // 设置播放设备音量
if (settingData.ecordingDeviceId) agora.setRecordingDevice(settingData.ecordingDeviceId) // 设置音频采集设备
if (settingData.ecordingVolume) agora.setRecordingDeviceVolume(settingData.ecordingVolume) // 设置音频设备音量
if (settingData.isAINoiseReduction) agora.setAINSMode(settingData.isAINoiseReduction, settingData.aINoiseReduction) // 设置ai降噪
}, 1000);
},
// 事件回调
registerEventHandler: ({ onJoinChannelSuccess, onUserJoined, onUserOffline, onAudioVolumeIndication, onNetworkQuality, onRtcStats, onConnectionStateChanged, onLocalVideoStateChanged }: any) => {
rtcEngine.registerEventHandler({
// 监听本地用户加入频道事件
onJoinChannelSuccess: async (connection: RtcConnection, elapsed: number) => {
await onJoinChannelSuccess?.(connection, elapsed)
},
// 监听远端用户加入频道事件
onUserJoined: async (connection: RtcConnection, remoteUid: number, elapsed: number) => {
await onUserJoined?.(connection, remoteUid, elapsed)
},
// 监听用户离开频道事件
onUserOffline: async (connection: RtcConnection, remoteUid: number, reason: UserOfflineReasonType) => {
await onUserOffline?.(connection, remoteUid, reason)
},
// // 视频发布状态改变回调
// onVideoPublishStateChanged: (source: any, channel: any, oldState: any, newState: any, elapseSinceLastState: any) => {
// if (newState === 1) {
// }
// },
// // 音频发布状态改变回调
// onAudioPublishStateChanged: (channel: any, oldState: any, newState: any, elapseSinceLastState: any) => {
// if (newState === 1) {
// }
// },
// // 用户音量提示回调。
onAudioVolumeIndication: async (_connection: RtcConnection, speakers: AudioVolumeInfo[], _speakerNumber: number, _totalVolume: number) => {
await onAudioVolumeIndication?.(speakers)
},
//通话中每个用户的网络上下行 last mile 质量报告回调。
onNetworkQuality: async (connection: RtcConnection, remoteUid: number, txQuality: QualityType, rxQuality: QualityType) => {
await onNetworkQuality?.(connection, remoteUid, txQuality, rxQuality)
},
//当前通话相关的统计信息回调。
onRtcStats: async (_connection: RtcConnection, stats: RtcStats) => {
await onRtcStats?.(stats)
},
// 网络连接状态已改变回调。
onConnectionStateChanged: async (connection: RtcConnection, state: ConnectionStateType, reason: ConnectionChangedReasonType) => {
await onConnectionStateChanged?.(connection, state, reason)
},
// 本地视频状态发生改变回调。
onLocalVideoStateChanged: async (source: VideoSourceType, state: LocalVideoStreamState, reason: LocalVideoStreamReason) => {
await onLocalVideoStateChanged?.(source, state, reason)
},
});
},
// 获取视图模式
getRrenderMode: (uid: number) => {
if (String(uid).length === 9) {
return RenderModeType.RenderModeFit
} else {
return RenderModeType.RenderModeHidden
}
},
// 本地加入
setupLocalVideo: async (item: any) => {
if (item.view?.childNodes.length === 1 || item.type) {
await rtcEngine.setupLocalVideo({
renderMode: agora.getRrenderMode(item.uid),
sourceType: item.sourceType,
uid: item.uid,
view: item.view,
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
});
}
},
// 远端加入
setupRemoteVideoJoin: async (item: any) => {
if (item.view?.childNodes.length === 1) {
await rtcEngine.setupRemoteVideo(
{
renderMode: agora.getRrenderMode(item.uid),
sourceType: VideoSourceType.VideoSourceRemote,
uid: item.uid,
view: item.view,
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
},
{ channelId: item.channelId },
);
}
},
setupRemoteVideoEx: async (item: any) => {
if (item.view?.childNodes.length === 1) {
await rtcEngine.setupRemoteVideoEx(
{
renderMode: agora.getRrenderMode(item.uid),
sourceType: VideoSourceType.VideoSourceRemote,
uid: item.uid,
view: item.view,
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
},
{ channelId: item.channelId },
);
}
},
// 退出
setupRemoteVideo: async (item: any) => {
await rtcEngine.setupRemoteVideo(
{
renderMode: agora.getRrenderMode(item.uid),
sourceType: VideoSourceType.VideoSourceRemote,
uid: item.uid,
view: item.view,
setupMode: VideoViewSetupMode.VideoViewSetupRemove,
},
);
},
// 销毁
release: async () => {
await rtcEngine.release()
},
// 离开频道
leaveChannel: async () => {
await rtcEngine.leaveChannel({
stopAudioMixing: true,
stopAllEffect: true,
stopMicrophoneRecording: true,
})
agora.stopScreenCapture()
agora.release()
},
// 加入频道
joinChannel: async () => {
await rtcEngine.enableAudioVolumeIndication(100, 3, true)
await rtcEngine.joinChannel(option.token, option.channelId, option.uid);
await rtcEngine.setDualStreamModeEx(
SimulcastStreamMode.EnableSimulcastStream,
{
dimensions: {
width: 320,
height: 180
},
framerate: 5,
},
{ channelId: option.channelId, localUid: Number(option.uid) }
);
},
// 更新频道配置
updateChannelMediaOptions: async (bool: boolean) => {
await rtcEngine.updateChannelMediaOptions({
clientRoleType: bool ? ClientRoleType.ClientRoleBroadcaster : ClientRoleType.ClientRoleAudience, //用户角色 ClientRoleBroadcaster 主播 ClientRoleAudience 观众
autoSubscribeAudio: true,//设置是否自动订阅所有音频流
autoSubscribeVideo: true,//设置是否自动订阅所有视频流
publishMicrophoneTrack: true,//设置是否发布麦克风采集到的音频
publishCameraTrack: true,//设置是否发布摄像头采集的视频
publishScreenTrack: false,//设置是否发布屏幕采集的视频
})
},
// 设置接收大小流
setRemoteVideoStreamType: async (uid: number, type: VideoStreamType, bool: boolean) => {
await rtcEngine.setRemoteVideoStreamTypeEx(
Number(uid),
type,
bool ? { channelId: option.channelId, localUid: Number(option.uid) } : { channelId: option.channelId + 'a', localUid: Number('1' + option.screenShareId) }
)
},
// 共享屏幕单独用户
joinChannelEx: async (uid: any) => {
await agora.leaveChannelEx(uid)
await rtcEngine.joinChannelEx(
option.token,
{ channelId: option.channelId, localUid: Number(uid) },
{
autoSubscribeAudio: false,//设置是否自动订阅所有音频流
autoSubscribeVideo: false,//设置是否自动订阅所有视频流
publishMicrophoneTrack: false,//设置是否发布麦克风采集到的音频
publishCameraTrack: false,//设置是否发布摄像头采集的视频
clientRoleType: ClientRoleType.ClientRoleBroadcaster,//用户角色 ClientRoleBroadcaster 主播 ClientRoleAudience 观众
publishScreenTrack: true,//设置是否发布屏幕采集的视频
}
);
},
// 所有用户加入的第二个房间
allJoinChannelEx: async (bool: boolean = false) => {
const user = await JSON.parse(storage.getItem('user') as string)
await agora.startCameraCapture(true)
await rtcEngine.joinChannelEx(
option.tokenA,
{ channelId: option.channelId + 'a', localUid: Number('1' + option.screenShareId) },
{
clientRoleType: bool ? ClientRoleType.ClientRoleAudience : ClientRoleType.ClientRoleBroadcaster, //用户角色 ClientRoleBroadcaster 主播 ClientRoleAudience 观众
autoSubscribeAudio: false,//设置是否自动订阅所有音频流
autoSubscribeVideo: role.ID.includes(user.roleId) ? true : false,//设置是否自动订阅所有视频流
publishMicrophoneTrack: false,//设置是否发布麦克风采集到的音频
publishCameraTrack: true,//设置是否发布摄像头采集的视频
publishScreenTrack: false,//设置是否发布屏幕采集的视频
}
);
await rtcEngine.setDualStreamModeEx(
SimulcastStreamMode.EnableSimulcastStream,
{
dimensions: {
width: 320,
height: 180
},
framerate: 5,
},
{ channelId: option.channelId + 'a', localUid: Number('1' + option.screenShareId) }
);
},
// 退出第二个房间
allLeaveChannelEx: async () => {
await agora.stopCameraCapture();
await rtcEngine.leaveChannelEx({ channelId: option.channelId + 'a', localUid: Number('1' + option.screenShareId) })
},
// 停止/恢复接收指定的视频流。
muteRemoteVideoStreamEx: async (uid: number, mute: boolean) => {
await rtcEngine.muteRemoteVideoStreamEx(uid, mute, { channelId: option.channelId, localUid: Number(option.uid) })
},
// 取消或恢复订阅指定远端用户的音频流
muteRemoteVideoStream: async (uid: number, mute: boolean) => {
rtcEngine.muteRemoteVideoStream(uid, mute)
},
// 销毁视频渲染dom
destroyRendererByConfig: async (uid: number, channelId: string) => {
await rtcEngine.destroyRendererByConfig(VideoSourceType.VideoSourceRemote, channelId, uid);
},
// ai降噪
setAINSMode: async (enabled: boolean, mode: AudioAinsMode) => {
rtcEngine.setAINSMode(enabled, mode)
},
// 离开共享屏幕频道
leaveChannelEx: async (uid: any) => {
await rtcEngine.leaveChannelEx({ channelId: option.channelId, localUid: Number(uid) })
},
// 停止共享屏幕
stopScreenCapture: () => {
rtcEngine.stopScreenCapture();
rtcEngine.enableLoopbackRecording(false)
},
// 取消或恢复发布本地音频流
muteLocalAudioStream: async (data: any, publishMicrophoneTrack: boolean, publishCameraTrack: boolean) => {
// await rtcEngine.muteLocalAudioStream(mute)
await rtcEngine.updateChannelMediaOptions({
clientRoleType: data ? ClientRoleType.ClientRoleBroadcaster : ClientRoleType.ClientRoleAudience, //用户角色 ClientRoleBroadcaster 主播 ClientRoleAudience 观众
autoSubscribeAudio: true,//设置是否自动订阅所有音频流
autoSubscribeVideo: true,//设置是否自动订阅所有视频流
publishMicrophoneTrack: publishMicrophoneTrack,//设置是否发布麦克风采集到的音频
publishCameraTrack: publishCameraTrack,//设置是否发布摄像头采集的视频
publishScreenTrack: false,//设置是否发布屏幕采集的视频
})
},
// 取消或恢复发布本地视频流
muteLocalVideoStream: async (data: any, publishMicrophoneTrack: boolean, publishCameraTrack: boolean) => {
// await rtcEngine.muteLocalVideoStream(mute)
await rtcEngine.updateChannelMediaOptions({
clientRoleType: data ? ClientRoleType.ClientRoleBroadcaster : ClientRoleType.ClientRoleAudience, //用户角色 ClientRoleBroadcaster 主播 ClientRoleAudience 观众
autoSubscribeAudio: true,//设置是否自动订阅所有音频流
autoSubscribeVideo: true,//设置是否自动订阅所有视频流
publishMicrophoneTrack: publishMicrophoneTrack,//设置是否发布麦克风采集到的音频
publishCameraTrack: publishCameraTrack,//设置是否发布摄像头采集的视频
publishScreenTrack: false,//设置是否发布屏幕采集的视频
})
},
// 摄像头采集
startCameraCapture: async (bool: boolean = false) => {
await rtcEngine.startCameraCapture(VideoSourceType.VideoSourceCamera, {
format: {
width: bool ? 160 : 1280,
height: bool ? 160 : 720,
fps: 15,
}
})
},
// 停止采集摄像头
stopCameraCapture: async () => {
await rtcEngine.stopCameraCapture()
},
// 加入频道
setJoinChannel: async (data: any) => {
option.token = data.token;
option.tokenA = data.tokenA;
option.channelId = data.channelId;
option.uid = Number(data.uid);
option.screenShareId = data.screenShareId;
await agora.joinChannel()
},
// 桌面捕获音频和视频的媒体源的信息
getDesktopCapturerVideo: async (thumbSize: any, iconSize: any, includeScreen: boolean) => {
return await rtcEngine.getScreenCaptureSources(thumbSize, iconSize, includeScreen)
},
// 共享屏幕采集
setDesktopCapturerVideo: async (targetSource: any, isComputerAudio: boolean, isFluencyPriority: boolean) => {
const user = JSON.parse(storage.getItem('user') as string)
agora.stopScreenCapture();
if (isComputerAudio) {
rtcEngine.enableLoopbackRecording(true)
}
let data = {
frameRate: isFluencyPriority ? 30 : 15,
dimensions: {
width: 1920,
height: 1080,
}
}
if (
targetSource.type ===
ScreenCaptureSourceType.ScreencapturesourcetypeScreen
) {
rtcEngine.startScreenCaptureByDisplayId(
targetSource.sourceId,
{},
{
windowFocus: true,
...data
}
);
} else {
rtcEngine.startScreenCaptureByWindowId(
targetSource.sourceId,
{},
{
windowFocus: true,
...data
}
);
}
await agora.joinChannelEx(user.screenShareId)
},
// 获取系统中所有的视频设备列表。
getVideoDeviceManager: async (): Promise<any> => {
return {
list: rtcEngine.getVideoDeviceManager().enumerateVideoDevices(),
item: rtcEngine.getVideoDeviceManager().getDevice()
}
},
// 通过设备 ID 指定视频采集设备。
setVideoDeviceManager: async (deviceIdUTF8: string) => {
await rtcEngine.getVideoDeviceManager().setDevice(deviceIdUTF8)
},
// 开启本地视频预览
startPreview: async (id: string, uid: number): Promise<void> => {
rtcEngine.enableVideo();
rtcEngine.startPreview();
await GetRoomRtcToken(`${+new Date()}`).then(async (res) => {
await rtcEngine.joinChannelEx(res.data, {
channelId: `${+new Date() + uid}`,
localUid: 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,
});
})
},
// 获取输入输出设备列表
getAudioMediaList: async () => {
return {
playBackList: rtcEngine.getAudioDeviceManager().enumeratePlaybackDevices(),
ecordingList: rtcEngine.getAudioDeviceManager().enumerateRecordingDevices(),
playBackItem: rtcEngine.getAudioDeviceManager().getPlaybackDefaultDevice(),
ecordingItem: rtcEngine.getAudioDeviceManager().getRecordingDefaultDevice(),
ecordingVolume: rtcEngine.getAudioDeviceManager().getRecordingDeviceVolume(),
}
},
// 启动音频播放设备测试。
startPlaybackDeviceTest: async () => {
await rtcEngine.getAudioDeviceManager().startPlaybackDeviceTest('https://wgshare.oss-cn-chengdu.aliyuncs.com/TestAudio.mp3')
},
// 停止音频播放设备测试。
stopPlaybackDeviceTest: async () => {
await rtcEngine.getAudioDeviceManager().stopPlaybackDeviceTest()
},
// 设置播放设备音量
setPlaybackDeviceVolume: async (volume: number) => {
await rtcEngine.getAudioDeviceManager().setPlaybackDeviceVolume(volume)
},
// 指定播放设备
setPlaybackDevice: async (deviceId: string) => {
await rtcEngine.getAudioDeviceManager().setPlaybackDevice(deviceId)
},
// 启动音频采集设备测试
startRecordingDeviceTest: async (indicationInterval: number) => {
await rtcEngine.getAudioDeviceManager().startRecordingDeviceTest(indicationInterval)
},
// 设置音频设备音量
setRecordingDeviceVolume: async (volume: number) => {
await rtcEngine.getAudioDeviceManager().setRecordingDeviceVolume(volume)
},
// 设置音频采集设备
setRecordingDevice: async (deviceId: string) => {
await rtcEngine.getAudioDeviceManager().setRecordingDevice(deviceId)
},
// 停止音频采集设备测试
stopRecordingDeviceTest: async () => {
await rtcEngine.getAudioDeviceManager().stopRecordingDeviceTest()
},
}