すべてのプロダクト
Search
ドキュメントセンター

ApsaraVideo Media Processing:HLS 暗号化を実行する

最終更新日:Nov 13, 2025

動画暗号化機能を使用すると、動画コンテンツに対して詳細なセキュリティ処理を実行し、動画データが不正に取得および送信されるのを防ぐことができます。この機能は、オンライン教育や金融など、高いセキュリティが要求されるシナリオで、動画の漏洩やホットリンクを防ぐために広く使用されています。ApsaraVideo Media Processing (MPS) は、Alibaba Cloud 専用の暗号化と HTTP-Live-Streaming (HLS) 暗号化の 2 つの暗号化方式をサポートしています。このトピックでは、HLS 暗号化の仕組みと HLS 暗号化の使用方法について説明します。これにより、HLS 暗号化を使用して動画のセキュリティを確保し、動画をスムーズに再生できます。

シナリオ

HLS 暗号化は、動画の不正なダウンロードや配布からの保護など、基本的なデータ保護シナリオに使用されます。

使用上の注意

  • HLS 暗号化を使用するには、SubmitJobs オペレーションを呼び出す必要があります。

  • ワークフローでは、HLS 暗号化に Base64 アルゴリズムを使用することはできません。

  • HLS 暗号化の技術的原則については、「HLS 暗号化」をご参照ください。

依存関係

  • Java 用 MPS SDK をインストールします。 詳細については、「Java 用 MPS SDK をインストールする」をご参照ください。

  • その他の依存関係:

    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>kms20160120</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.68.noneautotype</version>
    </dependency>
    <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.9</version>
    </dependency>

KMS ベースの暗号化 (推奨)

暗号化とトランスコード

説明

