当前位置: 首页 > 知识库问答 >
问题:

如何使用ClearKey加密WebM或MP4文件,然后播放它

司空炯
2023-03-14

我目前正在研究在浏览器中加密和播放加密视频的主题。在使用Widevine时,我已经在castlabs的DRMToday和Shaka播放器上取得了一些成功。

现在,我正在尝试使用ClearKey在没有外部服务的情况下加密视频,并在Chrome中播放(使用任何可以处理的js播放器)。

我确实使用MP4Box加密了单个mp4文件(mse eme用于创建加密配置),但我不知道如何在浏览器中播放它。HTML5的视频甚至没有触发“加密”事件。加密本身工作得很好——我能够用同样的工具用正确的密钥将其解密回来。

我试图从这个加密文件中创建一个DASH并在Shaka Player中播放它。我使用MP4Box创建了清单。我必须手动将缺少的xmlns添加到此文件中(xmlns: cenc="urn: mpeg: cenc: 2013"),以便DOMParser正确解析它。我不知道应该如何处理许可证。

我发现很少有播放编码的webm文件的工作示例(包括Shaka Player的演示页面)。如何加密webm文件?我确实找到了https://github.com/webmproject/webm-tools但它似乎需要构建完整的Chromium才能工作。

还有其他可以加密webm文件的工具吗?

共有3个答案

盖锦程
2023-03-14

您可以使用Azure Media Services在不同的流媒体协议(HLS、平滑流媒体和MPEG-DASH)中使用AES clear key动态加密多比特率MP4。你不必自己制作加密机。我们还有一个播放器,可以在所有浏览器中播放AES加密内容,例如,在现代浏览器中播放带DASH的AES,在Safari中播放带HLS的AES,在旧浏览器中播放带Flash的平滑流媒体AES。

您可以在此处查看一个示例:http://amsplayer.azurewebsites.net/azuremediaplayer.html.并选择与AES相关的样本流。您可以按照本教程为视频配置AES加密:https://azure.microsoft.com/en-us/documentation/articles/media-services-protect-with-aes128/.

祖翰音
2023-03-14

明确回答“HTML5的视频甚至没有触发“加密”事件”2019年,除非MSE与视频一起使用,否则Chrome不会触发OneCrypted事件,Firefox显示错误,表明没有MSE,EME无法工作。所以要播放加密视频,必须使用媒体源扩展。

这在留档中一点也不明显,但在这里突出显示https://github.com/cpearce/eme-in-non-fragmented-mp4

