前言:视频直播模块主要是在阿里云上生成一个播流与推流的地址,把推流地址放入obs中(相当于主播开播),播流地址放入vcl中(相当于观众看直播)进行一个直播。
好的,话不多说,就是干,现在开始详细介绍直播开通的详细步骤
包括直接在阿里云上生成直播的播流与推流地址以及java代码生成播流与推流地址
请一定要看文字,看文字,看文字,结合图片
一:阿里云上直接生成播流与推流地址
阿里云直播官方开发文档:https://help.aliyun.com/document_detail/29951.html?spm=5176.13910061.sslink.15.517a4399mhjSM6
前提:根据条件创建阿里账号,实名认证,申请两个备案的域名(申请过程可能需要几天,域名会经过工信部审核),一个用于拉流地址生成,一个用于推流地址生成,
步骤按以下步骤一步一步来
1:点击开通直播服务(不需要任何操作点击就可开通),开通完成返回到快速入门界面
2:登录阿里云云解析DNS控制台:
如果域名备案成功,在域名解析模块会看到以下几个域名,红框里面例如域名为live.com,记住这个域名下面一步会用到
3:点击添加推流域名和播流域名,就是阿里云上面的第二步骤,再点击视频直播控制台,点击域名管理,添加域名
注:加速域名填pull.live.com子域名,就是上面域名解析中的地址live.com加上一个随机的前缀pull.该前缀可以任意改变,
其他选择默认的即可点击提交
出现以下界面
再次去到解析域名,点击添加记录
记录类型选择:TXT
主机记录填写上面:主机记录值
记录值填写:记录值
至此完成pull域名添加。再次以此方法添加一个推流域名问push.live.com(下面业务类型选择推流域名)(不需要再去解析域名,点提交不会弹出新页面)
4:再次点击阿里云云解析控制台,域名解析,解析设置(注:选择刚才使用的生成推流播流子域名的域名解析),添加记录
记录类型选择:CNAME
主机记录填:刚才生成的pull.live.com 的前缀 pull
记录值填写:CNAME下面的值复制下来
TTL:选择默认即可
点击确认
再次点击添加记录,重复上面步骤,把主机记录改为:push
至此域名的CNAME配置完成.
5:关联推流与播流域名(生成的推流播流域名为一组)
点击域名管理中的播流域名的域名配置
点击基本设置,推流信息,添加推流信息
推流域选择刚才建立的推流域名push.live.com
6:生成推流播流地址,点击地址生成器
播流域名选择:pull.live.com(选择完,自动匹配出推流域名)
AppName:随便填
StringName:随便填(如0000)
点击开始生成
生成结果如下
7:开始测试推流播流
下载安装OBS(推流软件)
打开OBS,选择文件,设置,推流
服务填:自定义
推流地址例子:rtmp://push.aliyunlive.com/app/stream?auth_key=1543302081-0-0-9c6e7c8190c10bdfb3c0***********
服务器填:rtmp://push.aliyunlive.com/app/
串流密钥填stream?auth_key=1543302081-0-0-9c6e7c8190c10bdfb3c0***********(以AppName为分割)
点击提交即可
点击+号,添加媒体源,点击新建,确定
选择一个MP4等格式的视频文件,确定即可
点击开始推流,就开始视频直播了
下载安装VCL(播流软件)
打开VCL,选择媒体,网络串流,把播流地址填入网络URL中即可,以M3U8播流地址为例子,点击播放即可
效果图如下:
二:java代码生成推流,播流地址(按照一中需要完成前5步包括第5步,才能生成有效的推播流地址,不然生成的是模拟的地址,生成模拟地址不需要前5步,直接按下面开始)
注:由于aliyun-java-vod-upload-1.4.12.jar包maven仓库未开源,所以需要按以下步骤加入到maven仓库
准备阶段下载aliyun-java-vod-upload-1.4.12.jar: https://help.aliyun.com/document_detail/51992.html?spm=a2c4g.11186623.6.1029.2dab6cecZfMGvO
下载完成后解压缩文件
把aliyun-java-vod-upload-1.4.12.jar包复制到你自己的maven仓库中的lib文件下
在该目录下cmd回车
运行以下代码
mvn install:install-file -DgroupId=com.aliyun -DartifactId=aliyun-sdk-vod-upload -Dversion=1.4.12 -Dpackaging=jar -Dfile=aliyun-java-vod-upload-1.4.12.jar
1:在maven工程引入以下依赖
<!-- Hutool工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.0.12</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 配置文件自动提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- aliyun核心sdk-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.1</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-vod</artifactId>
<version>2.15.11</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20170516</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.48</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
2:创建一个AliyunLiveController(controlle类型)引入下面代码
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.open.video.model.AliyunLiveConfig;
import com.open.video.model.ApiLiveModel;
import com.open.video.util.AliyunLiveUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@RestController
@RequestMapping("/aliyunLive")
@Slf4j
//aliyun推流以及拉流地址
public class AliyunLiveController {
@Resource
private AliyunLiveConfig aliyunConfig;
/**
* 生成推流播流地址
* sourceId 在这里我将它设置为房间号
*/
@GetMapping("/save_Live")
public void save_Live(HttpServletRequest request, @RequestParam("sourceId") String sourceId){
try {
//生成推流地址
String pushUrl = AliyunLiveUtil.createPushUrl(sourceId, aliyunConfig);
//生成播流地址
String pullUrl = AliyunLiveUtil.createPullUrl(sourceId, aliyunConfig);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3:创建一个AliyunLiveUtil(工具类型)引入以下代码
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.open.video.model.AliyunLiveConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
public class AliyunLiveUtil {
private static final Logger log = LoggerFactory.getLogger(AliyunLiveUtil.class);
/**
* 推拉流地址示例:
* rtmp://www.ttest.ygdjonline.com/a/a?auth_key=1558065152-0-0-c3cb54d946c0590ca9aeee63573201ee
* 播流地址
* 原画
* rtmp://www.btest.ygdjonline.com/a/a?auth_key=1558065152-0-0-fc711455c0815aeb581385f33451d5b4
* http://www.btest.ygdjonline.com/a/a.flv?auth_key=1558065152-0-0-221abff1da1ee32151e365cf0dd42a53
* http://www.btest.ygdjonline.com/a/a.m3u8?auth_key=1558065152-0-0-72124fcc3aee3404b0d65dcc114e207f
*/
/**
* 根据源id创建该id的推流url
*
* @param sourceId
* @param aliyunConfig
* @return
*/
public static String createPushUrl(String sourceId, AliyunLiveConfig aliyunConfig) {
// 推流域名
String pushDomain = aliyunConfig.getAliyunLivePushDomain();
// 应用名称
String appName = aliyunConfig.getAliyunLiveAppName();
// 流名称
String streamName = StrUtil.format(sourceId);
// 推流签名key
String pushIdentKey = aliyunConfig.getAliyunLivePushIdentKey();
// 签名url有效时间
Integer identUrlValidTime = aliyunConfig.getAliyunLiveIdentUrlValidTime();
//log.info("签名url有效时间" + identUrlValidTime);
// 计算过期时间
String timestamp = String.valueOf((System.currentTimeMillis() / 1000) + identUrlValidTime);
// log.info("计算过期时间" + timestamp);
// 组合推流域名前缀
//rtmp://{pushDomain}/{appName}/{streamName}
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);
log.info("组合md5加密串"+md5Url);
// md5加密
String md5Str = DigestUtil.md5Hex(md5Url);
// log.info("md5加密串,md5Url=" + md5Url + "------md5加密结果,md5Str=" + 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 sourceId
* @param aliyunConfig
* @return
*/
public static String createPullUrl(String sourceId, AliyunLiveConfig aliyunConfig) {
// 拉流域名
String pullDomain = aliyunConfig.getAliyunLivePullDomain();
// 应用名称
String appName = aliyunConfig.getAliyunLiveAppName();
// 流名称
String streamName = StrUtil.format(sourceId);
// 拉流签名key
String pullIdentKey = aliyunConfig.getAliyunLivePullIdentKey();
// 签名url有效时间
Integer identUrlValidTime = aliyunConfig.getAliyunLiveIdentUrlValidTime();
// 计算过期时间
String timestamp = String.valueOf((System.currentTimeMillis() / 1000) + identUrlValidTime);
// 组合通用域名
// {pullDomain}/{appName}/{streamName}
String pullUrl = StrUtil.format("{}/{}/{}", pullDomain, appName, streamName);
//log.info("组合通用域名,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("md5加密串,md5Url =" + md5Url + " ------ md5加密结果,md5Str=" + md5Str);
//log.info("md5加密串,md5FlvUrl =" + md5FlvUrl + " ------ md5加密结果,md5FlvStr=" + md5FlvStr);
//log.info("md5加密串,md5M3u8Url=" + md5M3u8Url + " ------ md5加密结果,md5M3u8Str=" + 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("最终鉴权过的拉流rtmp域名=" + rtmpUrl);
log.info("最终鉴权过的拉流flv域名 =" + flvUrl);
log.info("最终鉴权过的拉流m3u8域名=" + m3u8Url);
return m3u8Url;
}
}
4:创建一个AliyunLiveConfig(model类型)引入以下代码
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
@Data
public class AliyunLiveConfig {
/**
* 推流域名
*/
@Value("${aliyun.live.push.domain}")
private String aliyunLivePushDomain;
/**
* 拉流域名
*/
@Value("${aliyun.live.pull.domain}")
private String aliyunLivePullDomain;
/**
* 直播测试appName
*/
@Value("${aliyun.live.appName}")
private String aliyunLiveAppName;
/**
* 直播测试streamName{直播类型}_{类型id}
*/
// @Value("${aliyun.live.streamName}")
// private String aliyunLiveStreamName;
/**
* 推流鉴权url key
*/
@Value("${aliyun.live.push.ident.key}")
private String aliyunLivePushIdentKey;
/**
* 拉流鉴权url key
*/
@Value("${aliyun.live.pull.ident.key}")
private String aliyunLivePullIdentKey;
/**
* 鉴权url的有效时间(秒),默认30分钟,1800秒 key
*/
@Value("${aliyun.live.ident.url.validTime}")
private Integer aliyunLiveIdentUrlValidTime;
}
5:创建一个ApiLiveModel(model类型)引入以下代码
import lombok.Data;
import java.util.List;
@Data
public class ApiLiveModel {
private List<String> action;
private List<String> ip;
private List<String> id;
private List<String> app;
private List<String> appname;
private List<String> time;
private List<String> usrargs;
private List<String> node;
}
6:在配置文件application.properties中引入下面代码(核心配置aliyun的配置文件)下面会解释说明每一个值
注:模拟生成一个推拉流地址不需要改写值
#阿里云直播配置 begin
#推流域名
aliyun.live.push.domain=xxx.xxx.com
#推流鉴权url key
aliyun.live.push.ident.key=xxx
#拉流域名
aliyun.live.pull.domain=xxx.xxx.com
#拉流鉴权url key
aliyun.live.pull.ident.key=xxx
#直播测试appName
aliyun.live.appName=xxx
#直播测试streamName{直播类型}{类型id}
aliyun.live.streamName=wanxi
#鉴权url的有效时间(秒),默认30分钟,1800秒
aliyun.live.ident.url.validTime=1800
#阿里云直播配置 end
推流域名:前面的生成的push.live.com(需看阿里云生成例子)
播流(拉流)域名:前面的生成的pull.live.com(需看阿里云生成例子)
推流鉴权url key:点击域名管理,域名配置,访问控制,url鉴权查看key
播流鉴权url key:同上,开始选择播流域名查看
appName:自定义
streamName:自定义(前端传参就是sourceId,就是根据这streamName(sourceId)生成不同的直播房间,推流地址)