ワークフローを使用して HLS 暗号化とトランスコードをトリガーする場合、ワークフローで指定された入力パスにファイルをアップロードできます。 また、AddMedia を呼び出してワークフローをトリガーすることもできます。

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import com.aliyun.tea.*;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class SubmitJobsForKMS {
    /**
     * 説明説明

復号化サービス

import com.aliyun.tea.TeaException;
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;

public class DecryptServerKMS {

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

    public class HlsDecryptHandler implements HttpHandler {
        public void handle(HttpExchange httpExchange) throws IOException {
            String requestMethod = httpExchange.getRequestMethod();
            if(requestMethod.equalsIgnoreCase("GET")){
                // URL からキーの暗号文を取得します。
                String ciphertext = getCiphertext(httpExchange);
                System.out.println(ciphertext);
                if (null == ciphertext)
                    return;
                // KMS からキーを復号し、Base64 デコードを実行します。
                byte[] key = decrypt(ciphertext);
                // ヘッダーを設定します。
                setHeader(httpExchange, key);
                // キーを返します。
                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) {

            try {
                com.aliyun.kms20160120.Client client = DecryptServerKMS.createKMSClient();
                com.aliyun.kms20160120.models.DecryptRequest decryptRequest = new com.aliyun.kms20160120.models.DecryptRequest();
                // これを KMS コンソールでエイリアス alias/acs/mts を持つキーに置き換えます。
                decryptRequest.setCiphertextBlob(ciphertext);
                com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
                // コードをコピーして実行する場合は、API 操作の戻り値を出力します。
                com.aliyun.kms20160120.models.DecryptResponse decryptResponse = client.decryptWithOptions(decryptRequest, runtime);
                String plaintext = decryptResponse.getBody().getPlaintext();
                return Base64.decodeBase64(plaintext);
            } catch (TeaException error) {
                // これはデモンストレーションのみを目的としています。例外は慎重に処理してください。プロジェクトで例外を無視しないでください。
                // エラーメッセージ。
                System.out.println(error.getMessage());
                // 診断アドレス。
                System.out.println(error.getData().get("Recommend"));
                com.aliyun.teautil.Common.assertAsString(error.message);
                return null;
            } catch (Exception _error) {
                TeaException error = new TeaException(_error.getMessage(), _error);
                // これはデモンストレーションのみを目的としています。例外は慎重に処理してください。プロジェクトで例外を無視しないでください。
                // エラーメッセージ。
                System.out.println(error.getMessage());
                // 診断アドレス。
                System.out.println(error.getData().get("Recommend"));
                com.aliyun.teautil.Common.assertAsString(error.message);
                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;
            }
        }
    }

    /**
     * サービスを開始します。
     *
     * @throws IOException
     */
    private void startService() throws IOException {
        HttpServerProvider provider = HttpServerProvider.provider();
        // ポート 8888 でリッスンします。サービスは 30 の同時リクエストを受け入れることができます。必要に応じてポートを変更できます。
        HttpServer httpserver = provider.createHttpServer(new InetSocketAddress(8888), 30);
        httpserver.createContext("/", new HlsDecryptHandler());
        httpserver.start();
        System.out.println("no token hls decrypt server started");
    }


    /**
     * 説明

Base64 暗号化

暗号化とトランスコード

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.tea.TeaException;
import org.apache.commons.codec.binary.Base64;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class SubmitJobsForBase64 {

    /**
     * <b>説明</b> :
     * <p>AccessKey ペアを使用して MPS クライアントを初期化します。</p>
     * @return Client
     *
     * @throws Exception
     */
    public static com.aliyun.mts20140618.Client createClient() throws Exception {

        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 必須。 ALIBABA_CLOUD_ACCESS_KEY_ID 環境変数が構成されていることを確認します。
                .setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
                // 必須。 ALIBABA_CLOUD_ACCESS_KEY_SECRET 環境変数が構成されていることを確認します。
                .setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        config.endpoint = "mts.cn-shanghai.aliyuncs.com";
        return new com.aliyun.mts20140618.Client(config);
    }

    /**
     * 暗号化構成を構築します。
     * @return
     */
    private static JSONObject getEncryptionConfigs() throws Exception  {
        JSONObject encryption = new JSONObject();
        encryption.put("Type", "hls-aes-128");
        // 暗号鍵の長さは 16 バイトである必要があります。
        encryption.put("Key", Base64.encodeBase64URLSafeString("encryptionkey128".getBytes()));
        // 復号鍵を取得するために使用されるエンドポイント。
        String url = "http://127.0.0.1:8888";
        encryption.put("KeyUri", Base64.encodeBase64URLSafeString(url.getBytes()));
        encryption.put("KeyType", "Base64");
        return encryption;
    }

    /**
     * KMS 暗号化とトランスコードを送信します。
     * @return
     * @throws Exception
     */
    public static void submitJobsForBase64() throws Exception {

        // ジョブ入力を構成します。ジョブ入力として使用されるメディアファイルが、クライアントと同じリージョンにあることを確認します。
        JSONObject input = new JSONObject();
        input.put("Bucket", "<your bucket name>");
        input.put("Location", "oss-cn-shanghai");

        // ジョブ出力を構成します。
        JSONObject output = new JSONObject();
        try {
            input.put("Object", URLEncoder.encode("mps-test/input/test.mp4", "utf-8"));
            output.put("OutputObject", URLEncoder.encode("mps-test/output/test", "utf-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("input URL encode failed");
        }
        output.put("TemplateId", "<transcode templateId>");
        output.put("Encryption", getEncryptionConfigs());
        JSONArray outputs = new JSONArray();
        outputs.add(output);
        // HLS 暗号化とトランスコードを送信します。
        com.aliyun.mts20140618.Client client = SubmitJobsForKMS.createMTSClient();
        com.aliyun.mts20140618.models.SubmitJobsRequest submitJobsRequest = new com.aliyun.mts20140618.models.SubmitJobsRequest()
                // ジョブ入力。
                .setInput(input.toJSONString())
                // ジョブ出力構成。
                .setOutputs(outputs.toJSONString())
                // 出力ファイルを格納する OSS バケット。
                .setOutputBucket("<your bucket name>")
                // OSS バケットが存在するリージョン。
                .setOutputLocation("oss-cn-shanghai")
                // MPS キューの ID。
                .setPipelineId("<transcode pipelineId>");
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try {
            // 必要に応じて、API 操作の応答を表示するための独自のコードを記述します。
            client.submitJobsWithOptions(submitJobsRequest, runtime);
        } catch (TeaException error) {
            // 実際のビジネスシナリオでは、例外を慎重に処理し、プロジェクトで例外を無視しないでください。この例では、例外は参照用にのみ提供されています。
            // エラーメッセージ。
            System.out.println(error.getMessage());
            // トラブルシューティング用の URL。
            System.out.println(error.getData().get("Recommend"));
            com.aliyun.teautil.Common.assertAsString(error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 実際のビジネスシナリオでは、例外を慎重に処理し、プロジェクトで例外を無視しないでください。この例では、例外は参照用にのみ提供されています。
            // エラーメッセージ。
            System.out.println(error.getMessage());
            // トラブルシューティング用の URL。
            System.out.println(error.getData().get("Recommend"));
            com.aliyun.teautil.Common.assertAsString(error.message);
        }

    }

    public static void main(String[] args) throws Exception{
        submitJobsForBase64();
    }
}

復号サービス

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;

public class DecryptServerBase64 {

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

    public class Base64DecryptHandler implements HttpHandler {
        /**
         * 復号リクエストを処理します。
         * @param httpExchange
         * @throws IOException
         */
        public void handle(HttpExchange httpExchange) throws IOException {
            String requestMethod = httpExchange.getRequestMethod();
            if ("GET".equalsIgnoreCase(requestMethod)) {
                // 復号鍵は暗号鍵と同じでなければなりません。
                byte[] key = "encryptionkey128".getBytes();
                // ヘッダーを設定します。
                setHeader(httpExchange, key);
                // Base64 アルゴリズムを使用してデコードされたプレーンテキストキーを返します。
                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);
        }
    }
    /**
     * サービスを開始します。
     * @throws IOException
     */
    private void startService() throws IOException {
        HttpServerProvider provider = HttpServerProvider.provider();
        // ポート 8888 にリスナーを設定します。一度に 30 のリクエストを受け入れることができます。
        HttpServer httpserver = provider.createHttpServer(new InetSocketAddress(8888), 30);
        httpserver.createContext("/", new Base64DecryptHandler());
        httpserver.start();
        System.out.println("base64 hls decrypt server started");
    }
}

参照資料

暗号化