首页 > 系统相关 >Avalonia 实现视频聊天、远程桌面(源码,支持Windows、Linux、国产OS)

Avalonia 实现视频聊天、远程桌面(源码,支持Windows、Linux、国产OS)

时间:2023-10-16 09:45:40浏览次数:54  
标签:视频 请求 聊天 Windows 源码 远程桌面 public Avalonia

       现在最火的.NET跨平台UI框架莫过于Avalonia了。Avalonia 基于.NET Core,因此它可以运行在任何支持.NET Core的平台上。之前基于CPF跨平台UI框架写过一个视频聊天的demo,而现在看来Avalonia是大势所趋,于是,我再写一个Avalonia版本的Demo来供大家参考,它可以在Windows和Linux(包括国产OS,如银河麒麟、统信UOS)上运行。

       下图是视频聊天Demo的Avalonia客户端在国产统信UOS上的运行的截图:

       

 

一.功能介绍 

      客户端登录成功后,运行的主界面如下图所示: 

             

1. 视频聊天

(1)每个登录的用户都可向其他任意在线用户发送视频聊天请求。

(2)当收到来自其他在线用户的视频聊天邀请时,可接受或拒绝对方的请求。

(3)当接受其他在线用户的视频聊天邀请时,即可开启视频聊天。 

2. 远程桌面

(1)每个登录的用户都可向其他任意在线用户发送远程桌面请求;当对方未响应时,可主动取消远程桌面请求。

(2)当收到来自其他在线用户请求控制桌面时,可接受或拒绝对方的请求。

(3)当发送方收到其他在线用户同意控制其电脑时,即可开启远程桌面连接。

(4)被控端和主控端都可主动断开远程桌面连接。 

 

二.开发环境

1.开发工具:

Visual Studio 2022 

2. 开发框架: 

.NET Core 3.1

3.开发语言:

C#

4.其它框架:

Avalonia UI 框架(版本:0.10.22)、OMCS 语音视频框架 (版本:8.0)

注:建议 Avalonia 使用0.10.*的版本,精简而且很稳定,而最新的11.0的版本太庞大了。

三.具体实现

      下面我们讲一下Demo中核心的代码实现,大家从文末下载源码并对照着源码看,会更清楚些。

1.自定义消息类型 InformationTypes

        public static class InformationTypes
    {
        /// <summary>
                /// 视频请求 0
        /// </summary>
        public const int VideoRequest = 0;

        /// <summary>
                /// 回复视频请求的结果 1
        /// </summary>
        public const int VideoResult = 1;

        /// <summary>
                /// 通知对方 挂断 视频连接 2
        /// </summary>
        public const int CloseVideo = 2;

        /// <summary>
        /// 通知好友 网络原因,导致 视频中断 3
        /// </summary>
        public const int NetReasonCloseVideo = 3;

        /// <summary>
        /// 通知对方(忙线中) 挂断 视频连接 4
        /// </summary>
        public const int BusyLine = 4;

        /// <summary>
                /// 远程桌面请求 5
        /// </summary>
        public const int DesktopRequest = 5;

        /// <summary>
                /// 回复远程桌面请求的结果 6
        /// </summary>
        public const int DesktopResult = 6;

        /// <summary>
                ///  主动取消远程桌面请求 7
        /// </summary>
        public const int CancelDesktop = 7;

        /// <summary>
                ///  对方(主人端)主动断开远程桌面 8
        /// </summary>
        public const int OwnerCloseDesktop = 8;

        /// <summary>
                /// 客人端断开远程桌面连接 9
        /// </summary>
        public const int GuestCloseDesktop = 9;
    } 

2. 发送视频请求

