Java 基于SSM整合阿里直播服务框架
这篇文章我们来介绍使用java语言进行推流和播流的链接生成。
1.首先需要导入maven依赖
<!--阿里云直播--> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-live</artifactId> <version>3.8.0</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-vod</artifactId> <version>2.7.0</version> </dependency> <!-- Hutool工具包 --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>4.0.12</version> </dependency>
2.创建一个AliyunLiveConfig类,设置一些参数
package com.inxedu.os.common.live; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /**
* 描述:
*
* @author gJK
* @create 2020-07-12 10:55
*/ @Data @Component public class AliYunLiveConfig { /**
* 推流域名
* 在上篇文章中我们设置的推流域名
*/ @Value("www.填写自己实设置的.cn") private String aliyunLivePushDomain; /**
* 拉流域名
*/ @Value("www.填写自己实设置的.cn") private String aliyunLivePullDomain; /**
* appName
* 这个根据自己情况设置
*/ @Value("inxedu") private String aliyunLiveAppName; /**
* 直播流名称streamName{直播类型}_{类型id}:可以给个时间戳
*/ @Value("") private String aliyunLiveStreamName; /**
* 推流鉴权url key
*/ @Value("r1raw0LhU5") private String aliyunLivePushIdentKey; /**
* 拉流鉴权url key
*/ @Value("EWAkkktIDhk") private String aliyunLivePullIdentKey; /**
* 鉴权url的有效时间(秒),默认30分钟,1800秒 key
* 默认是1800秒,我设置成86400,这是最大值
*/ @Value("86400") private Integer aliyunLiveIdentUrlValidTime; /**
* OSS-区域代码
*/ @Value("cn-beijing") private String regionId; /**
* OSS-RAM 访问控制-人员管理-用户 AccessKey
*/ @Value("LQAIJIAyMSll2xis") private String accessKeyId; /**
* OSS-RAM 访问控制-人员管理-用户 secret
*/ @Value("F8Z8RkNS9WdvZdjx") private String secret; }
3. 创建推流和播流的工具类
package com.inxedu.os.common.live; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.exceptions.ServerException; import com.aliyuncs.profile.DefaultProfile; import java.util.*; import com.aliyuncs.live.model.v20161101.*; /**
* 描述:
*
* @author gJK
* @create 2020-07-12 12:25
*/ public class AliYunLiveUtil{ /**
* 我这里传入了一个主播用户的ID,根据用户id创建该id的推流url
* 假设传入的sysUserId = 1
* @param aliYunLiveConfig
* @return
*/ public static String createLivePushUrl(Integer sysUserId,AliYunLiveConfig aliYunLiveConfig) { // 推流域名 String pushDomain = aliYunLiveConfig.getAliyunLivePushDomain(); // 应用名称 String appName = aliYunLiveConfig.getAliyunLiveAppName(); // 流名称streamNameDemo String streamName = StrUtil.format(sysUserId+""); // 推流签名 String pushIdentKey = aliYunLiveConfig.getAliyunLivePushIdentKey(); // 签名url有效时间 Integer identUrlValidTime = aliYunLiveConfig.getAliyunLiveIdentUrlValidTime(); // 计算过期时间 String timestamp = String.valueOf((System.currentTimeMillis() / 1000) + identUrlValidTime); //rtmp://{pushDomain}/{appName}/{streamName} //拼接后输出rtmp://www.video2.zhuyueedu.cn/inxedu/1 String rtmpUrl = StrUtil.format("rtmp://{}/{}/{}", pushDomain, appName, streamName); // 组合md5加密串 ///{appName}/{streamName}-{timestamp}-0-0-{pushIdentKey} // String md5Url = StrUtil.format("/{}/{}-{}-0-0-{}", appName, streamName, timestamp, pushIdentKey); // md5加密 String md5Str = DigestUtil.md5Hex(md5Url); // 组合最终鉴权过的推流域名 // {rtmpUrl}?auth_key={timestamp}-0-0-{md5Str} String finallyPushUrl = StrUtil.format("{}?auth_key={}-0-0-{}", rtmpUrl, timestamp, md5Str); //会返回我们上片文章中的完整的推流url地址, //我们通过各个参数的拼接,最终拼接成阿里要求的格式即可 return finallyPushUrl; } /**
*播流有三种格式,我只需要拼接不同的类型就行
* 创建拉流域名,key=rtmpUrl、flvUrl、m3u8Url,代表三种拉流类型域名
* @param
* @return
*/ public static Map<String,Object> createLivePullUrl(Integer sysUserId,AliYunLiveConfig aliYunLiveConfig) { Map<String,Object> map = new HashMap(); // 拉流域名 String pullDomain = aliYunLiveConfig.getAliyunLivePullDomain(); // 应用名称inxedu String appName = aliYunLiveConfig.getAliyunLiveAppName(); // 流名称 String streamName = StrUtil.format(sysUserId+""); // 拉流签名 String pullIdentKey = aliYunLiveConfig.getAliyunLivePullIdentKey(); // 签名url有效时间 Integer identUrlValidTime = aliYunLiveConfig.getAliyunLiveIdentUrlValidTime(); // 计算过期时间 String timestamp = String.valueOf((System.currentTimeMillis() / 1000) + identUrlValidTime); // 组合通用域名 // {pullDomain}/{appName}/{streamName} String pullUrl = StrUtil.format("{}/{}/{}", pullDomain, appName, streamName); // 组合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); // 组合三种拉流域名前缀 // 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); map.put("rtmpUrl",rtmpUrl); map.put("flvUrl",flvUrl); map.put("m3u8Url",m3u8Url); return map; }
推流和播流的工具类写完之后,其他地方调用即可。剩下就是业务逻辑了,根据自己项目的需要在合理的地方进行调用。
----------------------------------------华丽的分割---------------------------------------
在项目中浪费时间最长的就是推流地址回调接口的 使用。
这个回调有上面用呢?就是当主播在OBS上点击‘开始推流’或者‘停止推流’时,返回给我们的数据。
这些数据里包括当前直播流是否关闭,当我得到这些就可以更改数据库直播状态的字段,来通知用户当前直播是否结束或者是否正在直播。
1.首先去阿里官方进行配置回调地址
2.这里地址是你项目域名的地址,后面的/live/callBackPath,是你在后台controller中方法@GetMapping("/live/callBackPath")对应的地址;
3.这个回调地址唯一不好的是,在本地调试的话根本进不来,所以我们需要想办法。这里当时用的花生壳,有免费的1G流量进行测试,足够了。注册后把阿里域名管理里面的配置回调地址换成花生的域名即可,切记项目上线后记得换诚自己项目的域名。这样配置后,你在本地项目debug就可以调试了
4.这是我本地回调接口方法
/**
* 推流地址回调接口 根据返回状态值进行业务处理
*
*action是直播的状态,‘publish’则是直播中, 'publish_done‘直播关闭
* {
* 'action': 'publish',
* 'ip': {回调地址ip},
* 'id': {推流流名},
* 'app': {推流域名},
* 'appname': {推流app名},
* 'time': {timestamp},
* 'usrargs': {用户参数},
* 'node': {内部节点ip}
* }
*
*/ @GetMapping("/live/callBackPath") public void callBackPath(HttpServletRequest request){ try { //Live是自己定义的实体类 Live live = new Live(); // 接收回调得到参数 Map<String, String[]> parameterMap = request.getParameterMap(); //将接收的map转为我们写的ApiLiveModel,下面就可以直接通过变量获取 ApiLiveModel model = JSONObject.parseObject(JSON.toJSONString(parameterMap),ApiLiveModel.class); // 实现效果 根据回调接口 publish_done:关闭直播 publish 开启直播 if (model != null){ //直播状态值:publish:正在直播,publish_done:关闭直播 String action = model.getAction().get(0); //获取直播状态值 String sysUserId = model.getId().get(0);//老师id if (action.equals("publish")){ log.info("开启直播状态"); //更新状态 并生成拉流地址 live.setStatus(1);//直播状态;1:直播中;2:待开始;3:已结束 //生成拉流URL Map<String, Object> livePullUrl = AliYunLiveUtil.createLivePullUrl(Integer.valueOf(sysUserId).intValue(), aliYunLiveConfig); /*String rtmpUrl = livePullUrl.get("rtmpUrl").toString();*/ String flvUrl = livePullUrl.get("flvUrl").toString(); String m3u8Url = livePullUrl.get("m3u8Url").toString(); live.setPullM3u8Url(m3u8Url);//保存移动拉流url live.setPullFlvUrl(flvUrl);//PC端拉流 liveService.updateStatusAndPullUrlByUserId(Integer.valueOf(sysUserId).intValue(),live); log.info("更新状态、拉流url成功"); }else if (action.equals("publish_done")){ //更新状态 并生成拉流地址 live.setStatus(3);//直播状态;1:直播中;2:待开始;3:已结束 //liveService.updateStatusByUserId(Integer.valueOf(sysUserId).intValue(),live); liveService.deleteByUserId(Integer.valueOf(sysUserId).intValue()); log.info("关闭直播状态"); } } }catch (Exception e){ e.printStackTrace(); } }
5.这是Live实体类,对应数据库表和字段
package com.inxedu.os.edu.entity.live; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import java.util.Date; /**
* 描述:
*
* @author gJK
* @create 2020-07-14 10:53
*/ @Data @EqualsAndHashCode(callSuper = false) @AllArgsConstructor @NoArgsConstructor public class Live { private Integer liveId;//直播主键ID private Integer userId;//管理员id private Date startTime;//直播开始时间 private Integer duration;//直播时长 private Integer status;//直播状态 private Integer totalNum;//在线人数 private String pushUrl;//推流地址 private String pullM3u8Url;//移动端拉流地址 private String pullFlvUrl;//PC端拉流地址 private String liveDescribe;//直播介绍 private String title;//直播标题 private String liver;//直播老师姓名 private String roomKey;//房间密码 private String liveType;//直播课类型 }
差不多我就用到这些了,还有在线人数统计,但是我没有用,我用的webSocekt统计的在线人数。阿里的在线人数也需要设置回调地址,原理一样,缺点就是5分钟更新一次人数,太慢了,所以就没有用阿里的。
以下这是我的效果图,聊天室是用的webSocket进行实现的,实时统计在线人数。
----------------------------------------华丽的分割---------------------------------------
分享基本就到此结束了,第一次做文章,在格式上和美观上都有很多欠缺。内容应该些的也不是很详细,如果我哪里些的不是很明白的可以私聊或者在评论中讨论。
如果文章对你有 一丁点的帮助,就多多支持吧!
文章地址:https://blog.csdn.net/q0505123/article/details/108239523
上一篇: Java中的值传递和地址值传递