【音视频通话】使用asp.net core 8+vue3 实现高效音视频通话

引言

    在三年前,写智能小车的时候,当时小车上有一个摄像头需要采集,实现推拉流的操作,技术选型当时第一版用的是nginx的rtmp的推拉流,服务器的配置环境是centos,2H4G3M的一个配置,nginx的rtmp的延迟是20秒,超慢,后来研究了SRS以及ZLMediaKit这两个开源的推拉流服务器,没记错的话,两个都是基于c++开发的,性能都很棒,后来更换了推拉流服务器,小汽车的延迟在一秒不到,性能大幅度提升,当时研究了一下,然后没有记录,这次使用SRS实现了音视频通话,以及共享桌面的功能,特此记录以及分享给大家。

技术概览

    本demo总共涉及到三个服务,部署环境是腾讯云的轻量服务器,配置是2H2G3M的服务器,CENTOS系统,nginx部署前端,docker部署后端以及SRS服务。

    SRS 

      SRS是一个开源的(MIT协议)简单高效的实时视频服务器,支持RTMP、WebRTC、HLS、HTTP-FLV、SRT、MPEG-DASH和GB28181等协议。 SRS媒体服务器和FFmpeg、OBS、VLC、 WebRTC等客户端配合使用,提供流的接收和分发的能力,是一个典型的发布 (推流)和订阅(播放)服务器模型。 SRS支持互联网广泛应用的音视频协议转换,比如可以将RTMP或SRT, 转成HLS或HTTP-FLV或WebRTC等协议。

      后端

      后端是一个基于net8.0基础框架开发的一个webapi的接口,前后端通讯使用的是signalr,用来实现不同用户之间的一个消息更改通知,本项目没有涉及到任何数据库方面的。

 

 

    前端

      前端是基于node20.16.0,vue3。其中,推拉流的地址和后端服务器的地址配置在configjs.json中配置,pushUrl是推流的地址,pullUrl是拉流的地址,apiUrl是后端接口的地址,signalrUrl是用来做前后端websocket通讯的一个地址。在apiUrl和signalrUrl中的端口需要和上方的后端运行的端口保持一致才可以互相访问通讯,具体配置文档查看下方图例

 