(1)当发起视频聊天时,将显示视频聊天窗口 

    /// <summary>
    /// 打开视频通话窗口
    /// </summary>
    /// <param name="destID">对方ID</param>
    /// <param name="isWorking">false表示主动发起视频通话邀请</param>
    internal void OpenVideoChat(string destID,bool isWorking)
    {
        if (!this.VideoInvokeVerdict(destID))
        {
            return;
        }

        App.Multimedia.OutputAudio = true;
        VideoChatWindow videoChatWindow = new VideoChatWindow(destID, isWorking);
        videoChatWindow.EndTheCalled += VideoChatWindow_EndTheCalled;
        objectManager.Add(destID, videoChatWindow);
        videoChatWindow.Show();
    }

  (2)连接自己的摄像头 

    public VideoChatWindow(string destID,bool isWorking)
    {
        this.DestID = destID;
        this.IsWorking = isWorking;
        InitializeComponent();

        //连接自己的摄像头
        this.selfCamera.Core.DisplayVideoParameters = true;
        this.selfCamera.Core.VideoDrawMode = VideoDrawMode.ScaleToFill;
        this.selfCamera.BeginConnect(MainWindow.CurrentID);

        this.Title = this.title.Text = this.RepeatedCallTip(false);
        this.timer = new System.Timers.Timer();
        this.timer.Interval = 1000;
        this.timer.Elapsed += Timer_Elapsed;
        if (IsWorking)
        { 
            this.BeginConnect();
        }
    }

  (3)发送视频通话请求

   protected override void OnInitialized()
   {
       base.OnInitialized(); 
       this.SetWindowStats();
       if (!this.IsWorking)
       {
           //向对方发起视频通话邀请
           VideoController.Singleton.SendMessage(this.DestID, InformationTypes.VideoRequest, null);
       }
   }

  

3. 回复对方视频请求

(1)当收到对方的视频聊天邀请时,将显示视频邀请窗口  

          

 (2)发送回复视频聊天请求消息 

 protected override void OnClosed(EventArgs e)
 {
     base.OnClosed(e);
     if (this.EndTheCalled != null)
     {
         this.EndTheCalled(this.DestID);
     }
     if (this.NotifyOther)
     {  
         //回复对方的视频通话请求
         byte[] bytes = BitConverter.GetBytes(replyResult);
         VideoController.Singleton.SendMessage(this.DestID, InformationTypes.VideoResult, bytes);
     }
     if (this.replyResult)
     {
         VideoController.Singleton.OpenVideoChat(DestID,true);
     }
 }

4. 收到对方视频请求的回复 

    /// <summary>
    /// 视频通话,收到对方回复
    /// </summary> 
    internal void TargerReply(string destID, CommunicationStateType type)
    {
        ICommunicationAid aid = this.objectManager.Get(destID);
        if(aid == null)
        {
            return;
        } 
        switch (type)
        {
            case CommunicationStateType.Agree:
                VideoChatWindow videoChatWindow = (VideoChatWindow)aid;
                videoChatWindow.BeginConnect();
                break;
            case CommunicationStateType.Reject: 
                aid.CloseWindow(false);
                break;
            case CommunicationStateType.HangUp: 
                aid.CloseWindow(false);
                break;
            default:
                break;
        }
    }

  当对方回复同意时,将连接到对方的麦克风和摄像头,开始视频聊天会话: 

  /// <summary>
  /// 连接对方设备
  /// </summary>
  internal void BeginConnect()
  {
      UiSafeInvoker.ActionOnUI(() =>
      {
          this.IsWorking = true;
          this.Title = this.title.Text = this.RepeatedCallTip(false);
          this.startTime = DateTime.Now;
          this.timer.Start();
          this.otherCamera.Core.DisplayVideoParameters = true;
          this.otherCamera.Core.VideoDrawMode = VideoDrawMode.ScaleToFill;
          this.otherCamera.Core.ConnectEnded += DynamicCameraConnector_ConnectEnded;
          this.otherCamera.Core.Disconnected += DynamicCameraConnector_Disconnected;
          this.microphoneConnector.ConnectEnded += MicrophoneConnector_ConnectEnded;
          this.microphoneConnector.Disconnected += MicrophoneConnector_Disconnected;
          this.otherCamera.BeginConnect(this.DestID);
          this.microphoneConnector.BeginConnect(this.DestID);
           
          this.NotifyOther = true;
      });
  }  

5. 实现远程桌面

      远程桌面的请求/应答逻辑几乎与视频聊天请求/应答逻辑是一模一样的。这里就不再罗列响应的代码了。

(1)当收到对方的远程桌面控制请求时,将显示请求窗口。

   

(2)当同意对方的控制请求时,对方就可以控制请求方的电脑了。

         

四.源码下载     

     .NetCore服务端 + Avalonia客户端:VideoChatMini.Avalonia.rar  

      在Windows上部署运行服务端和客户端很容易,大家也都很熟悉了。下面讲一下如何在Linux上部署运行这个视频聊天程序的服务端和客户端。

     在Linux上部署运行说明

       在部署之前,需要在linux服务端和客户端上分别安装 .Net core 3.1版本,命令行安装命令如下:

 yum install dotnet-sdk-3.1

      检查版本安装情况

 dotnet --version

       运行:

