C# 查询腾讯云直播流是否存在的API实现

应用场景

在云考试中,为防止作弊行为的发生,会在考生端部署音视频监控系统,当然还有考官方监控墙系统。在实际应用中,考生一方至少包括两路直播流:

(1)前置摄像头:答题的设备要求使用笔记本电脑,使用支持H5的WEB浏览器,并授权打开前置摄像头,产生一路直播流,以监控考生正面活体人像的行为,并进行录像留证。

(2)后方摄像:使用其它可用的摄像设备,如手机、平板等,打开摄像头,产生一路直播流,以监控考生背面、笔记本及前方音视频情况,并进行录像留证。

如果不考虑各种成本,还可以使用屏幕共享功能,以录制笔记本电脑屏幕上的一切操作行为。

腾讯云实时音视频

我们的云考试监控部分的开发采用基于腾讯云WebRTC的技术实现,其产品以多人音视频通话和低延时互动直播两大场景,通过开放API,帮助开发者快速搭建低成本、低延时、高品质的音视频互动解决方案。

具体可访问该网址进行了解:https://cloud.tencent.com/document/product/647

产品架构

下图是我们基于腾讯云产品架构图的部分采用和实现方案:

 关于RoomID

当创建直播流的时候,我们可以简单的理解为,首先需要创建一个房间(音视频聊天室),该房间就应该分配一个唯一的房号,这房号就是RoomID。

RoomID是一组10位数字的字符串值,但在实际应用中,第一位不要为0,否则腾讯会自动转数值,而变成9位数字,这个位数是不合法的。但这种情况在微信小程序的RTC版本里不会出现。

另外,数值的范围最好在1000000000-5000000000这间,否则也有可能报错误,以上都是曾经踩到的一些坑点,在此分享。

需求示例 

考试产品可以提供二维码或接口接入的形式,访问首页如下图演示:

核对信息无误后,创建RoomID和用户名,用户名按实际业务需要创建,比如前置为 roomid_1,后置为 roomid_2,从名称上可以区分前后直播流即可。 进入考试如下图:

创建了前置摄像直播流,提示用户用手机微信扫描以打开后方摄像头功能,如果成功则可以进行答题,如下图:

现在的需求是,如果考生在考试过程中断开其中一路或全部断开则提示其重新连接摄像头。我们采用了腾讯云给出的一种解决方案,利用其API定时查询对应的直播流是否存在,如果不存在则进行提示,以下图为例 :

 

关键代码

API实现

