我已经使用 clear key 实现了 EME,遵循以下实用指南: https ://www.html5rocks.com/tutorials/eme/basics/
我已经使用 webm-encrypt npm 包加密了一个音频,提供了一个密钥和 webm 音频文件。我在明文密钥代码中使用相同的密钥来解密音频。当我在本地使用加密的音频文件时,它工作正常,将 src 设置为:
audio.src = './encrypted.webm'
另一方面,我将相同的加密文件存储在 s3 中。问题是,当我将音频 src 指向我的服务器 api 时,它又重定向到加密音频文件的预签名 s3 url,音频没有播放,我在控制台中看到以下错误:
无法生成许可证请求 TypeError:无法在“MediaKeySession”上执行“generateRequest”:initDataType 参数为空。
audio 元素不为空,并且也触发了加密事件,但 event.initData 和 event.initDataType 都是空的。不知道我在这里缺少什么。
main.js
"use strict";
var KEY = new Uint8Array([
0xeb,0xdd,0x62,0xf1,0x68,0x14,0xd2,0x7b,
0x68,0xef,0x12,0x2a,0xfc,0xe4,0xae,0x3c,
]);
var config = [
{
initDataTypes: ["webm"],
videoCapabilities: [
{
contentType: 'video/webm; codecs="vp8"',
},
],
audioCapabilities: [
{ contentType: 'audio/webm; codecs="opus"' },
{ contentType: 'audio/webm; codecs="vorbis"' },
],
},
];
var audio = document.querySelector("audio");
audio.addEventListener("encrypted", handleEncrypted, false);
createMediaKeys().then(() => {
//src points to server api
audio.src = "/api/audio?file=encrypted1.webm";
});
function createMediaKeys() {
return navigator
.requestMediaKeySystemAccess("org.w3.clearkey", config)
.then((keySystemAccess) => {
return keySystemAccess.createMediaKeys();
})
.then((mediaKeys) => {
return audio.setMediaKeys(mediaKeys);
})
.catch(function (error) {
console.error("Failed to set up MediaKeys", error);
});
}
function handleEncrypted(event) {
var session = audio.mediaKeys.createSession();
session.addEventListener("message", handleMessage, false);
// error occurs at this line
session
.generateRequest(event.initDataType, event.initData)
.catch(function (error) {
console.error("Failed to generate a license request", error);
});
}
function handleMessage(event) {
var license = generateLicense(event.message);
var session = event.target;
session.update(license).catch(function (error) {
console.error("Failed to update the session", error);
});
}
function toBase64(u8arr) {
return btoa(String.fromCharCode.apply(null, u8arr))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=*$/, "");
}
function generateLicense(message) {
var request = JSON.parse(new TextDecoder().decode(message));
console.assert(request.kids.length === 1);
var keyObj = {
kty: "oct",
alg: "A128KW",
kid: request.kids[0],
k: toBase64(KEY),
};
return new TextEncoder().encode(
JSON.stringify({
keys: [keyObj],
})
);
}
索引.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EME with Clear Key</title>
</head>
<body>
<div id="audio-player">
<audio controls>
<p>This browser does not support the audio element.</p>
</audio>
</div>
<script src="./main.js"></script>
</body>
</html>
服务器.js
app.get("/api/audio", (req, res) => {
const params = {
Bucket: "test",
Key: req.query.file,
};
const url = AWSS3.getSignedUrl("getObject", params);
res.setHeader("Cache-Control", "public, max-age=0");
return res.redirect(302, url);
});