(1)在CentOS上启动VideoChatMini.ServerNetcore服务端:

  拷贝Oraycn.VideoChatMini.ServerNetcore项目下的Debug文件夹,到CentOS操作系统上,打开Debug -> netcoreapp3.1目录 ,在目录下打开终端,执行以下命令启动服务端   

dotnet Oraycn.VideoChatMini.ServerNetcore.dll

 (2)在麒麟或统信UOS、Ubuntu上运行VideoChatMini.ClientAvalonia客户端:

  拷贝Oraycn.VideoChatMini.ClientAvalonia项目下的Debug文件夹,到麒麟或统信UOS、Ubuntu操作系统上,打开Debug -> netcoreapp3.1目录 ,在目录下打开终端,执行以下命令启动客户端

dotnet Oraycn.VideoChatMini.ClientAvalonia.dll

       命令执行成功后,就会出现之前截图的客户端主界面。        

        Avalonia 支持在X64和ARM64架构的Linux上运行,Demo的运行目录下放的是X64架构的so,如果需要ARM64架构的so,可留下邮箱获取。

 

标签:视频,请求,聊天,Windows,源码,远程桌面,public,Avalonia
From: https://www.cnblogs.com/shawshank/p/17761146.html

相关文章

  • Vue源码学习(十一):计算属性computed初步学习
    好家伙,  1.Computed实现原理if(opts.computed){initComputed(vm,opts.computed);}functioninitComputed(vm,computed){//存放计算属性的watcherconstwatchers=vm._computedWatchers={};for(constkeyincomputed){constuser......
  • GitHub 3个初中生开源了windows 12网页版,目前5k+ star!
    国内3个初中生开源了Windows12网页版,尽管项目基本涉及前端,对于大多数开发者来说可能没什么太高的技术含量,可是想到他们才上初中,真的是后生可畏呀!目前项目已经获得了5k+star。GitHub:https://github.com/tjy-gitnub/win12在线体验:https://tjy-gitnub.github.io/win12/deskt......
  • 《人人都是数据分析师》高清高质量PDF电子书+源码
    下载:https://pan.quark.cn/s/3f61395b8d51......
  • 《Head First JavaScript程序设计》高清高质量 原版电子书PDF+源码
    下载:https://pan.quark.cn/s/9b368a216582......
  • Android WebView获取html源码
    通过执行js语句来获取valcode="""document.documentElement.outerHTML""".trimIndent()webview.evaluateJavascript(code){value->valhtmlContent=if(value==null){""}else{//这里需要处理下......
  • 研发必会-异步编程利器之CompletableFuture(含源码 中)
    微信公众号访问地址:研发必会-异步编程利器之CompletableFuture(含源码中)近期热推文章:    1、springBoot对接kafka,批量、并发、异步获取消息,并动态、批量插入库表;    2、SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据;    3、基于Redis的Geo实现附......
  • 自动批量将阿里云盘资源发布成WordPress文章带截图Python脚本(含正文 付费信息 下载地
    自动批量将阿里云盘资源发布成WordPress文章带截图Python脚本(含正文付费信息下载地址SEO等自动设置)自动批量将阿里云盘资源发布成WordPress文章带截图Python脚本(含正文付费信息下载地址SEO等自动设置)源码下载自动上传图片至WordPress站点,使用RestFulAPI批量发布文章,文章含......
  • Django 代码部署运行(Windows)
     安装git 准备好文件夹E:\_prjct\boshi_xinxi_caiji\codes2 启动gitbash$pwd/E/_prjct/boshi_xinxi_caiji/codes2$gitclonehttps://gitee.com/xautstar/doctoral-dissertation-collection.git   创建数据库collection,修改用户和密码  在sqlyog......
  • 忘记Windows 10 登录密码
    Win10Win10不记得开机密码 这个(https://zhidao.baidu.com/question/376236858295220644.html)介绍了两种方法。先可以试一下第一种方法。第一种方法的思路是添加一个管理员级别的账号,用这个新的账号修改以前系统的账号。第二种方法的思路是用U盘做一个启动系统的PE系统,在PE系......
  • 安装 windows 10 无法安装到这个磁盘 启用了磁盘的控制器
           解决办法:               重启机器进入BIOS,还原BIOS默认设置。               具体操作:开机,按del进入BIOS,选择Exit下LoadSetupDefaults,回车,Yes,F10保存退出 将【Boot-Mode】修改为UEFI https://blog.csdn.net/u0......