//查询在线直播流,参数1:部分或全部流名称,页码         
//方法返回LVBStream类对象的ArrayList集合   
public ArrayList SearchOnlineStream(string partname,string PageNum)
            {
                ArrayList data = new ArrayList();
                //请求地址
                string settingUrl = "https://live.tencentcloudapi.com/";
                //应用ID和应用key
                string secretId = 应用ID;
                string secretKey = 应用key;
                //时间戳
                string timesTamp = GetTimeStamp();
                //Nonce
                var nonce = new Random().Next(10000, 99999);
                //拼接参数 abcdefghijklmnopq
                string paramsStr = string.Format(@"Action=DescribeLiveStreamOnlineList&Nonce={0}&PageNum=1&PageSize=100&Region=ap-guangzhou&SecretId={1}&SignatureMethod=HmacSHA1&Timestamp={2}&Version=2018-08-01",
                     nonce, secretId, timesTamp);
                //生成签名参数
                //                      string requestText = settingUrl + "?" + paramsStr;
                string requestText = "POST" + settingUrl.Replace("https://", "") + "?" + paramsStr;
                //获得请求签名
                string signText = GetHmacSha1Sign(secretKey, requestText);
                //这里一定要进行URL编码,不然调用API会报错
                signText = HttpUtility.UrlEncode(signText, Encoding.UTF8);
//                string text = HttpUtility.UrlEncode(SearchText, Encoding.UTF8);
                paramsStr = string.Format(@"Action=DescribeLiveStreamOnlineList&Nonce={0}&PageNum=1&PageSize=100&Region=ap-guangzhou&SecretId={1}&Signature={2}&SignatureMethod=HmacSHA1&Timestamp={3}&Version=2018-08-01",
                      nonce, secretId, signText, timesTamp);
                //请求腾讯API,返回身份证信息
                string resultStr = SendRequest(settingUrl, paramsStr);
                if (resultStr.IndexOf("TotalNum") != -1)
                {
                    Newtonsoft.Json.Linq.JObject jsonObj = Newtonsoft.Json.Linq.JObject.Parse(resultStr);
                    //"Response":{"MediaInfoSet":[],"TotalCount":0, "RequestId":"85f181fc-d76f-42bb-82d8-7ac4d5ff432a"}}
                    int total = jsonObj["Response"]["OnlineInfo"].Count();

                    int totalpage =int.Parse(jsonObj["Response"]["TotalPage"].ToString());
                    for (int i = 0; i < total; i++)
                    {
                        LVBStream ls = new LVBStream();
                        try
                        {
                           
                            ls.StreamName = jsonObj["Response"]["OnlineInfo"][i]["StreamName"].ToString();
                            ls.AppName = jsonObj["Response"]["OnlineInfo"][i]["AppName"].ToString();
                            ls.DomainName = jsonObj["Response"]["OnlineInfo"][i]["DomainName"].ToString();
                            if (partname != "")
                            {
                                if (ls.StreamName.IndexOf(partname) != -1)
                                {
                                    data.Add(ls);
                                }
                            }
                            else
                            {
                                data.Add(ls);
                            }
                        }
                        catch (Exception e) { }
                    }
                    if (totalpage > 1 && int.Parse(PageNum) == 1)
                    {
                        for (int i = int.Parse(PageNum) + 1; i <= totalpage; i++) {
                            ArrayList data2 = new ArrayList();
                            data2 = SearchOnlineStream(partname, i.ToString());
                            foreach (CoWeixin.wxLiveManager.TencentCloud.LVBStream lvb in data2)
                            {
                                data.Add(lvb);
                            }
                        }
                    }
                    return data;
                }
                return data;
} //search media
public class LVBStream
{
                 public string StreamName = "";
                 public string AppName = "";
                 public string DomainName = "";

                 public LVBStream()
                 {
                 }
}
          public static string GetTimeStamp()
          {
              TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
              return Convert.ToInt64(ts.TotalSeconds).ToString();
          }
  
          /// <summary>
          /// HMAC-SHA1加密返回签名
          /// </summary>
          /// <param name="secret">密钥</param>
          /// <param name="strOrgData">源文</param>
          /// <returns></returns>
          public static string GetHmacSha1Sign(string secret, string strOrgData)
         {
              var hmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secret));
              var dataBuffer = Encoding.UTF8.GetBytes(strOrgData);
              var hashBytes = hmacsha1.ComputeHash(dataBuffer);
              return Convert.ToBase64String(hashBytes);
          }
  
         public static string SendRequest(string url, string completeUrl)
          {
              ServicePointManager.SecurityProtocol = (SecurityProtocolType)192 | (SecurityProtocolType)768 | (SecurityProtocolType)3072;


              HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
              request.Method = "POST";
              request.ContentType = "application/x-www-form-urlencoded";
              request.ProtocolVersion = HttpVersion.Version10;
              request.Host = url.Replace("https://", "").Replace("/", "");
              byte[] data = Encoding.UTF8.GetBytes(completeUrl);
              request.ContentLength = data.Length;
              Stream newStream = request.GetRequestStream();
              newStream.Write(data, 0, data.Length);
              newStream.Close();
              HttpWebResponse response = null;
              string content;
              try
              {
                  response = (HttpWebResponse)request.GetResponse();
                 StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                 content = reader.ReadToEnd();
             }
             catch (WebException e)
             {
                 response = (HttpWebResponse)e.Response;
                 using (Stream errData = response.GetResponseStream())
                 {
                     using (StreamReader reader = new StreamReader(errData))
                     {
                         content = reader.ReadToEnd();
                     }
                 }
             }
             return content;
         }

JS调用的服务端方法

    [WebMethod]
