写完了不知道该发哪里,就发这里吧,有需要自取 
脚本能禁止使用clearkey然后就会回落到熟悉的wv,因为pssh需要拼凑才能得到很麻烦,直接通过脚本在控制台输出,方便快速拿key,主要是用来破dcv档不用下那破播放器还要捣鼓抓包了
只在火狐上测试过能用
无论是clearkey还是wv,只要是相同的文件用的就是相同的key,只是加密技术不同而已所以通过clearkey拿到的key一样可以用来破dcv不需要回落wv
脚本只适用于普通视频,4k和vr这种的话卖这么贵根本连测试片源都没有好吧应该是用不了的
wasm真是好方便,看下以后有没可能直接脚本拿key 
// ==UserScript==
// @name Disable ClearKey & Get PSSH
// @namespace http://tampermonkey.net/
// @version 0.0.1
// @description Disable ClearKey & Get PSSH
// @author You
// @match https://www.dmm.co.jp/digital/-/player/=/player=html5/act=playlist/pid=*
// @icon https://www.google.com/s2/favicons?sz=64&domain=dmm.co.jp
// @grant none
// ==/UserScript==
(function() {
'use strict';
// 禁用 ClearKey
const originalRequestMediaKeySystemAccess = navigator.requestMediaKeySystemAccess;
navigator.requestMediaKeySystemAccess = function(keySystem, configs) {
if (keySystem === 'org.w3.clearkey') {
return Promise.reject(new Error('ClearKey not supported'));
}
return originalRequestMediaKeySystemAccess.call(this, keySystem, configs);
};
let mpdKid = null;
let contentId = null;
let licenseURL = null;
let psshBase64 = null;
let licenseCookie = null;
let manifestURL = null;
// 提取 licenseUID 的正则表达式
function extractLicenseUID(cookieString) {
const match = cookieString.match(/licenseUID=([^;]+)/);
return match ? match[1] : null;
}
// 获取所有 cookies
const allCookies = document.cookie;
// 提取并输出 licenseUID
const licenseUID = extractLicenseUID(allCookies);
if (licenseUID) {
console.log('Extracted licenseUID:', licenseUID);
licenseCookie = `headers = { 'Cookie': 'licenseUID=${licenseUID}' }`;
} else {
console.log('licenseUID not found in cookies.');
}
// 保存原始 fetch
const originalFetch = window.fetch;
let mpdRequestCount = 0;
let licRequestCount = 0;
window.fetch = async function(...args) {
const request = args[0];
const options = args[1] || {};
// 判断 URL 是否以 manifest.mpd 结尾
if (typeof request === 'string' && request.endsWith('manifest.mpd')) {
mpdRequestCount++;
if (mpdRequestCount === 1) {
// console.log('Intercepted manifest.mpd URL:', request);
manifestURL = request;
// 获取响应
const response = await originalFetch.apply(this, args);
// 读取响应的内容
const responseText = await response.text();
// 正则表达式匹配 default_KID
const regex = /default_KID="([A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12})"/g;
let match;
let count = 0;
// 使用 while 循环来匹配所有匹配项
while ((match = regex.exec(responseText)) !== null) {
console.log('Matched default_KID:', match[1]); // match[1] 为捕获的 KID 值
count++;
if (count === 1) {
mpdKid = match[1].replace(/-/g, '').toLowerCase();
}
}
if (count === 0) {
console.log('No default_KID found.');
}
// 返回原始的响应
return response;
}
}
// 检查 URL 是否符合条件
if (typeof request === 'string' && request.startsWith('https://mlic.dmm')) {
licRequestCount++;
if (licRequestCount === 2) {
const url = new URL(request); // 使用 URL 对象解析 URL
licenseURL = request;
// 检查请求体是否存在并符合条件
if (options.body) {
const decoder = new TextDecoder(); // 解码器将字节转为字符串
const bodyText = decoder.decode(options.body).match(/{"v":.*?"}/);; // 解码为字符串
if (bodyText) {
contentId = bodyText[0];
} else {
console.log('%cNo matching content found in body.', 'color: red; font-weight: bold;');
}
} else {
console.log('%cNo body content in request.', 'color: red; font-weight: bold;');
}
// 如果 mpdKid 和 contentId 都已获取到,生成 PSSH
if (mpdKid && contentId) {
const encoder = new TextEncoder();
const contentIdBytes = encoder.encode(contentId);
const contentIdHex = Array.from(contentIdBytes)
.map(byte => byte.toString(16).padStart(2, '0'))
.join('');
(async () => {
const initModule = await import('https://emarsden.github.io/pssh-box-wasm/pkg/pssh_box_wasm.js');
await initModule.default();
psshBase64 = initModule.generate_widevine_pssh_b64(0, [mpdKid], '', contentIdHex, '', null, '', null);
})();
}
// 通过 setInterval 检查是否已经被赋值
const checkValue = setInterval(() => {
if (mpdKid) {
console.log('%cRequest Kid:\n', 'color: green; font-weight: bold;', mpdKid);
}
if (contentId) {
console.log('%cRequest contentId:\n', 'color: green; font-weight: bold;', contentId);
}
if (licenseURL) {
console.log('%cRequest License URL:\n', 'color: green; font-weight: bold;', request);
}
if (psshBase64) {
console.log('%cRequest PSSH:', 'color: green; font-weight: bold;', psshBase64);
}
if (licenseCookie) {
console.log('%cRequest Cookie:\n', 'color: green; font-weight: bold;', licenseCookie);
}
if (manifestURL) {
console.log('%cRequest Manifest URL:\n', 'color: green; font-weight: bold;', manifestURL);
}
// 全都有值时,停止检查
if (mpdKid && contentId && licenseURL && psshBase64 && licenseCookie && manifestURL) {
clearInterval(checkValue); // 清除定时器
}
}, 2000); // 每 2000 毫秒检查一次
}
}
// 调用原始 fetch
return originalFetch.apply(this, args);
};
})();