功能概览

    总体功能分为一下几个:

    设备检测/参数设置 

      这个页码主要是用来配置摄像头,并且检测摄像头是否可用,音频检测音频是否可用,并且配置音频设备,后续的音视频通话都是根据此处选择的设备进行推拉流,用户名称,由于本项目是一个demo,所以都是基于内存,用户是自己设置之后,在demo中与人通讯的一个标识;在这个页面配置好视频设备,音频设备,以及用户名称,就可以去后续的页面进行群聊或者单聊,或者桌面共享的功能。    

 

    群聊  

      群聊进入到页面,就可以看到已经存在的群聊信息,以及在线人数,可以进行加入或者删除群聊的操作,如果有新增的群组,此处也会使用Signalr进行同步更新获取最新的群组列表数据,此demo没有判断删除的时候权限问题以及如果有人正在群聊删除群组的问题,在设备检测页面没有选择音视频设备,也可以进入群组,可以查看有音视频的在线人员的一个音视频,如图所示,在上方输入要创建的群组名称,点击添加群组即可到如下页面,进入视频页面,会先去推流到服务器,以便下一个进入的人可以看到你的视频流,同时如果没有选择音视频设备,点击加入也是如下页面,并且该页面不会展示群组的在线人,可以从视频的摄像头上方可以查看是哪个用户的音视频。

    单聊

       单聊就是只有两个人进行音视频通话,同时也支持没有选择设备可以进行通话,没有添加文字聊天的支持,单聊列表,也会使用signalr进行同步更新,在用户设置了用户名称之后,在这里就可以看到列表数据的更新。点击通话就可以和在线的人员进行音视频通话,同时不能和自己通话,且选择的人如果在处于单聊状态中,也无法进行音视频通话,在选择了要进行通话的用户后,会进入到聊天页面,同时对方用户会收到一个提醒,是否接受音视频通话,可以拒绝,也可以接受,拒绝之后,请求方会退出到在线列表的页面,点击接受会进入到双方的一个音视频通话的页面,可以进行语音聊天,可以看对方的摄像头推送的视频流。同时接受之后,任意一方离开聊天,另外一方也会直接退出聊天页面。返回到用户在线列表页面中。

    共享桌面 

      共享桌面的操作和群组的一样,在上方输入共享桌面的名称,点击按钮,即可进入到共享桌面的页面中去。进入到页面,会提示需要共享的屏幕内容,可选整个屏幕,浏览器或者窗口都可以,同时也可以选择是否要共享此页面的音频,点击分享之后,即可看到共享的视频内容,右侧显示了参与人列表,并且如果选择了音频设备,也会采集语音推送,多个参与人进行语音聊天,语音会显示谁在发言,收到了谁的语音流。同时当共享的人,点击了停止共享,其他参与人也可以共享自己的桌面,点击了共享桌面按钮,其他参与人的共享桌面按钮会隐藏,并且他们会看到采集的你的屏幕的视频信息。

 

 程序配置

    关于配置方面,主要是前端的配置以及SRS的配置,前端方面的配置,在刚开始已经阐述过,主要是SRS的推拉流的配置,以及API和Signalr的地址配置,如果服务器是外网, 地址必须是外网服务器的地址,关于SRS的配置,在下载好SRS之后,SRS提供了默认的配置文件夹,文件夹名字是叫conf文件夹,里面提供了各种不同功能的conf配置文件,此处我们基于console.conf进行改造,下面的是console.conf的配置信息,第一行是listen,默认是1935,代表SRS启动的时候的RMP的直播服务端口。max_connection代表最大连接数量,默认是1000,srs_log_tank是日志的打印方式,默认是console,即控制台,可选配置有file和console,file是文件的输出形式,如果是file的形式,必须通过配置srs_log_file参数配置日志的打印文件的路径,默认是.objs/srs.log的文件。daemon,代表的是是否以后台的形式运行,on代表开启,off代表关闭。http_api,SRS提供了一些api,这个配置代表是否开启http_api,并且端口是8080。下方,展示了SRS官网提供的API导航。rtc_server启用webrtc的功能,端口是udp的8000,默认是8000,其中最后一个配置是candidata,如果是本机部署,这个可以不需要配置,如果是需要部署在外网服务器,那这个就需要设置成外网的服务器地址。

    SRS的视频推拉流,有虚拟主机的概念,默认提供了一个defaultVhost的虚拟主机在配置文件里,虚拟主机内有单独的关于主机的配置,hls代表开启hls的视频协议功能,http_remux,是否为http开启直播流服务,mout代表的是挂载的http流,可以是不同的格式,默认是flv,可选有ts,即后缀是.ts,有mp3,aac等协议。rtc代表是否给虚拟主机开启webrtc的功能,并且是否开启rtmp转rtc,以及rtc转rtmp的功能。http_hooks是SRS在有客户端推流或者拉流的时候配置的一个接口回调,这个回调可以是我们自己写的后端服务,这里的配置是我配置的我实际的后端服务的接口地址,可以根据自己的实际情况进行调整,enable代表是开启HOOK,publish是推流的回调,unpublish是停止推流的时候,play和stop是拉流的播放和停止回调。play是针对拉流的配置,gop_cache是否缓存最后一帧,如果开启,客户端能够快速播放,如果关闭,客户端拉取的一直都是最新的,queue_length是缓存的帧一秒缓存的队列长度,如果超过这个,会移除之前的帧,mw_latency,关于流的合并写入的延迟,毫秒级单位。Publish是推流的一个配置,mr是合并读取的延迟,毫米级单位。

    关于上面说了那么多的配置,主要的配置还是http_hooks的配置,这个配置,是SRS在接收到推流请求,或者停止推流,以及拉流,停止拉流的时候对我们后端服务的一个回调,enabled代表是否开启回调,publish是开始推流的回调,unpublish是停止推流,play和stop是客户端在播放流或者停止流的时候的一个回调,这里如果部署在外网,且srs和后端服务在一个服务器,此处的地址可以使用局域网的地址,与前端配置不同的是,前端的配置必须是外网的地址。

 

    以上关于所有的全面配置可以参考以下网址:

    http_api:http://ossrs.net/lts/zh-cn/docs/v6/doc/http-api。

    http_server:http://ossrs.net/lts/zh-cn/docs/v6/doc/http-server。

    rtc_server/rtc:http://ossrs.net/lts/zh-cn/docs/v6/doc/webrtc。

    hls:http://ossrs.net/lts/zh-cn/docs/v6/doc/hls。

 

 

