Implement a mp4decrypt native module

This commit is contained in:
AnimeDL 2024-03-29 15:49:11 -07:00
parent c82197a585
commit 368f1fd306
7 changed files with 309 additions and 109 deletions

View file

@ -1,4 +1,3 @@
ffmpeg: "ffmpeg.exe"
mkvmerge: "mkvmerge.exe"
ffprobe: "ffprobe.exe"
mp4decrypt: "mp4decrypt.exe"

View file

@ -10,7 +10,6 @@ import { console } from './modules/log';
import shlp from 'sei-helper';
import m3u8 from 'm3u8-parsed';
import streamdl, { M3U8Json } from './modules/hls-download';
import { exec } from './modules/sei-helper-fixes';
// custom modules
import * as fontsData from './modules/module.fontsData';
@ -19,6 +18,7 @@ import * as yamlCfg from './modules/module.cfg-loader';
import * as yargs from './modules/module.app-args';
import Merger, { Font, MergerInput, SubtitleInput } from './modules/module.merger';
import getKeys, { canDecrypt } from './modules/widevine';
import mp4decrypt from 'mp4decryptjs';
//import vttConvert from './modules/module.vttconvert';
// args
@ -1408,7 +1408,7 @@ export default class Crunchy implements ServiceClass {
if (
(s.match(/hls/) || s.match(/dash/))
&& !(s.match(/hls/) && s.match(/drm/))
&& !((!canDecrypt || !this.cfg.bin.mp4decrypt) && s.match(/drm/))
//&& !((!canDecrypt || !this.cfg.bin.mp4decrypt) && s.match(/drm/))
&& !s.match(/trailer/)
) {
const pb = Object.values(pbStreams[s]).map(v => {
@ -1681,7 +1681,7 @@ export default class Crunchy implements ServiceClass {
}
//Handle Decryption if needed
if ((chosenVideoSegments.pssh || chosenAudioSegments.pssh) && (videoDownloaded || audioDownloaded)) {
if ((chosenVideoSegments.pssh || chosenAudioSegments.pssh) && (videoDownloaded || audioDownloaded) && canDecrypt) {
const assetIdRegex = chosenVideoSegments.segments[0].uri.match(/\/assets\/(?:p\/)?([^_,]+)/);
const assetId = assetIdRegex ? assetIdRegex[1] : null;
const sessionId = new Date().getUTCMilliseconds().toString().padStart(3, '0') + process.hrtime.bigint().toString().slice(0, 13);
@ -1709,61 +1709,55 @@ export default class Crunchy implements ServiceClass {
console.error('Failed to get encryption keys');
return undefined;
}
/*const keys = {} as Record<string, string>;
const keys = {} as Record<string, string>;
encryptionKeys.forEach(function(key) {
keys[key.kid] = key.key;
});*/
});
if (this.cfg.bin.mp4decrypt) {
const commandBase = `--show-progress --key ${encryptionKeys[1].kid}:${encryptionKeys[1].key} `;
const commandVideo = commandBase+`"${tsFile}.video.enc.ts" "${tsFile}.video.ts"`;
const commandAudio = commandBase+`"${tsFile}.audio.enc.ts" "${tsFile}.audio.ts"`;
if (videoDownloaded) {
console.info('Started decrypting video');
const decryptVideo = exec('mp4decrypt', `"${this.cfg.bin.mp4decrypt}"`, commandVideo);
if (!decryptVideo.isOk) {
console.error(decryptVideo.err);
console.error(`Decryption failed with exit code ${decryptVideo.err.code}`);
return undefined;
} else {
console.info('Decryption done for video');
if (!options.nocleanup) {
fs.removeSync(`${tsFile}.video.enc.ts`);
}
files.push({
type: 'Video',
path: `${tsFile}.video.ts`,
lang: lang,
isPrimary: isPrimary
});
if (videoDownloaded) {
console.info('Started decrypting video');
const decryptVideo = await mp4decrypt(`${tsFile}.video.enc.ts`, `${tsFile}.video.ts`, keys);
if (!decryptVideo) {
console.error('Decryption of video failed');
return undefined;
} else {
console.info('Decryption done for video');
if (!options.nocleanup) {
fs.removeSync(`${tsFile}.video.enc.ts`);
}
files.push({
type: 'Video',
path: `${tsFile}.video.ts`,
lang: lang,
isPrimary: isPrimary
});
}
}
if (audioDownloaded) {
console.info('Started decrypting audio');
const decryptAudio = exec('mp4decrypt', `"${this.cfg.bin.mp4decrypt}"`, commandAudio);
if (!decryptAudio.isOk) {
console.error(decryptAudio.err);
console.error(`Decryption failed with exit code ${decryptAudio.err.code}`);
return undefined;
} else {
if (!options.nocleanup) {
fs.removeSync(`${tsFile}.audio.enc.ts`);
}
files.push({
type: 'Audio',
path: `${tsFile}.audio.ts`,
lang: lang,
isPrimary: isPrimary
});
console.info('Decryption done for audio');
if (audioDownloaded) {
console.info('Started decrypting audio');
const decryptAudio = await mp4decrypt(`${tsFile}.audio.enc.ts`, `${tsFile}.audio.ts`, keys);
if (!decryptAudio) {
console.error('Decryption of audio failed');
return undefined;
} else {
if (!options.nocleanup) {
fs.removeSync(`${tsFile}.audio.enc.ts`);
}
files.push({
type: 'Audio',
path: `${tsFile}.audio.ts`,
lang: lang,
isPrimary: isPrimary
});
console.info('Decryption done for audio');
}
} else {
console.warn('mp4decrypt not found, files need decryption. Decryption Keys:', encryptionKeys);
}
} else {
if (!canDecrypt) {
console.error('CDM Missing, unable to decrypt.');
return undefined;
}
files.push({
type: 'Video',
path: `${tsFile}.video.enc.ts`,

View file

@ -20,7 +20,6 @@ By default this application uses the following paths to programs (main executabl
* `ffmpeg.exe` (From PATH)
* `ffprobe.exe` (From PATH)
* `mkvmerge.exe` (From PATH)
* `mp4decrypt.exe` (From PATH)
To change these paths you need to edit `bin-path.yml` in `./config/` directory.
@ -63,10 +62,11 @@ Dependencies that are only required for running from code. These are not require
* NodeJS >= 14.6.0 (https://nodejs.org/)
* NPM >= 6.9.0 (https://www.npmjs.org/)
* PNPM >= 7.0.0 (https://pnpm.io/)
* CMake >= ??? (https://cmake.org/)
### Build Instructions
Please note that NodeJS, NPM, and PNPM must be installed on your system. For instructions on how to install pnpm, check (https://pnpm.io/installation)
Please note that NodeJS, NPM, PNPM, and CMake must be installed on your system. For instructions on how to install pnpm, check (https://pnpm.io/installation)
First clone this repo `git clone https://github.com/anidl/multi-downloader-nx.git`.
@ -79,10 +79,10 @@ If you want to package the application, run pnpm run build-`{platform}`-`{type}`
## DRM Decryption
### Decryption Requirements
* mp4decrypt >= Any (http://www.bento4.com/) - Only required for decrypting
### Instructions
In order to decrypt DRM content, you will need to have a dumped CDM, after that you will need to place the CDM files (`device_client_id_blob` and `device_private_key`) into the `./widevine/` directory. For legal reasons we do not include the CDM with the software, and you will have to source one yourself.
In order to decrypt DRM content, you will need to have a dumped CDM, after that you will need to place the CDM files (blob file and pem file) into the `./widevine/` directory. For legal reasons we do not include the CDM with the software, and you will have to source one yourself.
### Disclaimer
We do not support nor condone piracy

View file

@ -19,6 +19,9 @@ import * as yamlCfg from './modules/module.cfg-loader';
import * as yargs from './modules/module.app-args';
import Merger, { Font, MergerInput, SubtitleInput } from './modules/module.merger';
import vtt2ass from './modules/module.vtt2ass';
import getKeys, { canDecrypt } from './modules/widevine';
import { KeyContainer } from './modules/license';
import mp4decrypt from 'mp4decryptjs';
// load req
import { domain, api } from './modules/module.api-urls';
@ -40,9 +43,6 @@ import { Episode, NewHidiveEpisodeExtra, NewHidiveSeason, NewHidiveSeriesExtra }
import { NewHidiveEpisode } from './@types/newHidiveEpisode';
import { NewHidivePlayback, Subtitle } from './@types/newHidivePlayback';
import { MPDParsed, parse } from './modules/module.transform-mpd';
import getKeys, { canDecrypt } from './modules/widevine';
import { exec } from './modules/sei-helper-fixes';
import { KeyContainer } from './modules/license';
export default class Hidive implements ServiceClass {
public cfg: yamlCfg.ConfigObject;
@ -1130,6 +1130,7 @@ export default class Hidive implements ServiceClass {
const subsMargin = 0;
const chosenFontSize = options.originalFontSize ? undefined : options.fontSize;
let encryptionKeys: KeyContainer[] = [];
const keys: Record<string, string> = {};
if (!canDecrypt) console.warn('Decryption not enabled!');
if (!this.cfg.bin.ffmpeg)
@ -1237,11 +1238,14 @@ export default class Hidive implements ServiceClass {
console.info(`Selected (Available) Audio Languages: ${chosenAudios.map(a => a.language.name).join(', ')}`);
console.info('Stream URL:', chosenVideoSegments.segments[0].map.uri.split('/init.mp4')[0]);
if (chosenAudios[0].pssh || chosenVideoSegments.pssh) {
if ((chosenAudios[0].pssh || chosenVideoSegments.pssh) && canDecrypt) {
encryptionKeys = await getKeys(chosenVideoSegments.pssh, 'https://shield-drm.imggaming.com/api/v2/license', {
'Authorization': `Bearer ${selectedEpisode.jwtToken}`,
'X-Drm-Info': 'eyJzeXN0ZW0iOiJjb20ud2lkZXZpbmUuYWxwaGEifQ==',
});
encryptionKeys.forEach(function(key) {
keys[key.kid] = key.key;
});
}
if (!options.novids) {
@ -1288,30 +1292,22 @@ export default class Hidive implements ServiceClass {
console.error('Failed to get encryption keys');
return undefined;
}
if (this.cfg.bin.mp4decrypt) {
const commandBase = `--show-progress --key ${encryptionKeys[1].kid}:${encryptionKeys[1].key} `;
const commandVideo = commandBase+`"${tsFile}.video.enc.ts" "${tsFile}.video.ts"`;
console.info('Started decrypting video');
const decryptVideo = exec('mp4decrypt', `"${this.cfg.bin.mp4decrypt}"`, commandVideo);
if (!decryptVideo.isOk) {
console.error(decryptVideo.err);
console.error(`Decryption failed with exit code ${decryptVideo.err.code}`);
return undefined;
} else {
console.info('Decryption done for video');
if (!options.nocleanup) {
fs.removeSync(`${tsFile}.video.enc.ts`);
}
files.push({
type: 'Video',
path: `${tsFile}.video.ts`,
lang: chosenAudios[0].language,
isPrimary: true
});
}
console.info('Started decrypting video');
const decryptVideo = await mp4decrypt(`${tsFile}.video.enc.ts`, `${tsFile}.video.ts`, keys);
if (!decryptVideo) {
console.error('Decryption of video failed');
return undefined;
} else {
console.warn('mp4decrypt not found, files need decryption. Decryption Keys:', encryptionKeys);
console.info('Decryption done for video');
if (!options.nocleanup) {
fs.removeSync(`${tsFile}.video.enc.ts`);
}
files.push({
type: 'Video',
path: `${tsFile}.video.ts`,
lang: chosenAudios[0].language,
isPrimary: true
});
}
}
}
@ -1366,30 +1362,22 @@ export default class Hidive implements ServiceClass {
console.error('Failed to get encryption keys');
return undefined;
}
if (this.cfg.bin.mp4decrypt) {
const commandBase = `--show-progress --key ${encryptionKeys[1].kid}:${encryptionKeys[1].key} `;
const commandAudio = commandBase+`"${tsFile}.audio.enc.ts" "${tsFile}.audio.ts"`;
console.info('Started decrypting audio');
const decryptAudio = exec('mp4decrypt', `"${this.cfg.bin.mp4decrypt}"`, commandAudio);
if (!decryptAudio.isOk) {
console.error(decryptAudio.err);
console.error(`Decryption failed with exit code ${decryptAudio.err.code}`);
return undefined;
} else {
if (!options.nocleanup) {
fs.removeSync(`${tsFile}.audio.enc.ts`);
}
files.push({
type: 'Audio',
path: `${tsFile}.audio.ts`,
lang: chosenAudioSegments.language,
isPrimary: chosenAudioSegments.default
});
console.info('Decryption done for audio');
}
console.info('Started decrypting audio');
const decryptAudio = await mp4decrypt(`${tsFile}.audio.enc.ts`, `${tsFile}.audio.ts`, keys);
if (!decryptAudio) {
console.error('Decryption of audio failed');
return undefined;
} else {
console.warn('mp4decrypt not found, files need decryption. Decryption Keys:', encryptionKeys);
if (!options.nocleanup) {
fs.removeSync(`${tsFile}.audio.enc.ts`);
}
files.push({
type: 'Audio',
path: `${tsFile}.audio.ts`,
lang: chosenAudioSegments.language,
isPrimary: chosenAudioSegments.default
});
console.info('Decryption done for audio');
}
}
}

View file

@ -84,7 +84,6 @@ export type ConfigObject = {
ffmpeg?: string,
mkvmerge?: string,
ffprobe?: string,
mp4decrypt?: string
},
cli: {
[key: string]: any
@ -149,7 +148,6 @@ const loadBinCfg = async () => {
ffmpeg: 'ffmpeg',
mkvmerge: 'mkvmerge',
ffprobe: 'ffprobe',
mp4decrypt: 'mp4decrypt'
};
const keys = Object.keys(defaultBin) as (keyof typeof defaultBin)[];
for(const dir of keys){

View file

@ -1,7 +1,7 @@
{
"name": "multi-downloader-nx",
"short_name": "aniDL",
"version": "4.5.2",
"version": "4.6.0",
"description": "Downloader for Crunchyroll, Funimation, or Hidive via CLI or GUI",
"keywords": [
"download",
@ -61,6 +61,7 @@
"long": "^5.2.3",
"lookpath": "^1.2.2",
"m3u8-parsed": "^1.3.0",
"mp4decryptjs": "^1.0.1",
"mpd-parser": "^1.3.0",
"open": "^8.4.2",
"protobufjs": "^7.2.5",

View file

@ -62,6 +62,9 @@ dependencies:
m3u8-parsed:
specifier: ^1.3.0
version: 1.3.0
mp4decryptjs:
specifier: ^1.0.1
version: 1.0.1
mpd-parser:
specifier: ^1.3.0
version: 1.3.0
@ -2373,6 +2376,18 @@ packages:
dependencies:
color-convert: 2.0.1
/aproba@2.0.0:
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
dev: false
/are-we-there-yet@3.0.1:
resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
dependencies:
delegates: 1.0.0
readable-stream: 3.6.2
dev: false
/arg@4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
dev: true
@ -2460,6 +2475,16 @@ packages:
engines: {node: '>=4'}
dev: true
/axios@1.6.8(debug@4.3.4):
resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==}
dependencies:
follow-redirects: 1.15.6(debug@4.3.4)
form-data: 4.0.0
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
dev: false
/axobject-query@3.1.1:
resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==}
dependencies:
@ -2558,6 +2583,12 @@ packages:
chainsaw: 0.1.0
dev: true
/bindings@1.5.0:
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
dependencies:
file-uri-to-path: 1.0.0
dev: false
/bl@4.1.0:
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
dependencies:
@ -2738,6 +2769,11 @@ packages:
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
dev: false
/chownr@2.0.0:
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
engines: {node: '>=10'}
dev: false
/cliui@7.0.4:
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
dependencies:
@ -2783,6 +2819,28 @@ packages:
readable-stream: 2.3.8
dev: true
/cmake-js@7.3.0:
resolution: {integrity: sha512-dXs2zq9WxrV87bpJ+WbnGKv8WUBXDw8blNiwNHoRe/it+ptscxhQHKB1SJXa1w+kocLMeP28Tk4/eTCezg4o+w==}
engines: {node: '>= 14.15.0'}
hasBin: true
dependencies:
axios: 1.6.8(debug@4.3.4)
debug: 4.3.4
fs-extra: 11.2.0
lodash.isplainobject: 4.0.6
memory-stream: 1.0.0
node-api-headers: 1.1.0
npmlog: 6.0.2
rc: 1.2.8
semver: 7.5.4
tar: 6.2.1
url-join: 4.0.1
which: 2.0.2
yargs: 17.7.2
transitivePeerDependencies:
- supports-color
dev: false
/color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
@ -2800,6 +2858,11 @@ packages:
/color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
/color-support@1.1.3:
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
hasBin: true
dev: false
/combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
@ -2814,6 +2877,10 @@ packages:
resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==}
dev: true
/console-control-strings@1.1.0:
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
dev: false
/content-disposition@0.5.4:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'}
@ -3004,6 +3071,10 @@ packages:
engines: {node: '>=0.4.0'}
dev: false
/delegates@1.0.0:
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
dev: false
/depd@2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
@ -3699,6 +3770,10 @@ packages:
dependencies:
flat-cache: 3.0.4
/file-uri-to-path@1.0.0:
resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
dev: false
/fill-range@7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
@ -3737,6 +3812,18 @@ packages:
/flatted@3.2.7:
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
/follow-redirects@1.15.6(debug@4.3.4):
resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
dependencies:
debug: 4.3.4
dev: false
/for-each@0.3.3:
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
dependencies:
@ -3788,6 +3875,15 @@ packages:
universalify: 2.0.0
dev: false
/fs-extra@11.2.0:
resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==}
engines: {node: '>=14.14'}
dependencies:
graceful-fs: 4.2.11
jsonfile: 6.1.0
universalify: 2.0.0
dev: false
/fs-extra@8.1.0:
resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
engines: {node: '>=6 <7 || >=8'}
@ -3807,6 +3903,13 @@ packages:
universalify: 2.0.0
dev: false
/fs-minipass@2.1.0:
resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
engines: {node: '>= 8'}
dependencies:
minipass: 3.3.6
dev: false
/fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
@ -3835,6 +3938,20 @@ packages:
/functions-have-names@1.2.3:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
/gauge@4.0.4:
resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
dependencies:
aproba: 2.0.0
color-support: 1.1.3
console-control-strings: 1.1.0
has-unicode: 2.0.1
signal-exit: 3.0.7
string-width: 4.2.3
strip-ansi: 6.0.1
wide-align: 1.1.5
dev: false
/gensync@1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
@ -3987,6 +4104,10 @@ packages:
dependencies:
has-symbols: 1.0.3
/has-unicode@2.0.1:
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
dev: false
/has@1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
engines: {node: '>= 0.4.0'}
@ -4377,6 +4498,10 @@ packages:
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
dev: true
/lodash.isplainobject@4.0.6:
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
dev: false
/lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
@ -4452,6 +4577,12 @@ packages:
engines: {node: '>= 0.6'}
dev: false
/memory-stream@1.0.0:
resolution: {integrity: sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww==}
dependencies:
readable-stream: 3.6.2
dev: false
/merge-descriptors@1.0.1:
resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
dev: false
@ -4514,6 +4645,26 @@ packages:
/minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
/minipass@3.3.6:
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
engines: {node: '>=8'}
dependencies:
yallist: 4.0.0
dev: false
/minipass@5.0.0:
resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
engines: {node: '>=8'}
dev: false
/minizlib@2.1.2:
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
engines: {node: '>= 8'}
dependencies:
minipass: 3.3.6
yallist: 4.0.0
dev: false
/mkdirp-classic@0.5.3:
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
dev: false
@ -4525,6 +4676,23 @@ packages:
minimist: 1.2.8
dev: true
/mkdirp@1.0.4:
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
engines: {node: '>=10'}
hasBin: true
dev: false
/mp4decryptjs@1.0.1:
resolution: {integrity: sha512-KFkiJGaROybi+ceTPsxTDZWR6umgnL6DjtNviBODUOq3cglHkGlDepbD2dSRp9a5R43ePmKSOH6VzvGz/1SfXA==}
requiresBuild: true
dependencies:
bindings: 1.5.0
cmake-js: 7.3.0
node-addon-api: 6.1.0
transitivePeerDependencies:
- supports-color
dev: false
/mpd-parser@1.3.0:
resolution: {integrity: sha512-WgeIwxAqkmb9uTn4ClicXpEQYCEduDqRKfmUdp4X8vmghKfBNXZLYpREn9eqrDx/Tf5LhzRcJLSpi4ohfV742Q==}
hasBin: true
@ -4579,6 +4747,14 @@ packages:
semver: 7.5.4
dev: false
/node-addon-api@6.1.0:
resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==}
dev: false
/node-api-headers@1.1.0:
resolution: {integrity: sha512-ucQW+SbYCUPfprvmzBsnjT034IGRB2XK8rRc78BgjNKhTdFKgAwAmgW704bKIBmcYW48it0Gkjpkd39Azrwquw==}
dev: false
/node-domexception@1.0.0:
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
engines: {node: '>=10.5.0'}
@ -4617,6 +4793,16 @@ packages:
engines: {node: '>=10'}
dev: false
/npmlog@6.0.2:
resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
dependencies:
are-we-there-yet: 3.0.1
console-control-strings: 1.1.0
gauge: 4.0.4
set-blocking: 2.0.0
dev: false
/nth-check@2.1.1:
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
dependencies:
@ -4886,6 +5072,10 @@ packages:
ipaddr.js: 1.9.1
dev: false
/proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
dev: false
/pump@3.0.0:
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
dependencies:
@ -5155,6 +5345,10 @@ packages:
- supports-color
dev: false
/set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
dev: false
/setimmediate@1.0.5:
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
dev: true
@ -5180,6 +5374,10 @@ packages:
get-intrinsic: 1.2.0
object-inspect: 1.12.3
/signal-exit@3.0.7:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
dev: false
/simple-concat@1.0.1:
resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
dev: false
@ -5339,6 +5537,18 @@ packages:
readable-stream: 3.6.2
dev: false
/tar@6.2.1:
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
engines: {node: '>=10'}
dependencies:
chownr: 2.0.0
fs-minipass: 2.1.0
minipass: 5.0.0
minizlib: 2.1.2
mkdirp: 1.0.4
yallist: 4.0.0
dev: false
/text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
@ -5580,6 +5790,10 @@ packages:
dependencies:
punycode: 2.3.0
/url-join@4.0.1:
resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==}
dev: false
/url-toolkit@2.2.5:
resolution: {integrity: sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==}
dev: false
@ -5670,6 +5884,12 @@ packages:
dependencies:
isexe: 2.0.0
/wide-align@1.1.5:
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
dependencies:
string-width: 4.2.3
dev: false
/wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}