All Products
Search
Document Center

ApsaraVideo Media Processing:Perform HLS encryption and play an encrypted video

Last Updated:Aug 25, 2023

This topic describes the procedure for encrypting a video by using HTTP-Live-Streaming (HLS) encryption and playing the encrypted video.

Procedure

  1. Create a workflow for HLS encryption.

    For more information about the sample code for creating a workflow for HLS encryption, see Create a workflow for HLS encryption.

    Note

    When you create a workflow for HLS encryption, enter http://127.0.0.1:8888 as the value of the HLS_KEY_URI parameter for testing. When you play the encrypted video, the player sends a request to this URL to obtain the decryption key. ApsaraVideo Media Processing (MPS) starts a local service to distribute the key.

  2. Upload and encrypt a video.

    Log on to the MPS console. In the left-side navigation pane, click Upload Video. On the Upload Video page, click Add Video. In the Add Video and Initiate Workflow dialog box, select the workflow for HLS encryption that you created from the Workflow drop-down list. After the video is uploaded, MPS automatically triggers the workflow. In the left-side navigation pane, click Media List. When the video that you uploaded enters the Published state, proceed to the next step.

  3. Construct a local authentication service.

    To play the HLS-encrypted video, construct a local HTTP service as an authentication service to generate and verify the MtsHlsUriToken parameter.

    Dependencies required by the SDK for Java:

    Java SDK Core

    Java SDK KMS

    Sample code for decryption by using the Base64 algorithm:

  4. import com.sun.net.httpserver.*;
    import com.sun.net.httpserver.spi.HttpServerProvider;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.InetSocketAddress;
    
    /**
     * *****   Usage notes     ******
     * This sample code decodes the data key (DK) by using the Base64 algorithm.
     * The port number in the sample code is 8888. Make sure that this number is the same as that of the key uniform resource identifier (URI).
     * If you need additional token verification, see the following sample code for decryption by using Key Management Service (KMS).
     *
     * ***** Code logic ******
     * 1. Receive the decryption request and obtain the enveloped data key (EDK).
     * 2. Decode the DK by using the Base64 algorithm and return the decoded DK.
     */
    public class Base64DecryptServer {
    
        public static void main(String[] args) throws IOException {
            Base64DecryptServer server = new Base64DecryptServer();
            server.startService();
        }
    
        public class Base64DecryptHandler implements HttpHandler {
            /**
             * Process the decryption request.
             * @param httpExchange
             * @throws IOException
             */
            public void handle(HttpExchange httpExchange) throws IOException {
                String requestMethod = httpExchange.getRequestMethod();
                if ("GET".equalsIgnoreCase(requestMethod)) {
                    // The decryption key must be the same as the encryption key.
                    byte[] key = "encryptionkey128".getBytes();
                    // Configure the headers.
                    setHeader(httpExchange, key);
                    // Return the DK that is decoded by using the Base64 algorithm.
                    OutputStream responseBody = httpExchange.getResponseBody();
                    System.out.println(new String(key));
                    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);
            }
        }
        /**
         * Start the service.
         * @throws IOException
         */
        private void startService() throws IOException {
            HttpServerProvider provider = HttpServerProvider.provider();
            // Configure a listener on port 8888, which can accept 30 requests at a time.
            HttpServer httpserver = provider.createHttpServer(new InetSocketAddress(8888), 30);
            httpserver.createContext("/", new Base64DecryptHandler());
            httpserver.start();
            System.out.println("base64 hls decrypt server started");
        }
    
    }

Sample code for decryption by using KMS:

import com.aliyun.mps.sdk.utils.InitClient;
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.sun.net.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;

/**
 * *****   Usage notes     ******
 * This sample code constructs the decryption service by using KMS with the M3U8 encryption and rewrite feature disabled. The MtsHlsUriToken parameter is not verified.
 * For more information about the M3U8 encryption and rewrite feature and how to generate the MtsHlsUriToken parameter, see xxxxxxxxxxxx.
 * The port number in the sample code is 8888. Make sure that this number is the same as that of the key URI.
 *
 * ***** Code logic ******
 * 1. Receive the decryption request and obtain the EDK.
 * 2. Call the Decrypt operation of KMS to obtain the DK. 
 * 3. Decode the DK by using the Base64 algorithm and return the decoded DK.
 */
