日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

HLS標(biāo)準(zhǔn)加密

HLS標(biāo)準(zhǔn)加密需要配合密鑰管理服務(wù)和令牌服務(wù)使用,本文為您介紹HLS標(biāo)準(zhǔn)加密的相關(guān)概念、準(zhǔn)備工作和接入流程。

HLS加密解密流程

上傳加密流程圖加密播放解密流程圖播放解密

說明
  • 使用密鑰管理服務(wù)會產(chǎn)生費(fèi)用,計費(fèi)詳情請參見KMS計費(fèi)說明

  • 令牌服務(wù)和解密服務(wù)需要自行搭建。

相關(guān)概念

  • 密鑰管理服務(wù)

    密鑰管理服務(wù)(Key Management Service,簡稱KMS),是一種安全管理服務(wù),主要負(fù)責(zé)數(shù)據(jù)密鑰的生產(chǎn)、加密、解密等工作。

  • 訪問控制

    訪問控制(Resource Access Management,簡稱RAM)是阿里云為客戶提供的用戶身份管理與資源訪問控制服務(wù)。

  • 數(shù)據(jù)密鑰

    數(shù)據(jù)密鑰(Data Key,簡稱DK)也稱明文密鑰。DK為加密數(shù)據(jù)使用的明文數(shù)據(jù)密鑰。

  • 信封數(shù)據(jù)密鑰

    信封數(shù)據(jù)密鑰(Enveloped Data Key,簡稱EDK)也稱密文密鑰。EDK為通過信封加密技術(shù)保密后的密文數(shù)據(jù)密鑰。

準(zhǔn)備工作

  1. 開通視頻點(diǎn)播服務(wù)并登錄視頻點(diǎn)播控制臺,開啟對應(yīng)服務(wù)區(qū)域的存儲空間,具體操作,請參見開通存儲管理

  2. 在視頻點(diǎn)播控制臺上配置加速域名,并開啟該域名視頻相關(guān)中的HLS標(biāo)準(zhǔn)加密參數(shù)透傳,開啟后MtsHlsUriToken參數(shù)可以重寫。具體操作,請參見添加加速域名HLS標(biāo)準(zhǔn)加密參數(shù)透傳

  3. 登錄RAM訪問控制,獲取并保存AccessKey ID和AccessKey Secret。

  4. 開通密鑰管理服務(wù)并獲取Service Key。

    說明
    • Service Key是密鑰管理服務(wù)的一種加密主Key,接入標(biāo)準(zhǔn)加密的密鑰必須要使用該Service Key生成。

    • Service Key與視頻存儲的源站地域必須一致,例如:視頻存儲在華東2,則Service Key必須是在華東2創(chuàng)建。

    1. 登錄視頻點(diǎn)播控制臺,選擇配置管理 > 媒體處理配置 > 標(biāo)準(zhǔn)加密,在標(biāo)準(zhǔn)加密頁面,創(chuàng)建Service Key。

    2. 創(chuàng)建成功后,需調(diào)用GenerateDataKey接口,請求參數(shù)KeyId傳入別名alias/acs/vod,請求后的返回參數(shù)KeyId將用于后續(xù)的轉(zhuǎn)碼處理。

  5. 已搭建服務(wù)端SDK,具體操作,請參見服務(wù)端SDK安裝