部署

    上面说到,我们的发布环境是centos,nginx和docker,所以在安装好了nginx之后 需要对nginx进行一个端口反向代理的配置,这里我用的是443端口,在网上生成了一个ssl证书,因为如果是使用http开头的网址,浏览器的机制,会不让使用摄像头,需要更改浏览器的配置才可以使得http的网址可以访问摄像头,如果是在本地部署和调试此服务,建议使用127.0.0.1或者localhost等方式来获取摄像头的信息,因为浏览器的安全机制,非https并且url地址是IP非127.0.0.1或者localhost的方式获取摄像头是有限制,接触限制的方式是在浏览器地址输入chrome://flags,回车之后,在弹出的页面中搜索Insecure origins treated as secure,如图,回车之后,需要将服务的IP地址输入在下方输入框中,并且将disabled更改为enabled,在更改完成后,浏览器下方会出现图3的面板,点击Relauch重启浏览器即可通过IP地址访问服务,并且加载摄像头,如果是中文disable是禁用,enable是启用,Relauch是重启。

    所以基于上面http的问题,需要生成一个ssl证书,让web使用https进行访问。下面我放一份我的nginx的配置,在下面的443的配置中,指定了servicename,以及root指向的是我们发布的之后的web前端的地址。指定了index.html,以及ssl证书相关的配置地址,配置根路径访问的是web前端的index.html,然后将路由中包括api,pull,push的指向对应的端口,如上图的端口配置情况,1985,使用webrtc进行推流,8080,进行拉流的端口,video是signalr的反向代理地址。

    以上是我服务器自己部署的nginx的一个配置。

 

    

  

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;events {worker_connections 1024;
}http {log_format  main  '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log  /var/log/nginx/access.log  main;sendfile            on;tcp_nopush          on;tcp_nodelay         on;keepalive_timeout   65;types_hash_max_size 4096;map $http_upgrade $connection_upgrade {default upgrade;'' close;}include             /etc/nginx/mime.types;default_type        application/octet-stream;# Load modular configuration files from the /etc/nginx/conf.d directory.# See http://nginx.org/en/docs/ngx_core_module.html#include# for more information.include /etc/nginx/conf.d/*.conf;server {listen       80;listen       [::]:80;server_name  _;root         /video/dist/;index index.html;# Load configuration files for the default server block.include /etc/nginx/default.d/*.conf;location / {try_files $uri $uri/ /index.html;}error_page 404 /404.html;location = /404.html {}error_page 500 502 503 504 /50x.html;location = /50x.html {}}server {listen      443 ssl;listen       [::]:443;server_name  49.233.22.57;root         /video/dist/;index index.html;ssl_certificate /sslfile/49.233.22.57.crt; # ssl证书存储路径ssl_certificate_key /sslfile/49.233.22.57.private; # 秘钥存储路径# ssl的一些配置ssl_session_cache    shared:SSL:1m;ssl_session_timeout  5m;ssl_prefer_server_ciphers  on;ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #开启TLS协议location / {try_files $uri $uri/ /index.html;}location /api {proxy_pass http://10.2.20.12:5000;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto https;}location /rtc {proxy_pass http://10.2.20.12:1985;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto https;}location /pull {rewrite ^/pull/(.*)$ /$1 break;proxy_pass http://10.2.20.12:8080;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto https;}location /video {proxy_pass http://10.2.20.12:5000;proxy_set_header Host $host;proxy_set_header Upgrade $http_upgrade;proxy_cache_bypass $http_upgrade != '';proxy_set_header Connection $connection_upgrade;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto https;}}# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2;
#        listen       [::]:443 ssl http2;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }}

    后端部署在docker中, 环境是net8的开发环境,dockerfile配置如下,将发布后的文件和dockerfile放在一起,执行docker build -t videoimg .指令,打包docker镜像。记得后面有一个点.,回车之后,生成了videoimg的docker镜像,生成镜像后,需要启动容器,docker run --name videoc --security-opt seccomp=unconfined  -d -p 5000:8080 videoimg 回车之后即可启动了后端服务的容器,本机的端口是5000,需要防火墙或者云服务器开启5000端口,

#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 8080
EXPOSE 8081
COPY . .FROM base AS final
WORKDIR /app
ENTRYPOINT ["dotnet", "WebApplication1.dll"]

    docker启动SRS,如果SRS部署在外网服务器,需要在启动SRS容器之前,配置一个环境变量CANDIDATE="外网服务器IP地址",将外网的IP地址写入环境变量中,SRS启动会从中读取配置,也可以直接修改conf中关于CANDIDATE的配置直接更改为你的外网服务器的地址。配置好之后,启动SRS,docker run --rm  --name srs  -it -d -p 1935:1935 -p 1985:1985 -p 8080:8080 -p 1990:1990 -p 8088:8088 -p 8000:8000/udp -v /video/conf:/conf --env CANDIDATE=$CANDIDATE     registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5 ./objs/srs -c /conf/console.conf  上面的指令,-v是将容器内部的conf文件夹挂载出来,然后在后面指定使用了console.conf作为启动的配置文件,并且将端口信息暴露出来,推拉流,以及web服务器需要使用这些端口。

    SRS提供了一个web管理系统,防火墙等配置好之后,在浏览器输入IP:8080即可打开如下页面,在控制台可以看到视频的推拉流信息,以及流量的流入和流出。

端口配置

    服务器需要开启一下端口

    1:后端服务的端口,例如本例子的5000端口

    2:SRS相关端口:1935,1985,8080,1990,8088,8000/udp

代码和详细Windows文档地址

    关于更多的详细解读,可以查看写好的windows的文档部署地址,除了部署方式的差异,其余都一样。

    git地址:https://gitee.com/cxd199645/audio-video.git

总结

     关于做一个音视频通话的技术分享就到这里了,如果又不懂的,可以添加QQ/WX:934550201.

 

1. SRS

SRS是一个开源的(MIT协议)简单高效的实时视频服务器,支持RTMP、WebRTC、HLS、HTTP-FLV、SRT、MPEG-DASH和GB28181等协议。 SRS媒体服务器和FFmpegOBSVLC WebRTC等客户端配合使用,提供流的接收和分发的能力,是一个典型的发布 (推流)和订阅(播放)服务器模型。 SRS支持互联网广泛应用的音视频协议转换,比如可以将RTMPSRT 转成HLSHTTP-FLVWebRTC等协议。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/788479.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

免费、开源、详细完整的unity游戏、游戏源码、教程:人工智能分析和处理对话的美好三维世界(定期更新)

免费、开源、详细完整的unity游戏、游戏源码、教程:人工智能分析和处理对话的美好三维世界。这份unity游戏、游戏源码、教程:完全免费,完全开源,完整详细,通俗易懂,适合初学者入门,定期更新。 我不想和任何人说话,任何人不要跟我说话,不要打扰我,我要安安静静的写。我…

小企业必备:优选局域网文档管理软件推荐

国内外主流的10款局域网文档管理软件对比:1.PingCode;2.Worktile;3.语雀;4.联想Filez企业网盘;5.亿方云;6.黑域基地;7.Joplin;8.MediaWiki;9.TiddlyWiki;10.Zim Wiki。在处理局域网文档时,企业常常面临着文件管理不系统、数据安全性差等问题,这不仅影响团队协作效率…

机器学习之——决策树信息熵计算[附加计算程序]

0 前言本文主要讲述了决策树背后的信息熵的公式含义及计算方式,并列举出多道例题帮助理解。1 信息熵的定义 1.1 信息熵公式笔者使用下图(1-1)直观理解信息熵的含义。信息熵越大,表示该随机变量的不确定性越高。对于均匀分布,信息熵达到最大值。 1.2 证明:对于均匀分布,信息…

phpinclude-labs做题记录

Level 1 file协议payload:?wrappers=/flag Level 2 data协议 去包含data协议中的内容其实相当于进行了一次远程包含,所以data协议的利用条件需要 php.ini 中开启 allow_url_fopen 和 allow_url_include GET: ?wrappers=, 然后 POST:helloctf=system(cat /flag); Level 3 dat…

数据结构学习第一周

本文需要掌握的知识 1.认识数据结构 2.了解数据结构(逻辑结构)的分类 3.内存储器模型以及分配方式(物理结构) 4.认识Node类 5.简单了解泛型1 .数据结构(D-S/Data Structure) 1.1简介 1.1.1数据 分为原子数据和复合数据 1.1.2结构 分为逻辑结构和物理结构数据结构是由数据和数…

用 Higress AI 网关降低 AI 调用成本 - 阿里云天池云原生编程挑战赛参赛攻略

我们要在 Higress 网关中编写 WebAssembly(wasm)插件,使得在 http 请求的各个阶段(requestHeader,requestBody,responseHeader,responseBody)能够将相应的请求或返回捕获进行业务逻辑的处理。具体到本比赛,主要需要实现的是缓存对大模型的请求(openai 接口的形式)在…

科研项目管理工具选型全攻略

国内外主流的 10 款科研院所项目管理系统对比:PingCode、Worktile、云效、Tower 、Zoho Projects、Notion、Wrike、ClickUp、Asana、Teambition。在科研院所的日常运营中,项目管理系统的选择显得尤为重要。选择不当可能导致资源浪费、进度延误甚至项目失败,这是每个科研团队…

ensp使用交换机配置svi连通网段

ensp使用交换机配置svi连通网段 实验目的 如下图所示,PC1、PC2、PC3分别位于不同网段,使用S5700型号交换机连接,目前需要配置交换机和主机,主机能够互相连通。常用命令un in en:关闭信息通知 dis ip int b:显示端口ip配置情况(brief模式) dis ip routing-table:显示路…

B 端产品未来几年的发展趋势

未来几年,B 端产品领域将面临着诸多挑战和机遇。人工智能与机器学习的深度融合、云计算与容器化技术的持续发展、用户体验与设计的重要性日益凸显、数据安全与隐私保护的挑战与机遇、行业垂直化与专业化发展以及敏捷开发与持续交付的普及等趋势,将对 B 端产品经理提出更高的要…

postgresql下Schema和DataBase

database —> schema —> table 1.同一个实例下,不同database是不能相互访问的,即独立的。 2.同一个数据库,不同模式下的表是可以相互访问,即可共享的 3.不同模式下,表名可以是一样。也就是表在模式下是独立。 ##授权某个库下的某个模式下有创建表的权限grant creat…

使用 nuxi add 快速创建 Nuxt 应用组件

title: 使用 nuxi add 快速创建 Nuxt 应用组件 date: 2024/8/28 updated: 2024/8/28 author: cmdragon excerpt: 通过使用 nuxi add 命令,你可以快速创建 Nuxt 应用中的各种实体,如组件、页面、布局等。这可以极大地提高开发效率,减少手动创建文件的工作量。希望本文的示例…

Apache RocketMQ 批处理模型演进之路

RocketMQ 的目标,是致力于打造一个消息、事件、流一体的超融合处理平台。这意味着它需要满足各个场景下各式各样的要求,而批量处理则是流计算领域对于极致吞吐量要求的经典解法,这当然也意味着 RocketMQ 也有一套属于自己风格的批处理模型。作者:谷乂 RocketMQ 的目标,是致…