使用正确加密的媒体,您可以在MSE中添加单个MP4文件作为“段”并在chrome中播放(例如,使用此https://github.com/cpearce/mse-eme的修改版本)(我的测试仅为明钥,使用bento4首先片段,然后加密单个MP4文件-不要将片段与段混淆......)。这不是很有效,因为我假设在播放开始之前下载了整个文件(并保存在浏览器内存中),即它不像浏览器使用范围请求并管理文件下载和内存使用的直接html5视频元素播放。

汤跃
2023-03-14

这是我用来测试ClearKey DRM播放的一组文件。

MP4box(gpac)drm.xml规范文件,您可以在其中提供一个或多个要在init.mp4段内生成的PSSH表。

<?xml version="1.0" encoding="UTF-8" ?>
<GPACDRM type="CENC AES-CTR">
<!-- 
  kid=0x43215678123412341234123412341234
  key=0x12341234123412341234123412341234
  iv=0x22ee7d4745d3a26a
--> 

<!-- CENC -->
<DRMInfo type="pssh" version="1">
  <BS ID128="1077efecc0b24d02ace33c1e52e2fb4b"/>
  <BS bits="32" value="1"/>
  <BS ID128="43215678123412341234123412341234"/>
</DRMInfo>

<CrypTrack trackID="1" IsEncrypted="1" IV_size="8" first_IV="0x22ee7d4745d3a26a" saiSavedBox="senc">
  <key KID="0x43215678123412341234123412341234" value="0x12341234123412341234123412341234"/>
</CrypTrack>

</GPACDRM>

用于加密视频音频和分割片段的命令行。

MP4Box.exe -crypt gpacdrm.xml temp-v1.mp4 -out ./drm/temp-v1.mp4
MP4Box.exe -crypt gpacdrm.xml temp-a1.mp4 -out ./drm/temp-a1.mp4
MP4Box.exe -dash 6000 -frag 6000 -mem-frags -rap -profile dashavc264:live -profile-ext urn:hbbtv:dash:profile:isoff-live:2012 -min-buffer 3000  -bs-switching no -sample-groups-traf -single-traf -subsegs-per-sidx 1 -segment-name $RepresentationID$_$Number$$Init=i$ -segment-timeline -out manifest.mpd temp-v1.mp4#trackID=1:id=v1:period=p0 temp-a1.mp4#trackID=1:id=a1:period=p0

ShakaPlayer独立演示,用于ClearKey播放,使用Chrome或Firefox。我在网上找到了这段源代码,所以要归功于谁做的。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/shaka-player/2.1.0/shaka-player.compiled.js"></script>
    <title>MPEG-DASH Player Test</title>
    <script>
        var manifestUrl = 'https://my.server.com/drm/manifest_clearkey.mpd';
        var laUrl       = 'https://my.server.com/drm/laurl_ck.php';

        function initApp() {
            // Install built-in polyfills to patch browser incompatibilities.
            shaka.polyfill.installAll();

            // Check to see if the browser supports the basic APIs Shaka needs.
            if (shaka.Player.isBrowserSupported()) {
                // Everything looks good!
                initPlayer();
            } else {
                // This browser does not have the minimum set of APIs we need.
                console.error('Browser not supported!');
            }
        }

        function initPlayer() {
            // Create a Player instance.
            var video = document.getElementById('video');
            var player = new shaka.Player(video);

            // Configue
            player.configure({
                drm: {
                    servers: {
                        'org.w3.clearkey': laUrl
                    },
                    clearKeys: {
                        //'kid': 'key'
                    }
                }
            });

            // Attach player to the window to make it easy to access in the JS console.
            window.player = player;

            // Listen for error events.
            player.addEventListener('error', onErrorEvent);

            // Try to load a manifest.
            // This is an asynchronous process.
            player.load(manifestUrl).then(function () {
                // This runs if the asynchronous load is successful.
                console.log('The video has now been loaded!');
            }).catch(onError);  // onError is executed if the asynchronous load fails.
        }

        function onErrorEvent(event) {
            // Extract the shaka.util.Error object from the event.
            onError(event.detail);
        }

        function onError(error) {
            console.error('Error code', error.code, 'object', error);
            alert("ErrorCode="+error.code);
        }

        document.addEventListener('DOMContentLoaded', initApp);
    </script>
</head>
<body>
    <video id="video" autoplay controls></video>
</body>
</html>

ClearKey DRM“许可服务器php脚本”,播放器发送一个json文档,此脚本返回KID=KEY配对。

<?php
header( "Expires: Mon, 20 Dec 1998 01:00:00 GMT" );
header( "Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT" );
header( "Cache-Control: no-cache, must-revalidate" );
header( "Pragma: no-cache" );
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: origin,range,accept,accept-encoding,referer,content-type, SOAPAction,X-AxDRM-Message');
header('Access-Control-Allow-Methods: GET,HEAD,OPTIONS,POST');
header('Access-Control-Expose-Headers: server,range,content-range,content-length,content-type');
// write content-type header after OPTIONS check
// ClearKey DRM server

// some players may submit OPTIONS request(zero-length) before POST drm.xml submit
if ($_SERVER['REQUEST_METHOD']=="OPTIONS") {
    header("Content-Length: 0");
    header("Expires: -1");
    return;
}
//header('Content-Type: text/plain; charset=utf-8');
header('Content-Type: application/json; charset=utf-8');

// Request may have one or more KIDs(base64), read first KID from the request for now.
// KID base64 is without trailing "=" padding chars.
// Request : {"kids":["QyFWeBI0EjQSNBI0EjQSNA"],"type":"temporary"}
// Response: {"keys": [{"k": "EjQSNBI0EjQSNBI0EjQSNA", "kty": "oct", "kid": "QyFWeBI0EjQSNBI0EjQSNA" }], "type": "temporary"}
$req = file_get_contents('php://input'); // read POST bodypart
$json= json_decode($req);
$kidb= $json->{"kids"}[0]; // base64 format
$kid = bin2hex(base64_decode($kidb, true)); // hex format

// KID=KEY lookup table, find KEY and base64(trim trailing "==" chars)
// "EjQSNBI0EjQSNBI0EjQSNA==" -> "EjQSNBI0EjQSNBI0EjQSNA"
$keys = array(
  "43215678123412341234123412341234" => "12341234123412341234123412341234",
  "43215678123412341234123412341235" => "12341234123412341234123412341235",
  "43215678123412341234123412341236" => "12341234123412341234123412341236",
  "43215678123412341234123412341237" => "12341234123412341234123412341237",
  "43215678123412341234123412341238" => "12341234123412341234123412341238"
);
$key = base64_encode(hex2bin($keys[$kid]));
$key = str_replace("=", "", $key);

$data = "{\"keys\": [{\"k\": \$key, \"kty\": \"oct\", \"kid\": \$kid }], \"type\": \"temporary\"}";
$data = str_replace("\$key", "\"".$key."\"", $data);
$data = str_replace("\$kid", "\"".$kidb."\"", $data);

echo $data;

?>

使用CENC和ClearKey内容保护元素清单。

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:cenc="urn:mpeg:cenc:2013" xmlns:mas="urn:marlin:mas:1-0:services:schemas:mpd" xmlns:mspr="urn:microsoft:playready" maxSegmentDuration="PT0H0M6.000S" mediaPresentationDuration="PT0H1M30.000S" minBufferTime="PT3.000S" profiles="urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash264,urn:hbbtv:dash:profile:isoff-live:2012" type="static">


 <Period duration="PT0H1M30.000S" id="p0">
  <AdaptationSet lang="und" maxFrameRate="25" maxHeight="360" maxWidth="640" par="16:9" segmentAlignment="true" startWithSAP="1">
   <ContentProtection cenc:default_KID="43215678-1234-1234-1234-123412341234" schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc"/>
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
  <cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAFDIVZ4EjQSNBI0EjQSNBI0AAAAAA==</cenc:pssh>
</ContentProtection>
   <SegmentTemplate initialization="$RepresentationID$_i.mp4" media="$RepresentationID$_$Number$.m4s" startNumber="1" timescale="1000">
    <SegmentTimeline>
     <S d="6000" r="14" t="0"/>
    </SegmentTimeline>
   </SegmentTemplate>
   <Representation bandwidth="491773" codecs="avc1.4D4028" frameRate="25" height="360" id="v1" mimeType="video/mp4" sar="1:1" width="640">
   </Representation>
  </AdaptationSet>
  <AdaptationSet lang="und" segmentAlignment="true" startWithSAP="1">
   <ContentProtection cenc:default_KID="43215678-1234-1234-1234-123412341234" schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc"/>
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
  <cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAFDIVZ4EjQSNBI0EjQSNBI0AAAAAA==</cenc:pssh>
</ContentProtection>
   <SegmentTemplate initialization="$RepresentationID$_i.mp4" media="$RepresentationID$_$Number$.m4s" startNumber="1" timescale="1000">
    <SegmentTimeline>
     <S d="5973" t="0"/>
     <S d="5995" r="1"/>
     <S d="5994"/>
     <S d="5995" r="1"/>
     <S d="5994"/>
     <S d="5995"/>
     <S d="5994"/>
     <S d="5995" r="2"/>
     <S d="5994"/>
     <S d="5995" r="1"/>
     <S d="101"/>
    </SegmentTimeline>
   </SegmentTemplate>
   <Representation audioSamplingRate="48000" bandwidth="133119" codecs="mp4a.40.2" id="a1" mimeType="audio/mp4">
    <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
   </Representation>
  </AdaptationSet>
 </Period>
</MPD>

Manifest cenc:pssh包含KID值,如果只使用一个键,则很容易生成。请参阅pssh元素值的base64tohexdump。

00 00 00 34 70 73 73 68 01 00 00 00 
10 77 EF EC C0 B2 4D 02 AC E3 3C 1E 52 E2 FB 4B 
00 00 00 01 
43 21 56 78 12 34 12 34 12 34 12 34 12 34 12 34 
00 00 00 00
 类似资料:
  • 我一直试图在ShakaPlayer中播放加密的。WebM媒体文件,但没有太多成功,我在这里寻求任何经历过这一点的人的建议。如果这个很棒的开发人员社区有人能在这里指导我,那就太好了。 第1轮-我所尝试的(编码和虚线): 使用ffmpeg.将.mp4文件编码为多流Video.webm(VP9)&单流Audio.webm(Vorbis)文件 使用webm_tools/webm_dash_manifest

  • 我用WordPress开发了一个网站。我在主页上放了一段视频,它在Chrome,Mozila和IE中运行良好,但在Safari中运行良好。我已经使用了html5视频标签,有没有人可以建议我如何在Safari播放MP4视频?这是我正在使用的代码播放视频在我的网站。 上面的代码工作得很好,但在Safari中除外。有什么flash播放器解决方案播放MP4视频吗?

  • 我正在使用ChromeWeb驱动程序2.10 chromedriver_win32。使用SeleniumWebDriver 2.31压缩。2. 启用详细日志记录后,似乎期望的能力(https://sites.google.com/a/chromium.org/chromedriver/capabilities)传递得很好, 但Chrome Web驱动程序正在播放*。mp4而不是下载。 我尝试过如何

  • 下面是一个使用mediaSource API和MPEG DASH标准播放视频的演示。webm视频。这是使用的MPD文件: 有人知道如何获取/计算任何视频的“SegmentBase indexRange”和“Initialization range”数字吗?

  • 我正在尝试流式传输从FFmpeg编码的Webm视频文件。 然而,当我寻找到一个未被缓冲的位置时,视频播放停止。 我已验证是否下载了正确的字节范围。 知道是什么引起的吗?在x264中编码的mp4文件中,查找工作完美无瑕。Webm似乎是个问题。可能是视频编码方式有问题。 ffmpeg-i输入。mp4-编解码器:v libvpx-质量最佳-b:v 4000k-qmin 10-qmax 42-最大速率40

  • 问题内容: 我想用Java加密和解密文件,我已经阅读了这个URL http://www- users.york.ac.uk/~mal503/lore/pkencryption.htm ,我得到了两个文件,即公共安全证书和私有安全证书文件和private.pem文件,我将这些文件复制并粘贴到当前目录中,并按如下所示编写Java代码,当我运行此文件时,未执行任何加密或解密操作,请查看并告诉我我哪里出了