1:开通阿里云直播服务
2:进入到直播控制台
3:点击域名管理----添加推流域名
同样方式添加播流域名,根据需要选择加速区域
4:返回列表
注意CNAME和直播中心
复制CNAME参数跳转到域名控制台,域名列表中选择对应域名,然后点击解析,再点击添加记录
返回列表启用该域名,同样的方式配置播流,注意直播中心要选择同一个中心
5:返回直播控制台--》域名管理---》配置域名
配置播流和推流关联,播流和推流域名配置中有访问控制,开启url鉴权,会看到主KEY,播流和推流主KEY开发中用得到
然后点击直播管理中的地址生成
appName和StreamName自定义即可,StreamName就算是房间id吧,个人理解,然后点击开始生成
然后得到推流和播流地址
下载阿里推荐的obs推流工具和vlc播放工具
添加一个场景 、添加一个来源选择显示器采集或者媒体源,点击控件中的设置选择推流
确定之后点击开始推流
然后复制播流地址打开VLC点击媒体----》打开网络串流,输入播流地址,我在测试的时候除了RTMP格式的除外其他的都不能播放,
代码直接复制阿里云调试中的
@ApiOperation("直播鉴权")
@PostMapping("/authentication")
public CommonResult authentication(String roomId) {
String pullDomain = videoClientConfig.getPullDomain();
String pushDomain = videoClientConfig.getPushDomain();
String appName = videoClientConfig.getAppName();
String pullIdentKey = videoClientConfig.getPullIdentKey();
String pushIdentKey = videoClientConfig.getPushIdentKey();
Integer identUrlValidTime = videoClientConfig.getIdentUrlValidTime();
String pushUrl = AliyunLiveUtil.createPushUrl(identUrlValidTime, pushDomain, appName, roomId, pushIdentKey);
Map<String, String> map = AliyunLiveUtil.createPullUrl(pullDomain, appName, roomId, pullIdentKey, identUrlValidTime);
map.put("pushUrl",pushUrl);
log.info("-------------拉流域名={}", JSONObject.toJSONString(map));
return CommonResult.success(map);
}
参数roomId是StreamName
/**
* 根据源id创建该id的推流url
*
* @param identUrlValidTime 鉴权url的有效时间(秒),默认30分钟,1800秒
* @param pushDomain 推流域名
* @param appName 直播测试appName
* @param streamName 直播测试streamName
* @param pushIdentKey 推流鉴权url key
* @return
*/
public static String createPushUrl(Integer identUrlValidTime, String pushDomain, String appName, String streamName, String pushIdentKey) {
// 计算过期时间
String timestamp = String.valueOf((System.currentTimeMillis() / 1000) + identUrlValidTime);
// 组合推流域名前缀
// rtmp://{pushDomain}/{appName}/{streamName}
String rtmpUrl = StrUtil.format("rtmp://{}/{}/{}", pushDomain, appName, streamName);
log.info("----------推流域名前缀,rtmpUrl={}",rtmpUrl);
// 组合md5加密串
// /{appName}/{streamName}-{timestamp}-0-0-{pushIdentKey}
String md5Url = StrUtil.format("/{}/{}-{}-0-0-{}", appName, streamName, timestamp, pushIdentKey);
// md5加密
String md5Str = DigestUtil.md5Hex(md5Url);
log.info("---------md5加密串,md5Url={}------md5加密结果,md5Str = {}",md5Url,md5Str);
// 组合最终鉴权过的推流域名
// {rtmpUrl}?auth_key={timestamp}-0-0-{md5Str}
String finallyPushUrl = StrUtil.format("{}?auth_key={}-0-0-{}", rtmpUrl, timestamp, md5Str);
log.info("--------------最终鉴权过的推流域名={}",finallyPushUrl);
return finallyPushUrl;
}
/**
* 创建拉流域名,key=rtmpUrl、flvUrl、m3u8Url,代表三种拉流类型域名
*
* @param pullDomain 拉流域名
* @param appName 应用名称
* @param streamName 流名称
* @param pullIdentKey 拉流鉴权url key
* @param identUrlValidTime 鉴权url的有效时间(秒),默认30分钟,1800秒
* @return
*/
public static Map<String, String> createPullUrl(String pullDomain, String appName, String streamName, String pullIdentKey, Integer identUrlValidTime) {
// 计算过期时间
String timestamp = String.valueOf((System.currentTimeMillis() / 1000) + identUrlValidTime);
// 组合通用域名
// {pullDomain}/{appName}/{streamName}
String pullUrl = StrUtil.format("{}/{}/{}", pullDomain, appName, streamName);
log.info("-----createPullUrl-------组合通用域名,pullUrl={}",pullUrl);
// 组合md5加密串
// /{appName}/{streamName}-{timestamp}-0-0-{pullIdentKey}
String md5Url = StrUtil.format("/{}/{}-{}-0-0-{}", appName, streamName, timestamp, pullIdentKey);
String md5FlvUrl = StrUtil.format("/{}/{}.flv-{}-0-0-{}", appName, streamName, timestamp, pullIdentKey);
String md5M3u8Url = StrUtil.format("/{}/{}.m3u8-{}-0-0-{}", appName, streamName, timestamp, pullIdentKey);
// md5加密
String md5Str = DigestUtil.md5Hex(md5Url);
String md5FlvStr = DigestUtil.md5Hex(md5FlvUrl);
String md5M3u8Str = DigestUtil.md5Hex(md5M3u8Url);
log.info("-------createPullUrl----------md5加密串,md5Url ={},------ md5加密结果,md5Str = {}",md5Url, md5Str);
log.info("-------createPullUrl----------md5加密串,md5FlvUrl ={},------ md5加密结果,md5FlvStr = {}",md5FlvUrl,md5FlvStr);
log.info("-------createPullUrl----------md5加密串,md5M3u8Url={},------ md5加密结果,md5M3u8Str= {}",md5M3u8Url,md5M3u8Str);
// 组合三种拉流域名前缀
// rtmp://{pullUrl}?auth_key={timestamp}-0-0-{md5Str}
String rtmpUrl = StrUtil.format("rtmp://{}?auth_key={}-0-0-{}", pullUrl, timestamp, md5Str);
// http://{pullUrl}.flv?auth_key={timestamp}-0-0-{md5FlvStr}
String flvUrl = StrUtil.format("http://{}.flv?auth_key={}-0-0-{}", pullUrl, timestamp, md5FlvStr);
// http://{pullUrl}.m3u8?auth_key={timestamp}-0-0-{md5M3u8Str}
String m3u8Url = StrUtil.format("http://{}.m3u8?auth_key={}-0-0-{}", pullUrl, timestamp, md5M3u8Str);
log.info("-------createPullUrl----最终鉴权过的拉流rtmp域名 ={}",rtmpUrl);
log.info("-------createPullUrl----最终鉴权过的拉流flv域名 ={}",flvUrl);
log.info("-------createPullUrl----最终鉴权过的拉流m3u8域名 ={}",m3u8Url);
HashMap<String, String> urlMap = new HashMap<String, String>();
urlMap.put("rtmpUrl", rtmpUrl);
urlMap.put("flvUrl", flvUrl);
urlMap.put("m3u8Url", m3u8Url);
return urlMap;
}
@Getter
@Setter
public class VideoClientConfig {
// private static String liveEdge = "www.yourLiveEdge.club";
// private static String liveVideo = "www.yourLiveVideo.club";
/**
* 推流域名
*/
@Value("${aliyun.pushDomain}")
private String pushDomain;
/**
* 播流域名
*/
@Value("${aliyun.pullDomain}")
private String pullDomain;
@Value("${aliyun.regionId-bj}")
private String regionIdbj;
@Value("${aliyun.regionId-sh}")
private String regionIdsh;
@Value("${aliyun.accessKeyID}")
private String accessKeyID;
@Value("${aliyun.accessKeySecret}")
private String accessKeySecret;
@Value("${aliyun.appName}")
private String appName;
@Value("${aliyun.pullIdentKey}")
private String pullIdentKey;
@Value("${aliyun.pushIdentKey}")
private String pushIdentKey;
@Value("${aliyun.streamName}")
private String streamName;
@Value("${aliyun.identUrlValidTime}")
private Integer identUrlValidTime;
@Value("${aliyun.liveDomainType}")
private String liveDomainType;
/**
* Initialization 初始化公共请求参数
*/
public DefaultAcsClient initialization() {
// 初始化请求参数,可用地区码,key,secret
DefaultProfile profile = DefaultProfile.getProfile(regionIdbj, accessKeyID, accessKeySecret);
DefaultAcsClient defaultAcsClient = new DefaultAcsClient(profile);
return defaultAcsClient;
}
然后在控制器中:
@Autowired
private VideoClientConfig videoClientConfig;
参数配置
aliyun:
pullIdentKey: 123456
pushIdentKey: 789012
appName: test
identUrlValidTime: 1800
regionId: cn-beijing
# 推流域名
pushDomain: push.test.com
# 域名业务类型。取值:liveVideo:播流域名 liveEdge:边缘推流域名
liveDomainType: liveVideo
# 播流域名
pullDomain: pull.test.com
# 推流回调地址
pushNotify: http://test.test.com/live/notify/push
accessKeyID: 123456789
accessKeySecret: 987654321
pullIdentKey: 123456
pushIdentKey: 789012
这两个参数分别是直播控制台的域名管理中的播流域名和推流域名中的主KEY,如果不一致的话不影响鉴权,但是最后输出的播流和推流地址在工具中不能使用,要么不能正常播放。
其他代码就可以从阿里云调试中copy了
据药融云研发数据库统计,截至2023年1月pd-1相关药物研发有1900多种,其中全球上市共有15个药品,在中国上市的有11个分别为:帕博利珠单抗、纳武利尤单抗、特瑞普利单抗、派安普利单抗、替雷利珠单抗、信迪利单抗、斯鲁利单抗、卡度尼利单抗、赛帕利单抗、卡瑞利珠单抗、普特利单抗,剩余4种国外上市的药品为:dostarlimab、cemiplimab、prolgolimab、BMS-986213,其上市药品的治疗领域主要为肿瘤,其次为感染和血液系统。
DirectX修复工具是一款专用于修复系统异常的工具,DirectX修复工具还是一款使用简单易上手操作且绿色、可免安装的修复工具。使用DirectX修复工具可自动更新C++组件且完美修复0xc000007b问题异常。如果你的电脑出现了DirectX的异常问题,可直接下载DirectX修复工具进行修复解决。...
在项目五中,我们完成了抓取在线TS数据流、分析并剥离各层PDU、将TS流数据写入文件进行播放的操作。在此基础上,我们这次将写文件操作换成转发操作,将收到的TS流数据包转发给物理主机,在物理主机上在线播放视频流。发送数据包我们就要用到Socket编程了,奉上传送门:https://blog.csdn.net/canger_/article/details/81460943我们所需要做的,就是在抓...
摄像头的接口资料:MIPI-DSI、MIPI-CSI、LVDS等接口解析_夜风的博客-程序员秘密开发板上的FMC接口资料:FMC标准以及FMC连接器介绍_woshizzai的博客-程序员秘密_fmc接口说明:这个示例程序是基于ZCU102开发板的,Xilinx并没有在ZCU106开发板上搞这个示例程序的计划,因此这篇文章要做的就是把ZCU102的示例程序移植到ZCU106上面去,因此有很多需要注意的地方。(ZCU104也同理)示例程序的目的就是从摄像头采集图像,然后用显示器显示出来。参考资
1.注意:根据不同分辨率写Value,layout,drawable。从而做到适配2.布局<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res-auto" xmlns:app=
介绍tiptap编辑器基于Prosemirror,完全可扩展且无渲染。可以轻松地将自定义节点添加为Vue组件。Githubhttps://github.com/scrumpy/tiptap为什么使用tiptap?市面上有不少富文本编辑器,但大多数可能并不能满足你的需求。编辑器应该易于扩展,并且不应基于旧的依赖项(例如jQuery)。对于React...
1、圈子点赞实现分析在圈子功能中,对于圈子的点赞、喜欢、评论等均可理解为用户对动态的评论(Comment),在quanzi_comment表中使用commentType进行区分。在具体的实现中,需要将点赞数、某用户是否点赞等数据保存到Reds中,以减轻MongoDB的压力。具体存储结构如下:说明:在Redis的存储结构中,采用的是Hash存储,这样的好处就在于一条动态的点赞、喜欢等数据都会集中的存储到一起,从而减少了Redis中数据条数。2、点赞2.1、定义枚举为了规范使用Comment
您已经决定要更好地处理网络。也许您正在考虑设置一些监视。但是随后您发现需要配置名为SNMP的东西,这就是问题开始的时间。有一些您从未听说过的配置事项:OID,MIB,陷阱,通知,轮询和版本。这些东西到底是什么东西,您是否需要知道这一切?在SNMP系列的第一部分中,您将学习基础知识,并了解它如何帮助您使网络更可靠,更易于管理。SNMP到底是什么?SNMP代表简单网络管理协议。这是监视几乎所有制造商(从瞻博网络,思科,微软,Unix以及两者之间的所有产品)的硬件和软件的标准方法。SNMP仅需要.
这是有关如何使用EOS内置的http_plugin设置一个安全的HTTPS API的指南。自2018-04-27 release版发布以来SSL开始支持。首先,你必须使用DAWN-2018-04-27-ALPHA以上版本。如果你运行nodeos --version它应该输出2594537369。否则你必须进行版本更新。要更新,请运行你的eos repo拷贝:$ cd [EOSIO_DI...
@[email protected]注解是@Controller和@ResponseBody的合集,表示这是个控制器bean,并且是将函数的返回值直 接填入HTTP响应体中,是REST风格的控制器。package com.example.demo;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.Res
原文:http://hi.baidu.com/boorag/blog/item/42ca9f826a993ca70df4d250.html import randomimport string#随机整数:print random.randint(1,50)#随机选取0到100间的偶数:print random.randrange(0, 101, 2)#随机浮点数:print rand
@charset "UTF-8";/*ccs-1*/.whj_jqueryPaginationCss-1{ display: inline-block; padding: 5px; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-s...