接入流程

  1. 添加加密模板和不轉(zhuǎn)碼模板。

    HLS標(biāo)準(zhǔn)加密轉(zhuǎn)碼需要創(chuàng)建兩個轉(zhuǎn)碼模板:加密模板和不轉(zhuǎn)碼模板。

    不轉(zhuǎn)碼模板在開啟對應(yīng)服務(wù)區(qū)域的存儲空間后會自動生成。

    說明

    目前點(diǎn)播上傳視頻默認(rèn)都會自動觸發(fā)轉(zhuǎn)碼(自動觸發(fā)暫不支持HLS標(biāo)準(zhǔn)加密)),因此對于標(biāo)準(zhǔn)加密為防止自動觸發(fā)轉(zhuǎn)碼,需要先使用不轉(zhuǎn)碼模板上傳視頻(該類模板不會自動觸發(fā)轉(zhuǎn)碼),然后再調(diào)用提交媒體轉(zhuǎn)碼作業(yè)接口發(fā)起標(biāo)準(zhǔn)加密轉(zhuǎn)碼。

    添加加密模板并保存加密模板ID,操作流程如下:

    1. 登錄視頻點(diǎn)播控制臺

    2. 配置管理區(qū)域,選擇媒體處理配置 > 轉(zhuǎn)碼模板組 > 添加轉(zhuǎn)碼模板組

    3. 添加轉(zhuǎn)碼模板組頁面,輸入模板組名稱

    4. 普通轉(zhuǎn)碼模板區(qū)域單擊添加模板開始創(chuàng)建轉(zhuǎn)碼模板。

    5. 基本參數(shù)區(qū)域,選擇封裝格式hls

    6. 視頻參數(shù)區(qū)域、音頻參數(shù)區(qū)域及條件轉(zhuǎn)碼參數(shù)區(qū)域,可根據(jù)實際需要配置相關(guān)參數(shù),各參數(shù)的含義及配置限制請參見音視頻轉(zhuǎn)碼

    7. 高級參數(shù)區(qū)域,開啟視頻加密,并勾選私有加密選項(系統(tǒng)默認(rèn)勾選,否則不加密)。

      加密模板
      說明

      該模板在調(diào)用提交媒體轉(zhuǎn)碼作業(yè)接口時,通過TemplateGroupId參數(shù)傳遞,如此視頻點(diǎn)播將按照設(shè)置的模板和傳遞的密鑰信息進(jìn)行標(biāo)準(zhǔn)加密轉(zhuǎn)碼。

    8. 單擊保存,自動返回轉(zhuǎn)碼模板組頁面,獲取并自行保存加密模板ID。

  2. RAM授權(quán)。

    使用RAM服務(wù)給視頻點(diǎn)播授權(quán)訪問業(yè)務(wù)方密鑰管理服務(wù)的權(quán)限,進(jìn)入RAM授權(quán)頁面,單擊同意授權(quán)

    授權(quán)頁面
  3. 搭建密鑰管理服務(wù),封裝阿里云密鑰管理服務(wù)(KMS)。

    調(diào)用GenerateDataKey接口生成一個AES_128密鑰,該接口只需要傳KeyId(Service Key)和KeySpec(固定為:AES_128)即可,其他參數(shù)不用傳,否則可能加密失敗。

    調(diào)用成功后保存返回參數(shù)CiphertextBlob(密文密鑰)的值。

    說明

    使用密鑰會產(chǎn)生費(fèi)用,具體費(fèi)用說明,請參見API調(diào)用費(fèi)用

  4. 搭建令牌頒發(fā)服務(wù),生成MtsHlsUriToken。

    Java示例代碼以及示例代碼需要手動變更的地方如下所示:

    • ENCRYPT_KEY:加密字符串,長度為16,用戶自行定義。

    • INIT_VECTOR:自定義字符串,長度為16,不能含有特殊字符。

    • playToken.generateToken(""):自定義字符串,長度為16。

    最終代碼所生成的Token即是MtsHlsUriToken。

    import com.sun.deploy.util.StringUtils;
    import org.apache.commons.codec.binary.Base64;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.util.Arrays;
    
    public class PlayToken {
        //非AES生成方式,無需以下參數(shù)
        //加密字符串,用戶自行定義
        private static String ENCRYPT_KEY = "";  
        //長度為16的自定義字符串,不能有特殊字符
        private static String INIT_VECTOR = "";  
    
        public static void main(String[] args) throws Exception {
    
            PlayToken playToken = new PlayToken();
            playToken.generateToken("");
        }
    
        /**
         * 根據(jù)傳遞的參數(shù)生成令牌
         * 說明:
         *  1、參數(shù)可以是業(yè)務(wù)方的用戶ID、播放終端類型等信息
         *  2、調(diào)用令牌接口時生成令牌Token
         * @param args
         * @return
         */
        public String generateToken(String... args) throws Exception {
            if (null == args || args.length <= 0) {
                return null;
            }
            String base = StringUtils.join(Arrays.asList(args), "_");
            //設(shè)置30S后,該token過期,過期時間可以自行調(diào)整
            long expire = System.currentTimeMillis() + 30000L;
            //自定義字符串,base的最終長度為16位字符(此例中,時間戳占13位,下劃線(_)占1位,則還需傳入2位字符。實際配置時也可按需全部更改,最終保證base為16位字符串即可。)
            base += "_" + expire;  
            //生成token
            String token = encrypt(base, ENCRYPT_KEY);
            System.out.println(token);
            //保存token,用于解密時校驗token的有效性,例如:過期時間、token的使用次數(shù)
            saveToken(token);
            return token;
        }
        /**
         * 驗證token的有效性
         * 說明:
         *  1、解密接口在返回播放密鑰前,需要先校驗Token的合法性和有效性
         *  2、強(qiáng)烈建議同時校驗Token的過期時間以及Token的有效使用次數(shù)
         * @param token
         * @return
         * @throws Exception
         */
        public boolean validateToken(String token) throws Exception {
            if (null == token || "".equals(token)) {
                return false;
            }
            String base = decrypt(token, ENCRYPT_KEY);
            //先校驗token的有效時間
            Long expireTime = Long.valueOf(base.substring(base.lastIndexOf("_") + 1));
            if (System.currentTimeMillis() > expireTime) {
                return false;
            }
            //從DB獲取token信息,判斷token的有效性,業(yè)務(wù)方可自行實現(xiàn)
            Token dbToken = getToken(token);
            //判斷是否已經(jīng)使用過該token
            if (dbToken == null || dbToken.useCount > 0) {
                return false;
            }
            //獲取到業(yè)務(wù)屬性信息,用于校驗
            String businessInfo = base.substring(0, base.lastIndexOf("_"));
            String[] items = businessInfo.split("_");
            //校驗業(yè)務(wù)信息的合法性,業(yè)務(wù)方實現(xiàn)
            return validateInfo(items);
        }
        /**
         * 保存Token到DB
         * 業(yè)務(wù)方自行實現(xiàn)
         *
         * @param token
         */
        public void saveToken(String token) {
            //TODO 存儲Token
        }
        /**
         * 查詢Token
         * 業(yè)務(wù)方自行實現(xiàn)
         *
         * @param token
         */
        public Token getToken(String token) {
            //TODO 從DB 獲取Token信息,用于校驗有效性和合法性
            return null;
        }
        /**
         * 校驗業(yè)務(wù)信息的有效性,業(yè)務(wù)方可自行實現(xiàn)
         *
         * @param infos
         * @return
         */
        public boolean validateInfo(String... infos) {
            //TODO 校驗信息的有效性,例如UID是否有效等
            return true;
        }
        /**
         * AES加密生成Token
         *
         * @param key
         * @param value
         * @return
         * @throws Exception
         */
        public String encrypt(String value, String key) throws Exception {
            IvParameterSpec e = new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, e);
            byte[] encrypted = cipher.doFinal(value.getBytes());
            return Base64.encodeBase64String(encrypted);
        }
        /**
         * AES解密token
         *
         * @param key
         * @param encrypted
         * @return
         * @throws Exception
         */
        public String decrypt(String encrypted, String key) throws Exception {
            IvParameterSpec e = new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, e);
            byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
            return new String(original);
        }
        /**
         * Token信息,業(yè)務(wù)方可提供更多信息,這里僅僅給出示例
         */
        class Token {
            //Token的有效使用次數(shù),分布式環(huán)境需要注意同步修改問題
            int useCount;
            //token內(nèi)容
            String token;
        }}
  5. 搭建解密服務(wù)。

    重要

    解密服務(wù)在播放視頻前就需要啟動,否則視頻無法正常解密。

    解密密鑰EDK(密文密鑰),調(diào)用Decrypt接口進(jìn)行解密。如果業(yè)務(wù)方需要對解密接口進(jìn)行安全驗證,則需要提供令牌生成服務(wù),生成的令牌能夠在解密服務(wù)中被解析驗證。

    解密接口返回的數(shù)據(jù),是GenerateDataKey生成的兩種密鑰中的明文密鑰(PlainText)經(jīng)過base64decode之后的數(shù)據(jù)。

    Java示例代碼以及示例代碼需要手動變更的地方如下所示:

    • region:填寫地域,例如華東2(上海),填寫cn-shanghai

    • AccessKey:填寫對應(yīng)賬號的AccessKey ID和AccessKey Secret。

    • httpserver:根據(jù)需求選擇服務(wù)啟動的端口號。

    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.http.ProtocolType;
    import com.aliyuncs.kms.model.v20160120.DecryptRequest;
    import com.aliyuncs.kms.model.v20160120.DecryptResponse;
    import com.aliyuncs.profile.DefaultProfile;
    import com.sun.net.httpserver.Headers;
    import com.sun.net.httpserver.HttpExchange;
    import com.sun.net.httpserver.HttpHandler;
    import com.sun.net.httpserver.HttpServer;
    import com.sun.net.httpserver.spi.HttpServerProvider;
    import org.apache.commons.codec.binary.Base64;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.InetSocketAddress;
    import java.net.URI;import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    public class HlsDecryptServer {
        private static DefaultAcsClient client;
        static {
            //KMS的區(qū)域,必須與視頻對應(yīng)區(qū)域
            String region = "";
            // 訪問KMS的授權(quán)AccessKey信息
            // 阿里云賬號AccessKey擁有所有API的訪問權(quán)限,建議您使用RAM用戶進(jìn)行API訪問或日常運(yùn)維。
            // 強(qiáng)烈建議不要把AccessKey ID和AccessKey Secret保存到工程代碼里,否則可能導(dǎo)致AccessKey泄露,威脅您賬號下所有資源的安全。
            // 本示例通過從環(huán)境變量中讀取AccessKey,來實現(xiàn)API訪問的身份驗證。運(yùn)行代碼示例前,請配置環(huán)境變量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
            String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
            String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
            client = new DefaultAcsClient(DefaultProfile.getProfile(region, accessKeyId, accessKeySecret));
        }
        /**
         * 說明:
         * 1、接收解密請求,獲取密文密鑰和令牌Token
         * 2、調(diào)用KMS decrypt接口獲取明文密鑰
         * 3、將明文密鑰base64decode返回
         */
        public class HlsDecryptHandler implements HttpHandler {
            /**
             * 處理解密請求
             * @param httpExchange
             * @throws IOException
             */
            public void handle(HttpExchange httpExchange) throws IOException {
                String requestMethod = httpExchange.getRequestMethod();
                if ("GET".equalsIgnoreCase(requestMethod)) {
                    //校驗token的有效性
                    String token = getMtsHlsUriToken(httpExchange);
                    boolean validRe = validateToken(token);
                    if (!validRe) {
                        return;
                    }
                    //從URL中取得密文密鑰
                    String ciphertext = getCiphertext(httpExchange);
                    if (null == ciphertext)
                        return;
                    //從KMS中解密出來,并Base64 decode
                    byte[] key = decrypt(ciphertext);
                    //設(shè)置header
                    setHeader(httpExchange, key);
                    //返回base64decode之后的密鑰
                    OutputStream responseBody = httpExchange.getResponseBody();
                    responseBody.write(key);
                    responseBody.close();
                }
            }
            private void setHeader(HttpExchange httpExchange, byte[] key) throws IOException {
                Headers responseHeaders = httpExchange.getResponseHeaders();
                responseHeaders.set("Access-Control-Allow-Origin", "*");
                httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, key.length);
            }
            /**
             * 調(diào)用KMS decrypt接口解密,并將明文base64decode
             * @param ciphertext
             * @return
             */
            private byte[] decrypt(String ciphertext) {
                DecryptRequest request = new DecryptRequest();
                request.setCiphertextBlob(ciphertext);
                request.setProtocol(ProtocolType.HTTPS);
                try {
                    DecryptResponse response = client.getAcsResponse(request);
                    String plaintext = response.getPlaintext();
                    //注意:需要base64 decode
                    return Base64.decodeBase64(plaintext);
                } catch (ClientException e) {
                    e.printStackTrace();
                    return null;
                }
            }
            /**
             * 校驗令牌有效性
             * @param token
             * @return
             */
            private boolean validateToken(String token) {
                if (null == token || "".equals(token)) {
                    return false;
                }
                //TODO 業(yè)務(wù)方實現(xiàn)令牌有效性校驗
                return true;
            }
            /**
             * 從URL中獲取密文密鑰參數(shù)
             * @param httpExchange
             * @return
             */
            private String getCiphertext(HttpExchange httpExchange) {
                URI uri = httpExchange.getRequestURI();
                String queryString = uri.getQuery();
                String pattern = "CipherText=(\\w*)";
                Pattern r = Pattern.compile(pattern);
                Matcher m = r.matcher(queryString);
                if (m.find())
                    return m.group(1);
                else {
                    System.out.println("Not Found CipherText Param");
                    return null;
                }
            }
            /**
             * 獲取Token參數(shù)
             *
             * @param httpExchange
             * @return
             */
            private String getMtsHlsUriToken(HttpExchange httpExchange) {
                URI uri = httpExchange.getRequestURI();
                String queryString = uri.getQuery();
                String pattern = "MtsHlsUriToken=(\\w*)";
                Pattern r = Pattern.compile(pattern);
                Matcher m = r.matcher(queryString);
                if (m.find())
                    return m.group(1);
                else {
                    System.out.println("Not Found MtsHlsUriToken Param");
                    return null;
                }
            }
        }
        /**
         * 服務(wù)啟動
         *
         * @throws IOException
         */
        private void serviceBootStrap() throws IOException {
            HttpServerProvider provider = HttpServerProvider.provider();
            //監(jiān)聽端口可以自定義,能同時接受最多30個請求
            HttpServer httpserver = provider.createHttpServer(new InetSocketAddress(8099), 30);
            httpserver.createContext("/", new HlsDecryptHandler());
            httpserver.start();
            System.out.println("hls decrypt server started");
        }
        public static void main(String[] args) throws IOException {
            HlsDecryptServer server = new HlsDecryptServer();
            server.serviceBootStrap();
        }}
  6. 上傳視頻。

    使用不轉(zhuǎn)碼模板創(chuàng)建視頻上傳憑證和地址。控制臺具體操作,請參見控制臺上傳;服務(wù)端接口上傳,請參見獲取音視頻上傳地址和憑證

  7. 接收上傳完成回調(diào)消息。

    通過設(shè)置事件通知配置設(shè)置回調(diào),通過查詢事件通知配置查詢回調(diào)消息,當(dāng)接收到視頻上傳完成的回調(diào)消息,則表明文件已經(jīng)上傳到視頻點(diǎn)播。

  8. 發(fā)起標(biāo)準(zhǔn)加密轉(zhuǎn)碼。

    調(diào)用提交媒體轉(zhuǎn)碼作業(yè)接口發(fā)起標(biāo)準(zhǔn)加密轉(zhuǎn)碼。

    Java示例代碼以及示例代碼需要手動變更的地方如下所示:

    • request.setTemplateGroupId(""):傳入加密模板ID。

    • request.setVideoId(""):傳入視頻ID。

    • encryptConfig.put("CipherText",""):傳入步驟三獲取的CiphertextBlob值。

    • encryptConfig.put("DecryptKeyUri",""):傳入播放地址、CiphertextBlob值以及MtsHlsUriToken。以在本地的8099端口為例,播放地址為:http://172.16.0.1:8099?CipherText=CiphertextBlob值&MtsHlsUriToken=MtsHlsUriToken值

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.profile.DefaultProfile;
    import com.aliyuncs.vod.model.v20170321.SubmitTranscodeJobsRequest;
    import com.aliyuncs.vod.model.v20170321.SubmitTranscodeJobsResponse;
    
    public class SubmitTranscodeJobs {
    
        // 阿里云賬號AccessKey擁有所有API的訪問權(quán)限,建議您使用RAM用戶進(jìn)行API訪問或日常運(yùn)維。
        // 強(qiáng)烈建議不要把AccessKey ID和AccessKey Secret保存到工程代碼里,否則可能導(dǎo)致AccessKey泄露,威脅您賬號下所有資源的安全。
        // 本示例通過從環(huán)境變量中讀取AccessKey,來實現(xiàn)API訪問的身份驗證。運(yùn)行代碼示例前,請配置環(huán)境變量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
        private static String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        private static String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    
        public static SubmitTranscodeJobsResponse submitTranscodeJobs(DefaultAcsClient client) throws Exception{
            SubmitTranscodeJobsRequest request = new SubmitTranscodeJobsRequest();
            request.setTemplateGroupId("");
            request.setVideoId("");
            JSONObject encryptConfig = new JSONObject();
            encryptConfig.put("CipherText","");
            encryptConfig.put("DecryptKeyUri","");
            encryptConfig.put("KeyServiceType","KMS");
            request.setEncryptConfig(encryptConfig.toJSONString());
            return client.getAcsResponse(request);
        }
    
        public static void main(String[] args) throws ClientException {
            // 點(diǎn)播服務(wù)接入?yún)^(qū)域  
            String regionId = "cn-shanghai";  
            DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);
    
            SubmitTranscodeJobsResponse response;
            try {
                response = submitTranscodeJobs(client);
                System.out.println("RequestId is:"+response.getRequestId());
                System.out.println("TranscodeTaskId is:"+response.getTranscodeTaskId());
                System.out.println("TranscodeJobs is:"+ JSON.toJSON(response.getTranscodeJobs()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }       
  9. 驗證加密轉(zhuǎn)碼是否成功。

    您可以登錄視頻點(diǎn)播控制臺查看該視頻的視頻地址,通過以下三種方式來逐步判斷標(biāo)準(zhǔn)加密是否成功。

    • 當(dāng)視頻加密轉(zhuǎn)碼后,如果該視頻的視頻地址只有一個M3U8格式的視頻地址,那么該視頻狀態(tài)為轉(zhuǎn)碼失敗

    • 當(dāng)視頻加密轉(zhuǎn)碼后,如果視頻不只有M3U8格式的輸出(例如還存在格式為MP4的原始文件),只需查看M3U8格式后是否帶有標(biāo)準(zhǔn)加密,一般情況下,如果存在則表明標(biāo)準(zhǔn)加密已成功。

    • 如果以上兩種方式都不能判斷,那么可以將帶有加密標(biāo)志的M3U8文件的地址拷貝出來,使用curl -v "M3U8文件地址",查看獲取到的M3U8內(nèi)容是否存在URI="<業(yè)務(wù)方在發(fā)起標(biāo)準(zhǔn)加密時傳遞的解密地址,即加密配置 EncryptConfig中的DecryptKeyUri參數(shù)值>"關(guān)鍵信息,有則表明為標(biāo)準(zhǔn)加密且加密成功。

播放流程

  1. 獲取視頻的播放地址和憑證。

    調(diào)用獲取音視頻播放地址獲取音視頻播放憑證接口獲取視頻的播放地址和憑證。

  2. 傳入認(rèn)證信息。

    獲取M3U8文件地址后,播放器會解析M3U8文件中的EXT-X-KEY標(biāo)簽中的URI并訪問,從而獲取到帶密文密鑰的解密接口URI,此URI為您發(fā)起標(biāo)準(zhǔn)加密時傳遞的加密配置 EncryptConfig中的DecryptKeyUri參數(shù)值。

    若只允許合法用戶才可以訪問,那么需要播放器在獲取解密密鑰時攜帶您承認(rèn)的認(rèn)證信息,認(rèn)證信息可以通過MtsHlsUriToken參數(shù)傳入。

    示例:

    • 視頻的播放地址為:https://demo.aliyundoc.com/encrypt-stream****-hd.m3u8,則請求時需要攜帶MtsHlsUriToken參數(shù)傳入。

    • 最終請求地址為:https://demo.aliyundoc.com/encrypt-stream****-hd.m3u8?MtsHlsUriToken=<令牌>

    • 解密地址為:https://demo.aliyundoc.com?Ciphertext=ZjJmZGViNzUtZWY1Mi00Y2RlLTk3MTMtOT****

    • 最終解密請求地址為:https://demo.aliyundoc.com?Ciphertext=ZjJmZGViNzUtZWY1Mi00Y2RlLTk3MTMtOT****&MtsHlsUriToken=<頒發(fā)的令牌>

  3. 播放。

    播放器在解析到解密地址URI時會自動請求解密接口獲取解密密鑰,拿到解密密鑰去解密加密過的ts文件進(jìn)行播放。