//统计在线流情况,传递RoomID房间号
    public static string onlineLiveCount(string roomid)
    {
        string tip = "";

        ArrayList rv = SearchOnlineStream(roomid);
            bool isfront = false;
            bool isback = false;
        foreach (LVBStream lvb in rv)
        {
            if (lvb.StreamName.IndexOf("_1_main")!=-1)  //根据自己的命名规则判断 
            {
                isfront = true;
            }
            if (lvb.StreamName.IndexOf("_2_main") != -1) //根据自己的命名规则判断 
            {
                isback = true;
            }
        }
        if (rv.Count < 2)
        {
            if (isfront == false)
            {
                tip += "未监控到前方摄像头。<br>";
            }
            if (isfront==true&&isback == false)
            {
                tip += "未监控到后方摄像头。<br>";
            }
        }
        return tip;
    }

小结

以上提供的代码仅供参考,在实际的应用中,我们要编写符合自己业务的逻辑,还要考虑实际的运营成本。有关腾讯RTC产品的价格情况,可以访问:https://cloud.tencent.com/document/product/647/17157

以上就是自己的一些分享,时间仓促,不妥之处还请大家批评指正!

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot + EasyUI Datebox和Datetimebox样例

使用EasyUI的Datebox和Datetimebox组件&#xff0c;并对其进行适当的改造&#xff0c;比如更改日期格式、设置默认值或者将当前时间设置为默认值。 一、运行结果 二、实现代码 1.代码框架 2.实现代码 SpringBootMainApplication.java: package com.xj.main;import org.spri…

奇安信360天擎getsimilarlist存在SQL注入漏洞

奇安信360天擎getsimilarlist存在SQL注入漏洞 一、产品描述二、漏洞描述三、漏洞复现1.手动复现2.自动化复现①nulei扫描yaml ②小龙POC检测工具下载地址 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的…

oled显示器程序(IIC)从stm32f103移植到stm32f429出现bug不显示-解决移植失败问题

出现问题处&#xff1a; 刚开始更换了这两行代码&#xff0c;然后更换位置后&#xff0c;oled正常显示&#xff0c;如下为正确顺序 I2C_Configuration();//配置CPU的硬件I2COLED_Init();//OLED初始化 在这段代码中&#xff0c;I2C_Configuration() 函数用于配置CPU的硬件 I2C…

什么变量能够影响苦艾酒的味道?

没有一个答案可以描述每种苦艾酒的味道&#xff0c;因为每个生产商生产的苦艾酒都不一样。甜苦艾酒的味道与干苦艾酒不同&#xff0c;即使在这些类别中&#xff0c;甜的和干的苦艾酒的味道也会彼此不同&#xff0c;这取决于制造商、他们使用的草药和植物药的类型、他们用这些植…

如何估算业务需要多少代理IP量?

在互联网相关的行业中&#xff0c;很多业务都需要用到代理IP工具&#xff0c;比如数据采集、市场调查、SEO优化、品牌保护、跨境运营等&#xff0c;可以说代理IP已成为许多业务中不可或缺的一部分。代理IP可以帮助用户隐蔽真实IP地址&#xff0c;提高网络活动的范围和安全性&am…

会打字就能编程,自动写代码的ai助手 | 通义灵码

通义灵码介绍 通义灵码是一款由阿里云出品的智能编码辅助工具。 它基于通义大模型&#xff0c;可以提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码注释生成、代码解释、研发智能问答、异常报错排查等能力。 它支持Java、Python、Go、C/C、JavaScript、Type…

机器人阻抗与导纳控制的区别

机器人自身的非线性动力学&#xff08;由柔软性引起的&#xff09;导致控制精度下降&#xff0c;因此难以描述准确的动力学。 导纳控制和阻抗控制都是基于位置与力关系的模式&#xff0c;被认为具有鲁棒性和安全性。然而&#xff0c;当机器人与刚体接触时&#xff0c;导纳控制常…

【Qt之QVariant】使用

介绍 QVariant类类似于最常见的Qt数据类型的联合。由于C禁止联合类型包括具有非默认构造函数或析构函数的类型&#xff0c;大多数有趣的Qt类不能在联合中使用。如果没有QVariant&#xff0c;则QObject::property()和数据库操作等将会受到影响。 QVariant对象同时持有一个单一…

基于单片机的多层电梯控制仿真系统

**单片机设计介绍&#xff0c; 基于单片机的多层电梯控制仿真系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的多层电梯控制仿真系统是一个复杂的系统&#xff0c;它需要结合单片机技术、控制理论、电子技术以及人…

使用swagger-typescript-api