public class HlsDecryptServerNoToken {

    private static DefaultAcsClient client;
    static {
        try{
            client = InitClient.initMpsClient();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        HlsDecryptServerNoToken server = new HlsDecryptServerNoToken();
        server.startService();
    }

    public class HlsDecryptHandler implements HttpHandler {
        public void handle(HttpExchange httpExchange) throws IOException {
            String requestMethod = httpExchange.getRequestMethod();
            if(requestMethod.equalsIgnoreCase("GET")){
                // Obtain the EDK from the video URL.
                String ciphertext = getCiphertext(httpExchange);
                System.out.println(ciphertext);
                if (null == ciphertext)
                    return;
                // Decrypt the DK obtained from KMS and decode the DK by using the Base64 algorithm.
                byte[] key = decrypt(ciphertext);
                // Configure the headers.
                setHeader(httpExchange, key);
                // Return the decoded DK.
                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);
        }

        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();
                // Note: You must decode the DK by using the Base64 algorithm.
                return Base64.decodeBase64(plaintext);
            } catch (ClientException e) {
                e.printStackTrace();
                return null;
            }
        }
        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");
                return null;
            }
        }
    }

    /**
     * Start the service.
     *
     * @throws IOException
     */
    private void startService() throws IOException {
        HttpServerProvider provider = HttpServerProvider.provider();
        // Configure a listener on port 8888, which can accept 30 requests at a time. You can change the port based on your business requirements.
        HttpServer httpserver = provider.createHttpServer(new InetSocketAddress(8888), 30);
        httpserver.createContext("/", new HlsDecryptHandler());
        httpserver.start();
        System.out.println("no token hls decrypt server started");
    }

}

  1. Dependencies required by the SDK for Python:

pip install aliyun-python-sdk-core

pip install aliyun-python-sdk-kms

pip install aliyun-python-sdk-mts

# -*- coding: UTF-8 -*- 
from BaseHTTPServer import BaseHTTPRequestHandler
from aliyunsdkcore.client import AcsClient
from aliyunsdkkms.request.v20160120 import DecryptRequest
import cgi
import json
import base64
import urlparse
client = AcsClient("","","");
class AuthorizationHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.check()
self.set_header()
cipertext = self.get_cihpertext()
plaintext = self.decrypt_cihpertext(cipertext)
print plaintext
key = base64.b64decode(plaintext)
print key
self.wfile.write(key)
def do_POST(self):
pass
def check(self):
#check MtsHlsUriToken, etc.
pass
def set_header(self):
self.send_response(200)
#cors
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
def get_cihpertext(self):
path = urlparse.urlparse(self.path)
query = urlparse.parse_qs(path.query)
return query.get('Ciphertext')[0]
def decrypt_cihpertext(self, cipertext):
request = DecryptRequest.DecryptRequest()
request.set_CiphertextBlob(cipertext)
response = client.do_action_with_exception(request)
jsonResp = json.loads(response)
return jsonResp["Plaintext"]
if __name__ == '__main__':
# Start a simple server, and loop forever
from BaseHTTPServer import HTTPServer
print "Starting server, use  to stop"
server = HTTPServer(('127.0.0.1', 8888), AuthorizationHandler)
server.serve_forever()
  1. Query the streaming URL of the video by calling the QueryMediaList operation of MPS. For more information, see QueryMediaList.

  2. Play the encrypted video.

    You can use an online player to test the playback of the video encrypted by HLS encryption. For more information, visit ApsaraVideo Player Diagnostics Tool.

    When you use the ApsaraVideo Player diagnostics tool, enter the streaming URL of the video in the Source field and Click Play.

    Note

    On the browser debugging page, you can see that the player sends a request to the authentication server, obtains the decryption key, and then decrypts and plays the video.