所以我们接下来只需要给cdmServer拓展一下设置证书,在node部分拿到证书就可以了
剩下的不算很难了,我就只罗列一些关键的代码
获取pssh,这里我偷懒排序取了个最小pssh
function getPSSH(url, Cookie) {
return new Promise(async (resolve, reject) => {
try {
const { data } = await axios.request({
method: 'get',
url: url,
headers: {
'Cookie': Cookie
},
})
const reg = /<cenc\:pssh>(.*)<\/cenc\:pssh>/g
const psshArray = sortArray([...data.matchAll(reg)].map(item => item[1]))[0]
resolve(psshArray)
} catch (error) {
console.log(error)
reject()
}
})
}
然后获取证书
const certificate = await new Promise((resolve) => {
axios.post(domain + cdmServer, buf, {
headers: cdmHeader,
responseType: "arraybuffer"
}).then((response) => {
resolve(response.data.toString('hex'))
}).catch((err) => {
console.log('err', err)
})
})
在服务器端判断是否有证书,有的话就设置
certificate= form.get("certificate")
if not certificate is None:
certificate=bytes.fromhex(certificate)
cdmInstance.set_service_certificate(cdm_session_id,certificate)
那么我们就可以拿到密钥了,先在js创建一个密钥数组
const keyList = data.data.map((item) => item.key).map((key) => {
return '-decryption_key ' + key
})
分别解密mp4和m4a
const fileList = await downloadDRMViedeo(mpd, baseDir, mediaItem.id, Cookie)
const mergeFile = []
for (let index = 0; index < fileList.length; index++) {
const filePath = fileList[index]
await new Promise((resolve) => {
ffmpeg().input(baseDir + '/' + filePath).inputOptions([
...keyList,
]).audioCodec('copy').videoCodec('copy').output(baseDir + '/drm_' + filePath).on("end", () => {
mergeFile.push(baseDir + '/drm_' + filePath)
resolve();
}).run()
})
}
然后将两个视频合并到一起就可以了
await new Promise((resolve) => {
ffmpeg().input(mergeFile[0]).input(mergeFile[1]).audioCodec('copy').videoCodec('copy').output(baseDir + '/decrypt_drm_' + mediaItem.id + '.mp4')
.on('error', function (err) {
console.log('An error occurred: ' + err.message);
})
.on('end', function () {
resolve();
})
.run();
})
最后调用deleteVideoFiles分别删除残余文件
await deleteVideoFiles(baseDir, mediaItem.id + '')
await deleteVideoFiles(baseDir, 'drm_' + mediaItem.id)
这里的删除是我组合的功能函数,也抄了网上的
传入路径和文件前缀就可以自动删除
function deleteFiles(files, callback) {
if (files.length == 0) {
callback()
}
var i = files.length;
files.forEach(function (filepath) {
fs.unlink(filepath, function (err) {
i--;
if (err) {
callback(err);
return;
} else if (i <= 0) {
callback(null);
}
});
});
}
async function deleteVideoFiles(path, id) {
return new Promise(async (resolve) => {
const files = await getVideoFiles(path, id)
deleteFiles(files, resolve)
})
}
那么就实现了onlyfans的drm解密啦!
因为没法贴图,所以这里贴个玩偶姐姐代替图吧
完结撒花~