背景介绍
OSS支持使用RTMP协议推送H264编码的视频流和AAC编码的音频流到OSS。推送到OSS的音视频数据可以点播播放;在对延迟不敏感的应用场景,也可以做直播用途。RTMP推流上传的流程是创建LiveChannel以后生成推流地址,关于这块的介绍在官方帮助文档里也有介绍,具体可以参考文档"RTMP推流上传"。由于目前官方提供的示例是Python的,本文介绍如何使用JAVA实现生成LiveChannel的签名URL,包括推流地址和播放地址。主要介绍两种方式:
- 自签名方式:根据签名算法来生成签名并拼接URL
- SDK方法:直接调用SDK的方法生成签名URL
自签名方式便于理解OSS的签名原理,用户可以脱离SDK,自己封装方法去生成签名URL;SDK方法相对比较简单,直接集成SDK调用即可。
签名URL格式
目前OSS JAVA SDK的CreateLiveChannelResult类获取到的推流地址和播放地址,是不带签名参数的,如果Bucket的权限是私有的话,那必须使用签名URL去推流。带签名的推流地址形如:
rtmp://${bucket}.${host}/live/${channel}?OSSAccessKeyId=xxx&Expires=yyy&Signature=zzz&${params}
- live:RTMP协议的app名称,OSS固定使用live。
- params:推流参数,格式与HTTP请求的query string相同,即形如varA=valueA&varB=valueB。
推流地址的签名规则中包含的参数及描述如下表所示。
可以通过playlistName来指定生成的m3u8文件名称,其值涵盖LiveChannel中的配置。
Signature的计算规则如下
base64(hmac-sha1(AccessKeySecret,
+ Expires + "\n"
+ CanonicalizedParams
+ CanonicalizedResource))
Signature计算规则中涉及的参数及描述如下表所示
创建LiveChannel
参考OSS的JAVA SDK的安装文档引入JavaSDK。import以下几个类
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.CreateLiveChannelRequest;
import com.aliyun.oss.model.CreateLiveChannelResult;
通过CreateLiveChannelRequest类创建LiveChennel,通过CreateLiveChannelResult获取推流地址和播放地址,示例代码如下
public static void main(String[] args) {
// TODO Auto-generated method stub
// endpoint以杭州为例,其它region请按实际情况填写
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建
String accessKeyId = "<您的AccessKeyId>";
String accessKeySecret = "<您的AccessKeySecret>";
String bucketName = "<您的Bucket名称>";
String liveChannelName = "testChannel";//您的LiveChannel的名称,例如testChannel
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
//创建livechannel,打印推流地址和播放地址(未签名)
CreateLiveChannelRequest request = new CreateLiveChannelRequest(bucketName, liveChannelName);
CreateLiveChannelResult result = new CreateLiveChannelResult();
result = ossClient.createLiveChannel(request);
System.out.println("推流地址:"+result.getPublishUrls());
System.out.println("播放地址:"+result.getPlayUrls());
// 关闭client
ossClient.shutdown();
}
生成签名URL-自签名方式
引入如下依赖
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
private final static String CHARSET_UTF8 = "utf8";
private final static String ALGORITHM = "HmacSHA1";
构造签名字符串函数,返回签名字符串signString
public static String buildSignString(String Expires,String CanonicalizedParams,String CanonicalizedResource){
String signString = Expires + "\n"
+ CanonicalizedParams + "\n"
+ CanonicalizedResource;
return signString;
}
计算签名的函数,参数为签名字符串signString+AccessKeySecret
public static String hmacSha1(String signString, String AccessKeySecret) {
try {
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec keySpec = new SecretKeySpec(AccessKeySecret.getBytes(), ALGORITHM);
mac.init(keySpec);
byte[] rawHmac;
rawHmac = mac.doFinal(signString.getBytes(CHARSET_UTF8));
return new String(Base64.encodeBase64(rawHmac));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
主函数,生成推流URL
public static void main(String[] args) throws Exception{
String bucketName= "<您的Bucket名称>";
String Endpoint= "oss-cn-hangzhou.aliyuncs.com";//Endpoint
String channelName = "testChannel";//liveCahnnel名称
String CanonicalizedParams = "playlistName:playlist.m3u8";//格式为"playlistName:<指定的m3u8名称>"
String CanonicalizedResource = "/test-bucket/testChannel";//CanonicalizedResource格式为/BucketName/ChannelName
String accessKeyId= "<您的AccessKeyId>";
String secretAccessKey= "<您的AccessKeySecret>";
String Expires = Long.toString(System.currentTimeMillis()/1000L+3600); //生成一个unix时间戳Expires,定义URL过期时间
String Signature = (hmacSha1(buildSignString(Expires,CanonicalizedParams,CanonicalizedResource),secretAccessKey));
//推流地址的格式是:rtmp://bucketName.Endpoint/live/channelName?playlistName=playlist.m3u8&Expires=xxx&OSSAccessKeyId=xxx&Signature=xxx
System.out.println("推流地址是\n"+"rtmp://"+bucketName+"."+Endpoint+"/live/"+channelName+"?playlistName=playlist.m3u8"+"&Expires="+Expires+"&OSSAccessKeyId="+accessKeyId+"&Signature="+Signature);
}
生成签名URL-SDK方法
rtmp的推流地址可以用JavaSDK里的generateRtmpUri方法生成,示例如下
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
Date expiration = new Date(new Date().getTime() + 360000 * 1000);
String url = ossClient.generateRtmpUri(bucketName, liveChannelName, PlaylistName, expires);
System.out.println(url);
m3u8的签名播放地址可以用JavaSDK里的generatePresignedUrl方法来直接生成,示例如下
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
Date expiration = new Date(new Date().getTime() + 360000 * 1000);
java.net.URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
System.out.println(url);
ossClient.shutdown();