gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 13:05:35 26 4
gpt4 key购买 nike

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

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

我确实设法使用 MP4Box(和用于创建加密配置的 mse-eme)加密单个 mp4 文件,但我不知道如何在浏览器中播放它。 HTML5 的视频甚至没有触发“加密”事件。加密本身工作正常 - 我能够使用具有适当 key 的相同工具将其解密。

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

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

有没有其他工具可以加密webm文件?

最佳答案

这是我用来测试 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;

?>

Manifest 包含 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 值,如果只使用一个 key ,则很容易生成。请参阅 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

关于html - 如何使用ClearKey加密WebM或MP4文件然后播放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33632240/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com