段時間公司需要做直播服務,所以就研究了一下阿里雲的直播,在直播里面,最重要的就是url的鑒權操作(驗證推流或者拉流的有效性),在網上找了很多代碼,都沒有發現java的demo,所以就寫篇播客記錄一下,方便以后的使用和記憶,如果哪里有誤,請指出改正。
阿里雲直播提供的是觸發式的推流與播放,您無需提前創建資源,只要添加經過備案的推流域名和播流域名,並完成域名解析、鑒權等操作,即可根據地址拼接規則手動拼接,以快速獲取對應的推流地址和播流地址。本文介紹未設置轉碼的直播活動的推流地址和播流地址的拼接方法。
原文章地址:https://help.aliyun.com/document_detail/87396.html?spm=a2c4g.11174283.6.609.7eb3454eniwqXA
這句話的意思就是用戶無需提前創建資源,在有直播場景的時候,直接生成一個直播url並且通過鑒權就可以開始直播了(看直播也是類似的)。
1,推拉流工具類:
/**
* 阿里雲直播工具類
*/
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 aliyunLiveConfig
* @return
*/
public static String createPushUrl(Integer sourceId, LiveTypeEnum liveTypeEnum, AliyunLiveConfig aliyunLiveConfig) {
// 推流域名
String pushDomain = aliyunLiveConfig.getAliyunLivePushDomain();
// 應用名稱
String appName = aliyunLiveConfig.getAliyunLiveAppName();
// 流名稱
String streamName = StrUtil.format(aliyunLiveConfig.getAliyunLiveStreamName(), liveTypeEnum.getValue(), sourceId);
// 推流簽名key
String pushIdentKey = aliyunLiveConfig.getAliyunLivePushIdentKey();
// 簽名url有效時間
Integer identUrlValidTime = aliyunLiveConfig.getAliyunLiveIdentUrlValidTime();
// 計算過期時間
String timestamp = String.valueOf((System.currentTimeMillis() / 1000) + identUrlValidTime);
// 組合推流域名前綴
// rtmp://{pushDomain}/{appName}/{streamName}
String rtmpUrl = StrUtil.format("rtmp://{}/{}/{}", pushDomain, appName, streamName);
log.debug("推流域名前綴,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.debug("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.debug("最終鑒權過的推流域名=" + finallyPushUrl);
return finallyPushUrl;
}
/**
* 創建拉流域名,key=rtmpUrl、flvUrl、m3u8Url,代表三種拉流類型域名
*
* @param sourceId
* @param aliyunLiveConfig
* @return
*/
public static Map<String, String> createPullUrl(Integer sourceId, LiveTypeEnum liveTypeEnum, AliyunLiveConfig aliyunLiveConfig) {
// 拉流域名
String pullDomain = aliyunLiveConfig.getAliyunLivePullDomain();
// 應用名稱
String appName = aliyunLiveConfig.getAliyunLiveAppName();
// 流名稱
String streamName = StrUtil.format(aliyunLiveConfig.getAliyunLiveStreamName(), liveTypeEnum.getValue(), sourceId);
// 拉流簽名key
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);
log.debug("組合通用域名,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.debug("md5加密串,md5Url =" + md5Url + " ------ md5加密結果,md5Str=" + md5Str);
log.debug("md5加密串,md5FlvUrl =" + md5FlvUrl + " ------ md5加密結果,md5FlvStr=" + md5FlvStr);
log.debug("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.debug("最終鑒權過的拉流rtmp域名=" + rtmpUrl);
log.debug("最終鑒權過的拉流flv域名 =" + flvUrl);
log.debug("最終鑒權過的拉流m3u8域名=" + m3u8Url);
HashMap<String, String> urlMap = new HashMap<>();
urlMap.put("rtmpUrl", rtmpUrl);
urlMap.put("flvUrl", flvUrl);
urlMap.put("m3u8Url", m3u8Url);
return urlMap;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
2,阿里雲直播配置參數:
/**
* 阿里雲直播配置參數
*/
@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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
3,直播類型:
/**
* 直播類型
*/
@ApiModel(description = "直播類型")
public enum LiveTypeEnum {
course("course", "課程");
LiveTypeEnum(String value, String text) {
this.value = value;
this.text = text;
}
private String value;
private String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
/**
* 根據value獲取text
*
* @param value
* @return
*/
public static String getTextByValue(String value) {
LiveTypeEnum[] dictTypeEnums = LiveTypeEnum.values();
for (LiveTypeEnum dictTypeEnum : dictTypeEnums) {
if (dictTypeEnum.getValue().equals(value)) {
return dictTypeEnum.getText();
}
}
return "";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
4,application.properties 參數配置:
#阿里雲直播配置 begin
#推流域名
aliyun.live.push.domain=www.xxx.xxx.com
#推流鑒權url key
aliyun.live.push.ident.key=xxx
#拉流域名
aliyun.live.pull.domain=www.xxx.xxx.com
#拉流鑒權url key
aliyun.live.pull.ident.key=xxx
#直播測試appName
aliyun.live.appName=ttest
#直播測試streamName{直播類型}{類型id}
aliyun.live.streamName={}{}
#鑒權url的有效時間(秒),默認30分鍾,1800秒
aliyun.live.ident.url.validTime=1800
#阿里雲直播配置 end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
5,里面工具類的pom地址,不需要也可以自己寫
<!-- Hutool工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.0.12</version>
</dependency>
1
2
3
4
5
6
工具類使用api官網:http://hutool.mydoc.io/undefined
6,發起請求的結果: