crunchyroll optimizations and better widevine error handeling

This commit is contained in:
stratumadev 2025-05-11 16:48:39 +02:00
parent a727b4bcd6
commit 372f316974
3 changed files with 35 additions and 34 deletions

View file

@ -428,7 +428,7 @@ export default class Crunchy implements ServiceClass {
const cmsTokenReqOpts = {
headers: {
Authorization: `Bearer ${this.token.access_token}`,
'User-Agent': api.defaultUserAgent
...api.crunchyDefHeader
},
useProxy: true
};
@ -481,7 +481,7 @@ export default class Crunchy implements ServiceClass {
const searchReqOpts = {
headers: {
Authorization: `Bearer ${this.token.access_token}`,
'User-Agent': api.defaultUserAgent
...api.crunchyDefHeader
},
useProxy: true
};
@ -749,7 +749,7 @@ export default class Crunchy implements ServiceClass {
const AuthHeaders = {
headers: {
Authorization: `Bearer ${this.token.access_token}`,
'User-Agent': api.defaultUserAgent
...api.crunchyDefHeader
},
useProxy: true
};
@ -791,7 +791,7 @@ export default class Crunchy implements ServiceClass {
const AuthHeaders = {
headers: {
Authorization: `Bearer ${this.token.access_token}`,
'User-Agent': api.defaultUserAgent
...api.crunchyDefHeader
},
useProxy: true
};
@ -831,7 +831,7 @@ export default class Crunchy implements ServiceClass {
const newlyAddedReqOpts = {
headers: {
Authorization: `Bearer ${this.token.access_token}`,
'User-Agent': api.defaultUserAgent
...api.crunchyDefHeader
},
useProxy: true
};
@ -866,7 +866,7 @@ export default class Crunchy implements ServiceClass {
const AuthHeaders = {
headers: {
Authorization: `Bearer ${this.token.access_token}`,
'User-Agent': api.defaultUserAgent
...api.crunchyDefHeader
},
useProxy: true
};
@ -1103,7 +1103,7 @@ export default class Crunchy implements ServiceClass {
const AuthHeaders = {
headers: {
Authorization: `Bearer ${this.token.access_token}`,
'User-Agent': api.defaultUserAgent
...api.crunchyDefHeader
},
useProxy: true
};
@ -1280,12 +1280,7 @@ export default class Crunchy implements ServiceClass {
const AuthHeaders: RequestInit = {
headers: {
Authorization: `Bearer ${this.token.access_token}`,
// 'X-Cr-Disable-Drm': 'true',
// 'X-Cr-Enable-Drm': 'false',
// 'X-Cr-Stream-Limits': 'false',
'User-Agent': api.defaultUserAgent
//'X-Cr-Segment-CDN': 'all',
//'User-Agent': 'Crunchyroll/1.8.0 Nintendo Switch/12.3.12.0 UE4/4.27'
...api.crunchyDefHeader
}
};
@ -1316,17 +1311,13 @@ export default class Crunchy implements ServiceClass {
if (options.chapters) {
//Make Chapter Request
const chapterRequest = await this.req.getData(`https://static.crunchyroll.com/skip-events/production/${currentMediaId}.json`, {
headers: {
'User-Agent': api.defaultUserAgent
}
headers: api.crunchyDefHeader
});
if(!chapterRequest.ok || !chapterRequest.res){
//Old Chapter Request Fallback
console.warn('Chapter request failed, attempting old API');
const oldChapterRequest = await this.req.getData(`https://static.crunchyroll.com/datalab-intro-v2/${currentMediaId}.json`, {
headers: {
'User-Agent': api.defaultUserAgent
}
headers: api.crunchyDefHeader
});
if(!oldChapterRequest.ok || !oldChapterRequest.res) {
console.warn('Old Chapter API request failed');
@ -1809,7 +1800,7 @@ export default class Crunchy implements ServiceClass {
await this.refreshToken(true, true);
encryptionKeysVideo = await getKeysWVD(chosenVideoSegments.pssh_wvd, api.drm_widevine, {
Authorization: `Bearer ${this.token.access_token}`,
'User-Agent': api.defaultUserAgent,
...api.crunchyDefHeader,
Pragma: 'no-cache',
'Cache-Control': 'no-cache',
'content-type': 'application/octet-stream',
@ -1822,7 +1813,7 @@ export default class Crunchy implements ServiceClass {
await this.refreshToken(true, true);
encryptionKeysAudio = await getKeysWVD(chosenAudioSegments.pssh_wvd, api.drm_widevine, {
Authorization: `Bearer ${this.token.access_token}`,
'User-Agent': api.defaultUserAgent,
...api.crunchyDefHeader,
Pragma: 'no-cache',
'Cache-Control': 'no-cache',
'content-type': 'application/octet-stream',
@ -2067,9 +2058,7 @@ export default class Crunchy implements ServiceClass {
const outFile = parseFileName(options.fileName + '.' + (mMeta.lang?.name || lang.name), variables, options.numbers, options.override).join(path.sep);
console.info(`Output filename: ${outFile}`);
const chunkPage = await this.req.getData(selPlUrl, {
headers: {
'User-Agent': api.defaultUserAgent
}
headers: api.crunchyDefHeader,
});
if(!chunkPage.ok || !chunkPage.res){
console.error('CAN\'T FETCH VIDEO PLAYLIST!');
@ -2219,9 +2208,7 @@ export default class Crunchy implements ServiceClass {
continue;
if(options.dlsubs.includes('all') || options.dlsubs.includes(langItem.locale)){
const subsAssReq = await this.req.getData(subsItem.url, {
headers: {
'User-Agent': api.defaultUserAgent
}
headers: api.crunchyDefHeader
});
if(subsAssReq.ok && subsAssReq.res){
let sBody = await subsAssReq.res.text();
@ -2594,7 +2581,7 @@ export default class Crunchy implements ServiceClass {
const AuthHeaders = {
headers: {
Authorization: `Bearer ${this.token.access_token}`,
'User-Agent': api.defaultUserAgent
...api.crunchyDefHeader
},
useProxy: true
};
@ -2623,7 +2610,7 @@ export default class Crunchy implements ServiceClass {
const AuthHeaders = {
headers: {
Authorization: `Bearer ${this.token.access_token}`,
'User-Agent': api.defaultUserAgent
...api.crunchyDefHeader
},
useProxy: true
};

View file

@ -45,12 +45,15 @@ try {
const stats = fs.statSync(file);
if (stats.size < 1024 * 8 && stats.isFile()) {
const fileContents = fs.readFileSync(file, { encoding: 'utf8' });
if (fileContents.includes('-BEGIN PRIVATE KEY-') || fileContents.includes('-BEGIN RSA PRIVATE KEY-')) {
if (fileContents.startsWith('-----BEGIN RSA PRIVATE KEY-----') && fileContents.endsWith('-----END RSA PRIVATE KEY-----')) {
privateKey = fs.readFileSync(file);
}
if (fileContents.includes('widevine_cdm_version')) {
if (fileContents.includes('widevine_cdm_version') && fileContents.includes('oem_crypto_security_patch_level') && !fileContents.startsWith('WVD')) {
identifierBlob = fs.readFileSync(file);
}
if (fileContents.startsWith('WVD')) {
console.warn('Found WVD file in folder, AniDL currently only supports device_client_id_blob and device_private_key, make sure to have them in the widevine folder.');
}
}
});
} catch (e) {

View file

@ -36,6 +36,7 @@ export type APIType = {
/**
* Header
*/
crunchyDefHeader: Record<string, string>,
crunchyAuthHeader: Record<string, string>,
hd_apikey: string,
hd_devName: string,
@ -65,7 +66,7 @@ const api: APIType = {
session: `${domain.api}/start_session.0.json`,
collections: `${domain.api}/list_collections.0.json`,
// This User-Agent bypasses Cloudflare security of the newer Endpoint
defaultUserAgent: 'Crunchyroll/4.77.2 (bundle_identifier:com.crunchyroll.iphone; build_number:4139672.438176041) iOS/18.3.2 Gravity/4.77.2',
defaultUserAgent: 'Crunchyroll/4.77.3 (bundle_identifier:com.crunchyroll.iphone; build_number:4148147.285670380) iOS/18.3.2 Gravity/4.77.3',
beta_profile: `${domain.api_beta}/accounts/v1/me/profile`,
beta_cmsToken: `${domain.api_beta}/index/v2`,
search: `${domain.api_beta}/content/v2/discover/search`,
@ -79,6 +80,7 @@ const api: APIType = {
drm_widevine: `${domain.www}/license/v1/license/widevine`,
// playready endpoint currently broken
drm_playready: `${domain.www}/license/v1/license/playReady`,
crunchyDefHeader: {},
crunchyAuthHeader: {},
//hidive API
hd_apikey: '508efd7b42d546e19cc24f4d0b414e57e351ca73',
@ -93,10 +95,19 @@ const api: APIType = {
hd_new_version: '6.0.1.bbf09a2'
};
api.crunchyDefHeader = {
'User-Agent': api.defaultUserAgent,
'Accept': '*/*',
'Accept-Encoding': 'gzip;q=1.0, compress;q=0.5',
'Accept-Language': 'de-IT;q=1.0, it-IT;q=0.9, en-GB;q=0.8',
'Connection': 'keep-alive',
'Host': 'www.crunchyroll.com'
};
// set header
api.crunchyAuthHeader = {
'User-Agent': api.defaultUserAgent,
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
...api.crunchyDefHeader
};
export {