開發與維運

JAVA實現RTMP推流上傳阿里雲OSS的簽名URL

背景介紹

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。

推流地址的簽名規則中包含的參數及描述如下表所示。
image

可以通過playlistName來指定生成的m3u8文件名稱,其值涵蓋LiveChannel中的配置。
image

Signature的計算規則如下

base64(hmac-sha1(AccessKeySecret,
+ Expires + "\n"
+ CanonicalizedParams
+ CanonicalizedResource))

Signature計算規則中涉及的參數及描述如下表所示
image

創建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();

Leave a Reply

Your email address will not be published. Required fields are marked *