JianGongYun/JianGongYun/TRTC/LiveClassroom.cs

367 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using JianGongYun.TRTC.Components;
using JianGongYun.TRTC.Models;
using JianGongYun.TRTC.Utils;
using JianGongYun.TRTC.ViewModels;
using JianGongYun.TRTC.Windows;
using ManageLiteAV;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Window = System.Windows.Window;
using System.Collections.Concurrent;
namespace JianGongYun.TRTC
{
/// <summary>
/// 直播调用对象全放这里
/// </summary>
public static class LiveClassroom
{
const uint SDKAppID = 1400463444;
const string SDKAppKEY = "6ee2586282eb8ab5bff3f917b44500c4ffd9bbd3d820258b1fa8cdd470cfd1ee";
/// <summary>
/// TRTC实例
/// </summary>
public static ITRTCCloud lTRTCCloud;
/// <summary>
/// 设备管理器
/// </summary>
public static ITXDeviceManager lTXDeviceManager;
/// <summary>
/// live窗口的调用窗口
/// </summary>
public static Window CallerWindow { get; private set; }
/// <summary>
/// 直播窗口
/// </summary>
public static Window CurrentLiveWindow;
private static LiveWindowViewModel liveWinMode;
public static ClassroomEntity CurrentClassroomEntity { get; private set; }
public static TRTCCloudCallback TRTCCloudCallback = new TRTCCloudCallback();
public static ConcurrentBag<Task> SaveFileTask = new ConcurrentBag<Task>();
//public static int UserCount = 999;
/// <summary>
/// 进入直播教室
/// </summary>
/// <param name="callerWindow">调用窗口</param>
/// <param name="classroomEntity">教室数据</param>
public static void EnterTheClassroom(Window callerWindow, ClassroomEntity classroomEntity)
{
if (CurrentLiveWindow != null)
{
_ = AduSkin.Controls.Metro.AduMessageBox.Show("已经进入教室", "提醒");
CurrentLiveWindow.Topmost = true;
return;
}
CallerWindow = callerWindow;
CurrentClassroomEntity = classroomEntity;
CurrentLiveWindow = new LiveWindow();
liveWinMode = CurrentLiveWindow.DataContext as LiveWindowViewModel;
CurrentLiveWindow.Closed += CurrentLiveWindow_Closed;
lTRTCCloud = ITRTCCloud.getTRTCShareInstance();//创建TRTC实例
var roomPars = new TRTCParams
{
sdkAppId = SDKAppID,
userId = CurrentClassroomEntity.TeacherId,
userSig = GenTestUserSig(CurrentClassroomEntity.TeacherId),
roomId = 0,//使用strRoomId
strRoomId = CurrentClassroomEntity.TeacherId,
role = TRTCRoleType.TRTCRoleAnchor
};
lTRTCCloud.enterRoom(ref roomPars, TRTCAppScene.TRTCAppSceneLIVE);//创建房间
//设备
//var settingViewMode = ViewModels.SettingWindowViewModel.GetInstance();
lTXDeviceManager = lTRTCCloud.getDeviceManager();
var currentMic = settingWindowViewModel.CurrentMic;//麦克风
if (!string.IsNullOrEmpty(currentMic))
{
var res = lTXDeviceManager.setCurrentDevice(TRTCDeviceType.TXMediaDeviceTypeMic, currentMic);
Console.WriteLine($"设置麦克风:{res}");
}
lTXDeviceManager.setCurrentDeviceVolume(TRTCDeviceType.TXMediaDeviceTypeMic, settingWindowViewModel.MicVolume);//麦克风采集音量
lTRTCCloud.setSystemAudioLoopbackVolume(settingWindowViewModel.SytemGatherVolume);//系统声音采集音量
if (settingWindowViewModel.AudioSource == "2")
{
lTRTCCloud.startSystemAudioLoopback(null);
}
else
{
lTRTCCloud.stopSystemAudioLoopback();
}
var encParams = settingWindowViewModel.EncParams;
var qosParams = settingWindowViewModel.QosParams;
var renderParams = settingWindowViewModel.RenderParams;
lTRTCCloud.setVideoEncoderParam(ref encParams);
lTRTCCloud.setNetworkQosParam(ref qosParams);
lTRTCCloud.setLocalRenderParams(ref renderParams);
//设备完结
//liveWinMode.LoadAllScreen();
_RecoderDir = $"{classroomEntity.ClassHead}_{classroomEntity.ClassSubHead}";
lTRTCCloud.addCallback(TRTCCloudCallback);//注册回调
callerWindow.Hide();//隐藏调用窗口
CurrentLiveWindow.Show();
}
private static string _RecoderDir;
/// <summary>
/// 录制内容的具体路径
/// </summary>
public static string RecoderDir
{
get
{
var temp = Path.Combine(settingWindowViewModel.ScreenRecordingDir, _RecoderDir);
if (!Directory.Exists(temp))
{
Directory.CreateDirectory(temp);
}
return temp;
}
}
private static SettingWindowViewModel settingWindowViewModel = SettingWindowViewModel.GetInstance();
/// <summary>
/// 视频画面
/// </summary>
private static Dictionary<string, TXLiteAVVideoView> VideoViews = new Dictionary<string, TXLiteAVVideoView>();
/// <summary>
/// 启动摄像头
/// </summary>
/// <param name="parent">视频容器</param>
public static TXLiteAVVideoView StartVideoMain(Panel parent)
{
if (!liveWinMode.CameraRunning)
{
lTRTCCloud.startLocalPreview(IntPtr.Zero);
liveWinMode.CameraRunning = true;
return AddCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, true);
}
return null;
}
public static void ResizeVideoMain(Panel parent)
{
if (liveWinMode.CameraRunning)
{
StopVideoMain(parent);
StartVideoMain(parent);
}
}
/// <summary>
/// 停止摄像头
/// </summary>
/// <param name="parent"></param>
public static void StopVideoMain(Panel parent)
{
if (liveWinMode.CameraRunning)
{
liveWinMode.CameraRunning = false;
lTRTCCloud.stopLocalPreview();
RemoveCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, true);
}
}
/// <summary>
/// 启动屏幕分享
/// </summary>
/// <param name="parent"></param>
public static TXLiteAVVideoView StartVideoSub(Panel parent)
{
if (!liveWinMode.ScreenRunning)
{
liveWinMode.ScreenRunning = true;
SelectVieoSub();
lTRTCCloud.startScreenCapture(IntPtr.Zero, TRTCVideoStreamType.TRTCVideoStreamTypeSub, settingWindowViewModel.EncParams);
return AddCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeSub, true);
}
return null;
}
public static void ResizeVideoSub(Panel parent)
{
if (liveWinMode.ScreenRunning)
{
RemoveCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeSub, true);
AddCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeSub, true);
}
}
/// <summary>
/// 停止屏幕分享
/// </summary>
/// <param name="parent"></param>
public static void StopVideoSub(Panel parent)
{
if (liveWinMode.ScreenRunning)
{
liveWinMode.ScreenRunning = false;
lTRTCCloud.stopScreenCapture();
RemoveCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeSub, true);
}
}
/// <summary>
/// 选择要分享的屏幕
/// </summary>
public static void SelectVieoSub()
{
var current = liveWinMode.CurrentShareScreen;
var rect = new RECT();
var property = new TRTCScreenCaptureProperty();
lTRTCCloud.selectScreenCaptureTarget(ref current, ref rect, ref property);
}
/// <summary>
/// 启动麦克风
/// </summary>
public static void StartMic()
{
if (!liveWinMode.MicRunning)
{
liveWinMode.MicRunning = true;
lTRTCCloud.startLocalAudio(settingWindowViewModel.LiveAudioLevel);
if (liveWinMode.IsLive)
{
var pars = new TRTCAudioRecordingParams { filePath = "" };
lTRTCCloud.startAudioRecording(ref pars);
}
}
}
/// <summary>
/// 关闭麦克风
/// </summary>
public static void StopMic()
{
if (liveWinMode.MicRunning)
{
liveWinMode.MicRunning = false;
lTRTCCloud.stopLocalAudio();
}
}
/// <summary>
/// 设置麦克风静音
/// </summary>
public static void SetMicMute(bool? mute = true)
{
if (liveWinMode.MicRunning)
{
liveWinMode.MicMute = mute.HasValue ? mute.Value : !liveWinMode.MicMute;
lTRTCCloud.muteLocalAudio(liveWinMode.MicMute);
}
}
/// <summary>
/// 添加自定义渲染 View 并绑定渲染回调
/// </summary>
private static TXLiteAVVideoView AddCustomVideoView(Panel parent, string userId, TRTCVideoStreamType streamType, bool local = false)
{
TXLiteAVVideoView videoView = new TXLiteAVVideoView();
videoView.RegEngine(userId, streamType, lTRTCCloud, local);
videoView.SetRenderMode(streamType == TRTCVideoStreamType.TRTCVideoStreamTypeBig ? settingWindowViewModel.RenderParams.fillMode : TRTCVideoFillMode.TRTCVideoFillMode_Fit);
videoView.Width = parent.ActualWidth;
videoView.Height = parent.ActualHeight;
parent.Dispatcher.Invoke(new Action(() =>
{
parent.Children.Add(videoView);
}));
string key = string.Format("{0}_{1}", userId, streamType);
VideoViews.Add(key, videoView);
return videoView;
}
/// <summary>
/// 移除自定义渲染 View 并解绑渲染回调
/// </summary>
private static void RemoveCustomVideoView(Panel parent, string userId, TRTCVideoStreamType streamType, bool local = false)
{
TXLiteAVVideoView videoView = null;
string key = string.Format("{0}_{1}", userId, streamType);
if (VideoViews.TryGetValue(key, out videoView))
{
videoView.RemoveEngine(lTRTCCloud);
parent.Dispatcher.Invoke(new Action(() =>
{
parent.Children.Remove(videoView);
}));
VideoViews.Remove(key);
}
}
/// <summary>
/// 重启音频录制
/// </summary>
public static void RestartAudio() { }
/// <summary>
/// 重设主视频(摄像头)
/// </summary>
public static void ResetVideoMain() { }
/// <summary>
/// 重设主视频(摄像头)网络
/// </summary>
public static void ResetVideoMainQos() { }
/// <summary>
/// 重设副视频(录屏)
/// </summary>
public static void ResetVideoSub() { }
private static void CurrentLiveWindow_Closed(object sender, EventArgs e)
{
CurrentLiveWindow = null;
CurrentClassroomEntity = null;
CallerWindow.Show();//还原调用者窗口
lTXDeviceManager.Dispose();
lTXDeviceManager = null;
lTRTCCloud.exitRoom();
lTRTCCloud.removeCallback(TRTCCloudCallback);//注册回调
ITRTCCloud.destroyTRTCShareInstance();//销毁TRTC实例
lTRTCCloud.Dispose();
lTRTCCloud = null;
}
/// <summary>
/// 计算 UserSig 签名
///
/// 函数内部使用 HMAC-SHA256 非对称加密算法,对 SDKAPPID、userId 和 EXPIRETIME 进行加密
///
/// 该方案仅适合本地跑通demo和功能调试产品真正上线发布要使用服务器获取方案避免私钥被破解。
/// </summary>
/// <remarks>
/// 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
///
/// 本文件中的代码虽然能够正确计算出 UserSig但仅适合快速调通 SDK 的基本功能,不适合线上产品,
/// 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
/// 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
///
/// 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
/// 由于破解服务器的成本要高于破解客户端 App所以服务器计算的方案能够更好地保护您的加密密钥。
///
/// 文档https://cloud.tencent.com/document/product/647/17275#GetFromServer
/// </remarks>
public static string GenTestUserSig(string userId)
{
if (SDKAppID == 0 || string.IsNullOrEmpty(SDKAppKEY)) return null;
TLSSigAPIv2 api = new TLSSigAPIv2((int)SDKAppID, SDKAppKEY);
// 统一转换为UTF8SDK内部是用UTF8编码。
return api.GenSig(Util.UTF16To8(userId));
}
}
}