引言 前后端分离大致是这样的 后端&#xff1a;控制层 / 业务层 / 数据操作层前端&#xff1a;控制层 / 视图层 前后端的控制层&#xff0c;实际上就是前后端接口的对接 前后端分离&#xff0c;实现了更好地解耦合&#xff0c;但也引入了接口对接的过程&#xff0c;这个过程…

C++ STL - map 与 multimap用法和区别

目录 一、概述 二、用法 2.1、插入 2.2、拷贝与赋值 2.3、查找 2.4、删除 2.5、完整代码 三、其他成员类型 一、概述 map 与 multimap是存储key-value&#xff08;键-值 对&#xff09;类型的容器。不同之处在于&#xff1a;map只允许key与 value一一对应&#xff1b;…

asp.net core mvc之路由

一、默认路由 &#xff08;Startup.cs文件&#xff09; routes.MapRoute(name: "default",template: "{controllerHome}/{actionIndex}/{id?}" ); 默认访问可以匹配到 https://localhost:44302/home/index/1 https://localhost:44302/home/index https:…

PTL货位指引标签为仓储管理打开新思路

PTL货位指引标签是一种新型的仓储管理技术&#xff0c;它通过LED灯光指引和数字显示&#xff0c;为仓库管理带来了全新的管理思路和效率提升&#xff0c;成为现代物流仓库管理中的重要工具。 首先&#xff0c;PTL货位指引标签为仓储管理业务带来了管理新思路。传统的仓库管理中…

OFDM深入学习及MATLAB仿真

文章目录 前言一、OFDM 基本原理及概念1、OFDM 简介2、子载波3、符号4、子载波间隔与符号长度之间的关系 二、涉及的技术1、保护间隔2、交织3、信道编码4、扩频5、导频6、RF&#xff08;射频&#xff09;调制7、信道估计 三、变量间的关系四、IEEE 802.11a WLAN PHY 层标准五、…

matlab中的mapminmax函数初步理解和应用

matlab中的mapminmax函数初步认识 一、mapminmax 顾名思义&#xff1a;映射最大最小 二、语法及举例 2.1 语法1 [Y,PS] mapminmax(X) 将矩阵X映射形成矩阵Y, Y中每行中的最小值对应-1&#xff0c;最大值对应1。PS是一个包含映射信息的结构体。 举例&#xff1a; clc cle…

Jupyter Notebook 闪退

造成这个的原因非常非常多&#xff01; 比如什么环境变量没有配置&#xff0c;或者说jupyter和python版本不兼容&#xff0c;库不兼容等等。 但是我呢&#xff0c;以上都不是。 我是因为手残&#xff0c;删掉了不该删的文件&#xff1a; 这个操作就是打开"Anaconda Prom…

在react中组件间过渡动画如何实现?

一、是什么 在日常开发中&#xff0c;页面切换时的转场动画是比较基础的一个场景 当一个组件在显示与消失过程中存在过渡动画&#xff0c;可以很好的增加用户的体验 在react中实现过渡动画效果会有很多种选择&#xff0c;如react-transition-group&#xff0c;react-motion&…

Vb6 TCP Server服务端监听多个RFID读卡器客户端上传的刷卡数据

本示例使用设备介绍&#xff1a;WIFI无线4G网络RFID云读卡器远程网络开关物流网阅读器TTS语音-淘宝网 (taobao.com) Option ExplicitConst BUSY As Boolean False 定义常量 Const FREE As Boolean TrueDim ConnectState() As Boolean 定义连接状态 Dim ServerSendbuf(…

Kubernetes实战(四)-部署docker harbor私有仓库

1 Docker原生私有仓库Registry 1.1 原生私有仓库Registry概述 Docker的仓库主要分两类&#xff1a; 私有仓库公有仓库 共有仓库只要在官方注册用户&#xff0c;登录即可使用。但对于仓库的使用&#xff0c;企业还是会有自己的专属镜像&#xff0c;所以私有库的搭建也是很有…

数字化广告运营,小迈科技的关键一步

数据驱动广告运营是小迈科技提升整体经营效率、构建竞争优势的重要选择。 截止目前&#xff0c;小迈科技已经完成了数据驱动的广告运营体系的搭建&#xff0c;并通过与神策数据的深入合作&#xff0c;借力神策客户旅程分析平台&#xff0c;在广告投放、运营活动等各个环节实现了…