Initial commit for WV Decryption
This commit is contained in:
parent
d1d9840629
commit
28518bb461
12 changed files with 6439 additions and 34 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
ffmpeg: "ffmpeg.exe"
|
ffmpeg: "ffmpeg.exe"
|
||||||
mkvmerge: "mkvmerge.exe"
|
mkvmerge: "mkvmerge.exe"
|
||||||
ffprobe: "ffprobe.exe"
|
ffprobe: "ffprobe.exe"
|
||||||
|
mp4decrypt: "mp4decrypt.exe"
|
||||||
|
|
|
||||||
114
crunchy.ts
114
crunchy.ts
|
|
@ -4,11 +4,13 @@ import fs from 'fs-extra';
|
||||||
|
|
||||||
// package program
|
// package program
|
||||||
import packageJson from './package.json';
|
import packageJson from './package.json';
|
||||||
|
|
||||||
// plugins
|
// plugins
|
||||||
import { console } from './modules/log';
|
import { console } from './modules/log';
|
||||||
import shlp from 'sei-helper';
|
import shlp from 'sei-helper';
|
||||||
import m3u8 from 'm3u8-parsed';
|
import m3u8 from 'm3u8-parsed';
|
||||||
import streamdl, { M3U8Json } from './modules/hls-download';
|
import streamdl, { M3U8Json } from './modules/hls-download';
|
||||||
|
import { exec } from './modules/sei-helper-fixes';
|
||||||
|
|
||||||
// custom modules
|
// custom modules
|
||||||
import * as fontsData from './modules/module.fontsData';
|
import * as fontsData from './modules/module.fontsData';
|
||||||
|
|
@ -16,6 +18,7 @@ import * as langsData from './modules/module.langsData';
|
||||||
import * as yamlCfg from './modules/module.cfg-loader';
|
import * as yamlCfg from './modules/module.cfg-loader';
|
||||||
import * as yargs from './modules/module.app-args';
|
import * as yargs from './modules/module.app-args';
|
||||||
import Merger, { Font, MergerInput, SubtitleInput } from './modules/module.merger';
|
import Merger, { Font, MergerInput, SubtitleInput } from './modules/module.merger';
|
||||||
|
import getKeys from './modules/cr_widevine';
|
||||||
|
|
||||||
// args
|
// args
|
||||||
|
|
||||||
|
|
@ -1388,12 +1391,12 @@ export default class Crunchy implements ServiceClass {
|
||||||
console.error(`DL Stats: ${JSON.stringify(videoDownload.parts)}\n`);
|
console.error(`DL Stats: ${JSON.stringify(videoDownload.parts)}\n`);
|
||||||
dlFailed = true;
|
dlFailed = true;
|
||||||
}
|
}
|
||||||
files.push({
|
/*files.push({
|
||||||
type: 'Video',
|
type: 'Video',
|
||||||
path: `${tsFile}.video.ts`,
|
path: `${tsFile}.video.ts`,
|
||||||
lang: lang,
|
lang: lang,
|
||||||
isPrimary: isPrimary
|
isPrimary: isPrimary
|
||||||
});
|
});*/
|
||||||
dlVideoOnce = true;
|
dlVideoOnce = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1435,6 +1438,104 @@ export default class Crunchy implements ServiceClass {
|
||||||
console.error(`DL Stats: ${JSON.stringify(audioDownload.parts)}\n`);
|
console.error(`DL Stats: ${JSON.stringify(audioDownload.parts)}\n`);
|
||||||
dlFailed = true;
|
dlFailed = true;
|
||||||
}
|
}
|
||||||
|
/*files.push({
|
||||||
|
type: 'Audio',
|
||||||
|
path: `${tsFile}.audio.ts`,
|
||||||
|
lang: lang,
|
||||||
|
isPrimary: isPrimary
|
||||||
|
});*/
|
||||||
|
}
|
||||||
|
|
||||||
|
//Handle Decryption if needed
|
||||||
|
if (chosenVideoSegments.pssh || chosenAudioSegments.pssh) {
|
||||||
|
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);
|
||||||
|
console.info('Decryption Needed, attempting to decrypt');
|
||||||
|
|
||||||
|
const decReq = await this.req.getData('https://pl.crunchyroll.com/drm/v1/auth', {
|
||||||
|
'method': 'POST',
|
||||||
|
'body': JSON.stringify({
|
||||||
|
'accounting_id': 'crunchyroll',
|
||||||
|
'asset_id': assetId,
|
||||||
|
'session_id': sessionId,
|
||||||
|
'user_id': this.token.account_id
|
||||||
|
})
|
||||||
|
});
|
||||||
|
console.info({
|
||||||
|
'body': JSON.stringify({
|
||||||
|
'accounting_id': 'crunchyroll',
|
||||||
|
'asset_id': assetId,
|
||||||
|
'session_id': sessionId,
|
||||||
|
'user_id': this.token.account_id
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if(!decReq.ok || !decReq.res){
|
||||||
|
console.error('Request to DRM Authentication failed:', decReq.error?.code, decReq.error?.message);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const authData = JSON.parse(decReq.res.body) as {'custom_data': string, 'token': string};
|
||||||
|
console.info(authData);
|
||||||
|
const encryptionKeys = await getKeys(chosenVideoSegments.pssh, 'https://lic.drmtoday.com/license-proxy-widevine/cenc/', {
|
||||||
|
'dt-custom-data': authData.custom_data,
|
||||||
|
'x-dt-auth-token': authData.token
|
||||||
|
});
|
||||||
|
if (encryptionKeys.length == 0) {
|
||||||
|
console.error('Failed to get encryption keys');
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
/*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.ts" "${tsFile}.dec.video.ts"`;
|
||||||
|
const commandAudio = commandBase+`"${tsFile}.audio.ts" "${tsFile}.dec.audio.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');
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
console.info('Decryption done for video');
|
||||||
|
}
|
||||||
|
|
||||||
|
files.push({
|
||||||
|
type: 'Video',
|
||||||
|
path: `${tsFile}.dec.video.ts`,
|
||||||
|
lang: lang,
|
||||||
|
isPrimary: isPrimary
|
||||||
|
});
|
||||||
|
files.push({
|
||||||
|
type: 'Audio',
|
||||||
|
path: `${tsFile}.dec.audio.ts`,
|
||||||
|
lang: lang,
|
||||||
|
isPrimary: isPrimary
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.warn('mp4decrypt not found, files need decryption. Decryption Keys:', encryptionKeys);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
files.push({
|
||||||
|
type: 'Video',
|
||||||
|
path: `${tsFile}.video.ts`,
|
||||||
|
lang: lang,
|
||||||
|
isPrimary: isPrimary
|
||||||
|
});
|
||||||
files.push({
|
files.push({
|
||||||
type: 'Audio',
|
type: 'Audio',
|
||||||
path: `${tsFile}.audio.ts`,
|
path: `${tsFile}.audio.ts`,
|
||||||
|
|
@ -1442,15 +1543,6 @@ export default class Crunchy implements ServiceClass {
|
||||||
isPrimary: isPrimary
|
isPrimary: isPrimary
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Handle Decryption if needed
|
|
||||||
if (chosenVideoSegments.pssh) {
|
|
||||||
console.info('Decryption of Video Needed');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosenAudioSegments.pssh) {
|
|
||||||
console.info('Decryption of Audio Needed');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const streamPlaylists = m3u8(streamPlaylistsReq.res.body);
|
const streamPlaylists = m3u8(streamPlaylistsReq.res.body);
|
||||||
const plServerList: string[] = [],
|
const plServerList: string[] = [],
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ This application is not endorsed by or affiliated with *Funimation*, *Crunchyrol
|
||||||
* PNPM >= 7.0.0 (https://pnpm.io/)
|
* PNPM >= 7.0.0 (https://pnpm.io/)
|
||||||
* ffmpeg >= 4.0.0 (https://www.videohelp.com/software/ffmpeg)
|
* ffmpeg >= 4.0.0 (https://www.videohelp.com/software/ffmpeg)
|
||||||
* MKVToolNix >= 60.0.0 (https://www.videohelp.com/software/MKVToolNix)
|
* MKVToolNix >= 60.0.0 (https://www.videohelp.com/software/MKVToolNix)
|
||||||
|
* mp4decrypt >= Any (http://www.bento4.com/) - Only required for decrypting
|
||||||
|
|
||||||
### Paths Configuration
|
### Paths Configuration
|
||||||
|
|
||||||
|
|
@ -23,6 +24,7 @@ By default this application uses the following paths to programs (main executabl
|
||||||
* `ffmpeg.exe` (From PATH)
|
* `ffmpeg.exe` (From PATH)
|
||||||
* `ffprobe.exe` (From PATH)
|
* `ffprobe.exe` (From PATH)
|
||||||
* `mkvmerge.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.
|
To change these paths you need to edit `bin-path.yml` in `./config/` directory.
|
||||||
|
|
||||||
|
|
|
||||||
114
modules/cmac.ts
Normal file
114
modules/cmac.ts
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
//Originally from https://github.com/Frooastside/node-widevine/blob/main/src/cmac.ts
|
||||||
|
|
||||||
|
import crypto from 'crypto';
|
||||||
|
|
||||||
|
export class AES_CMAC {
|
||||||
|
private readonly BLOCK_SIZE = 16;
|
||||||
|
private readonly XOR_RIGHT = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87]);
|
||||||
|
private readonly EMPTY_BLOCK_SIZE_BUFFER = Buffer.alloc(this.BLOCK_SIZE);
|
||||||
|
|
||||||
|
private _key: Buffer;
|
||||||
|
private _subkeys: { first: Buffer; second: Buffer };
|
||||||
|
|
||||||
|
public constructor(key: Buffer) {
|
||||||
|
if (![16, 24, 32].includes(key.length)) {
|
||||||
|
throw new Error('Key size must be 128, 192, or 256 bits.');
|
||||||
|
}
|
||||||
|
this._key = key;
|
||||||
|
this._subkeys = this._generateSubkeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
public calculate(message: Buffer): Buffer {
|
||||||
|
const blockCount = this._getBlockCount(message);
|
||||||
|
|
||||||
|
let x = this.EMPTY_BLOCK_SIZE_BUFFER;
|
||||||
|
let y;
|
||||||
|
|
||||||
|
for (let i = 0; i < blockCount - 1; i++) {
|
||||||
|
const from = i * this.BLOCK_SIZE;
|
||||||
|
const block = message.subarray(from, from + this.BLOCK_SIZE);
|
||||||
|
y = this._xor(x, block);
|
||||||
|
x = this._aes(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
y = this._xor(x, this._getLastBlock(message));
|
||||||
|
x = this._aes(y);
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _generateSubkeys(): { first: Buffer; second: Buffer } {
|
||||||
|
const l = this._aes(this.EMPTY_BLOCK_SIZE_BUFFER);
|
||||||
|
|
||||||
|
let first = this._bitShiftLeft(l);
|
||||||
|
if (l[0] & 0x80) {
|
||||||
|
first = this._xor(first, this.XOR_RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
let second = this._bitShiftLeft(first);
|
||||||
|
if (first[0] & 0x80) {
|
||||||
|
second = this._xor(second, this.XOR_RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { first: first, second: second };
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getBlockCount(message: Buffer): number {
|
||||||
|
const blockCount = Math.ceil(message.length / this.BLOCK_SIZE);
|
||||||
|
return blockCount === 0 ? 1 : blockCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _aes(message: Buffer): Buffer {
|
||||||
|
const cipher = crypto.createCipheriv(`aes-${this._key.length * 8}-cbc`, this._key, Buffer.alloc(this.BLOCK_SIZE));
|
||||||
|
const result = cipher.update(message).subarray(0, 16);
|
||||||
|
cipher.destroy();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getLastBlock(message: Buffer): Buffer {
|
||||||
|
const blockCount = this._getBlockCount(message);
|
||||||
|
const paddedBlock = this._padding(message, blockCount - 1);
|
||||||
|
|
||||||
|
let complete = false;
|
||||||
|
if (message.length > 0) {
|
||||||
|
complete = message.length % this.BLOCK_SIZE === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = complete ? this._subkeys.first : this._subkeys.second;
|
||||||
|
return this._xor(paddedBlock, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _padding(message: Buffer, blockIndex: number): Buffer {
|
||||||
|
const block = Buffer.alloc(this.BLOCK_SIZE);
|
||||||
|
|
||||||
|
const from = blockIndex * this.BLOCK_SIZE;
|
||||||
|
|
||||||
|
const slice = message.subarray(from, from + this.BLOCK_SIZE);
|
||||||
|
block.set(slice);
|
||||||
|
|
||||||
|
if (slice.length !== this.BLOCK_SIZE) {
|
||||||
|
block[slice.length] = 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _bitShiftLeft(input: Buffer): Buffer {
|
||||||
|
const output = Buffer.alloc(input.length);
|
||||||
|
let overflow = 0;
|
||||||
|
for (let i = input.length - 1; i >= 0; i--) {
|
||||||
|
output[i] = (input[i] << 1) | overflow;
|
||||||
|
overflow = input[i] & 0x80 ? 1 : 0;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _xor(a: Buffer, b: Buffer): Buffer {
|
||||||
|
const length = Math.min(a.length, b.length);
|
||||||
|
const output = Buffer.alloc(length);
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
output[i] = a[i] ^ b[i];
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
modules/cr_widevine.ts
Normal file
36
modules/cr_widevine.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { KeyContainer, Session } from './license';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { console } from './log';
|
||||||
|
|
||||||
|
//read cdm files located in the same directory
|
||||||
|
const privateKey = fs.readFileSync('./widevine/device_private_key');
|
||||||
|
const identifierBlob = fs.readFileSync('./widevine/device_client_id_blob');
|
||||||
|
|
||||||
|
export default async function getKeys(pssh: string | undefined, licenseServer: string, authData: Record<string, string>): Promise<KeyContainer[]> {
|
||||||
|
if (!pssh) return [];
|
||||||
|
//pssh found in the mpd manifest
|
||||||
|
const psshBuffer = Buffer.from(
|
||||||
|
pssh,
|
||||||
|
'base64'
|
||||||
|
);
|
||||||
|
|
||||||
|
//Create a new widevine session
|
||||||
|
const session = new Session({ privateKey, identifierBlob }, psshBuffer);
|
||||||
|
|
||||||
|
//Generate license
|
||||||
|
const response = await fetch(licenseServer, {
|
||||||
|
method: 'POST',
|
||||||
|
body: session.createLicenseRequest(),
|
||||||
|
headers: authData
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
//Parse License and return keys
|
||||||
|
const json = await response.json();
|
||||||
|
const keys = session.parseLicense(Buffer.from(json['license'], 'base64'));
|
||||||
|
return keys;
|
||||||
|
} else {
|
||||||
|
console.info('License request failed:', response.statusText);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
161
modules/license.ts
Normal file
161
modules/license.ts
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
//Originaly from https://github.com/Frooastside/node-widevine/blob/main/src/license.ts
|
||||||
|
|
||||||
|
import crypto from 'crypto';
|
||||||
|
import Long from 'long';
|
||||||
|
import { AES_CMAC } from './cmac';
|
||||||
|
import {
|
||||||
|
ClientIdentification,
|
||||||
|
License,
|
||||||
|
LicenseRequest,
|
||||||
|
LicenseRequest_RequestType,
|
||||||
|
LicenseType,
|
||||||
|
ProtocolVersion,
|
||||||
|
SignedMessage,
|
||||||
|
SignedMessage_MessageType,
|
||||||
|
SignedMessage_SessionKeyType,
|
||||||
|
WidevinePsshData
|
||||||
|
} from './license_protocol';
|
||||||
|
|
||||||
|
const WIDEVINE_SYSTEM_ID = new Uint8Array([237, 239, 139, 169, 121, 214, 74, 206, 163, 200, 39, 220, 213, 29, 33, 237]);
|
||||||
|
|
||||||
|
export type KeyContainer = {
|
||||||
|
kid: string;
|
||||||
|
key: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ContentDecryptionModule = {
|
||||||
|
privateKey: Buffer;
|
||||||
|
identifierBlob: Buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class Session {
|
||||||
|
private _devicePrivateKey: crypto.KeyObject;
|
||||||
|
private _identifierBlob: ClientIdentification;
|
||||||
|
private _identifier: Buffer;
|
||||||
|
private _pssh: Buffer;
|
||||||
|
private _rawLicenseRequest?: Buffer;
|
||||||
|
|
||||||
|
constructor(contentDecryptionModule: ContentDecryptionModule, pssh: Buffer) {
|
||||||
|
this._devicePrivateKey = crypto.createPrivateKey(contentDecryptionModule.privateKey);
|
||||||
|
this._identifierBlob = ClientIdentification.decode(contentDecryptionModule.identifierBlob);
|
||||||
|
this._identifier = this._generateIdentifier();
|
||||||
|
this._pssh = pssh;
|
||||||
|
}
|
||||||
|
|
||||||
|
createLicenseRequest(): Buffer {
|
||||||
|
if (!this._pssh.subarray(12, 28).equals(Buffer.from(WIDEVINE_SYSTEM_ID))) {
|
||||||
|
throw new Error('the pssh is not an actuall pssh');
|
||||||
|
}
|
||||||
|
const pssh = this._parsePSSH(this._pssh);
|
||||||
|
if (!pssh) {
|
||||||
|
throw new Error('pssh is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
const licenseRequest: LicenseRequest = {
|
||||||
|
type: LicenseRequest_RequestType.NEW,
|
||||||
|
clientId: this._identifierBlob,
|
||||||
|
contentId: {
|
||||||
|
widevinePsshData: {
|
||||||
|
psshData: [this._pssh.subarray(32)],
|
||||||
|
licenseType: LicenseType.STREAMING,
|
||||||
|
requestId: this._identifier
|
||||||
|
}
|
||||||
|
},
|
||||||
|
requestTime: Long.fromNumber(Date.now()).divide(1000),
|
||||||
|
protocolVersion: ProtocolVersion.VERSION_2_1,
|
||||||
|
keyControlNonce: crypto.randomInt(2 ** 31),
|
||||||
|
keyControlNonceDeprecated: Buffer.alloc(0),
|
||||||
|
encryptedClientId: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
this._rawLicenseRequest = Buffer.from(LicenseRequest.encode(licenseRequest).finish());
|
||||||
|
|
||||||
|
const signature = crypto
|
||||||
|
.createSign('sha1')
|
||||||
|
.update(this._rawLicenseRequest)
|
||||||
|
.sign({ key: this._devicePrivateKey, padding: crypto.constants.RSA_PKCS1_PSS_PADDING, saltLength: 20 });
|
||||||
|
|
||||||
|
const signedLicenseRequest: SignedMessage = {
|
||||||
|
type: SignedMessage_MessageType.LICENSE_REQUEST,
|
||||||
|
msg: this._rawLicenseRequest,
|
||||||
|
signature: Buffer.from(signature),
|
||||||
|
sessionKey: Buffer.alloc(0),
|
||||||
|
remoteAttestation: Buffer.alloc(0),
|
||||||
|
metricData: [],
|
||||||
|
serviceVersionInfo: undefined,
|
||||||
|
sessionKeyType: SignedMessage_SessionKeyType.UNDEFINED,
|
||||||
|
oemcryptoCoreMessage: Buffer.alloc(0)
|
||||||
|
};
|
||||||
|
|
||||||
|
return Buffer.from(SignedMessage.encode(signedLicenseRequest).finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
parseLicense(rawLicense: Buffer) {
|
||||||
|
if (!this._rawLicenseRequest) {
|
||||||
|
throw new Error('please request a license first');
|
||||||
|
}
|
||||||
|
const signedLicense = SignedMessage.decode(rawLicense);
|
||||||
|
const sessionKey = crypto.privateDecrypt(this._devicePrivateKey, signedLicense.sessionKey);
|
||||||
|
|
||||||
|
const cmac = new AES_CMAC(Buffer.from(sessionKey));
|
||||||
|
|
||||||
|
const encKeyBase = Buffer.concat([
|
||||||
|
Buffer.from('ENCRYPTION'),
|
||||||
|
Buffer.from('\x00', 'ascii'),
|
||||||
|
this._rawLicenseRequest,
|
||||||
|
Buffer.from('\x00\x00\x00\x80', 'ascii')
|
||||||
|
]);
|
||||||
|
const authKeyBase = Buffer.concat([
|
||||||
|
Buffer.from('AUTHENTICATION'),
|
||||||
|
Buffer.from('\x00', 'ascii'),
|
||||||
|
this._rawLicenseRequest,
|
||||||
|
Buffer.from('\x00\x00\x02\x00', 'ascii')
|
||||||
|
]);
|
||||||
|
|
||||||
|
const encKey = cmac.calculate(Buffer.concat([Buffer.from('\x01'), encKeyBase]));
|
||||||
|
const serverKey = Buffer.concat([
|
||||||
|
cmac.calculate(Buffer.concat([Buffer.from('\x01'), authKeyBase])),
|
||||||
|
cmac.calculate(Buffer.concat([Buffer.from('\x02'), authKeyBase]))
|
||||||
|
]);
|
||||||
|
/*const clientKey = Buffer.concat([
|
||||||
|
cmac.calculate(Buffer.concat([Buffer.from("\x03"), authKeyBase])),
|
||||||
|
cmac.calculate(Buffer.concat([Buffer.from("\x04"), authKeyBase]))
|
||||||
|
]);*/
|
||||||
|
|
||||||
|
const calculatedSignature = crypto.createHmac('sha256', serverKey).update(signedLicense.msg).digest();
|
||||||
|
|
||||||
|
if (!calculatedSignature.equals(signedLicense.signature)) {
|
||||||
|
throw new Error('signatures do not match');
|
||||||
|
}
|
||||||
|
|
||||||
|
const license = License.decode(signedLicense.msg);
|
||||||
|
|
||||||
|
return license.key.map((keyContainer) => {
|
||||||
|
const keyId = keyContainer.id.length ? keyContainer.id.toString('hex') : keyContainer.type.toString();
|
||||||
|
const decipher = crypto.createDecipheriv(`aes-${encKey.length * 8}-cbc`, encKey, keyContainer.iv);
|
||||||
|
const decryptedKey = decipher.update(keyContainer.key);
|
||||||
|
decipher.destroy();
|
||||||
|
const key: KeyContainer = {
|
||||||
|
kid: keyId,
|
||||||
|
key: decryptedKey.toString('hex')
|
||||||
|
};
|
||||||
|
return key;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _parsePSSH(pssh: Buffer): WidevinePsshData | null {
|
||||||
|
try {
|
||||||
|
return WidevinePsshData.decode(pssh.subarray(32));
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _generateIdentifier(): Buffer {
|
||||||
|
return Buffer.from(`${crypto.randomBytes(8).toString('hex')}${'01'}${'00000000000000'}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
get pssh(): Buffer {
|
||||||
|
return this._pssh;
|
||||||
|
}
|
||||||
|
}
|
||||||
749
modules/license_protocol.proto
Normal file
749
modules/license_protocol.proto
Normal file
|
|
@ -0,0 +1,749 @@
|
||||||
|
//Originally from https://github.com/Frooastside/node-widevine/blob/main/src/license_protocol.proto
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
package license_protocol;
|
||||||
|
|
||||||
|
enum LicenseType {
|
||||||
|
STREAMING = 1;
|
||||||
|
OFFLINE = 2;
|
||||||
|
// License type decision is left to provider.
|
||||||
|
AUTOMATIC = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PlatformVerificationStatus {
|
||||||
|
// The platform is not verified.
|
||||||
|
PLATFORM_UNVERIFIED = 0;
|
||||||
|
// Tampering detected on the platform.
|
||||||
|
PLATFORM_TAMPERED = 1;
|
||||||
|
// The platform has been verified by means of software.
|
||||||
|
PLATFORM_SOFTWARE_VERIFIED = 2;
|
||||||
|
// The platform has been verified by means of hardware (e.g. secure boot).
|
||||||
|
PLATFORM_HARDWARE_VERIFIED = 3;
|
||||||
|
// Platform verification was not performed.
|
||||||
|
PLATFORM_NO_VERIFICATION = 4;
|
||||||
|
// Platform and secure storage capability have been verified by means of
|
||||||
|
// software.
|
||||||
|
PLATFORM_SECURE_STORAGE_SOFTWARE_VERIFIED = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LicenseIdentification is propagated from LicenseRequest to License,
|
||||||
|
// incrementing version with each iteration.
|
||||||
|
message LicenseIdentification {
|
||||||
|
optional bytes request_id = 1;
|
||||||
|
optional bytes session_id = 2;
|
||||||
|
optional bytes purchase_id = 3;
|
||||||
|
optional LicenseType type = 4;
|
||||||
|
optional int32 version = 5;
|
||||||
|
optional bytes provider_session_token = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message License {
|
||||||
|
message Policy {
|
||||||
|
// Indicates that playback of the content is allowed.
|
||||||
|
optional bool can_play = 1 [default = false];
|
||||||
|
|
||||||
|
// Indicates that the license may be persisted to non-volatile
|
||||||
|
// storage for offline use.
|
||||||
|
optional bool can_persist = 2 [default = false];
|
||||||
|
|
||||||
|
// Indicates that renewal of this license is allowed.
|
||||||
|
optional bool can_renew = 3 [default = false];
|
||||||
|
|
||||||
|
// For the |*duration*| fields, playback must halt when
|
||||||
|
// license_start_time (seconds since the epoch (UTC)) +
|
||||||
|
// license_duration_seconds is exceeded. A value of 0
|
||||||
|
// indicates that there is no limit to the duration.
|
||||||
|
|
||||||
|
// Indicates the rental window.
|
||||||
|
optional int64 rental_duration_seconds = 4 [default = 0];
|
||||||
|
|
||||||
|
// Indicates the viewing window, once playback has begun.
|
||||||
|
optional int64 playback_duration_seconds = 5 [default = 0];
|
||||||
|
|
||||||
|
// Indicates the time window for this specific license.
|
||||||
|
optional int64 license_duration_seconds = 6 [default = 0];
|
||||||
|
|
||||||
|
// The |renewal*| fields only apply if |can_renew| is true.
|
||||||
|
|
||||||
|
// The window of time, in which playback is allowed to continue while
|
||||||
|
// renewal is attempted, yet unsuccessful due to backend problems with
|
||||||
|
// the license server.
|
||||||
|
optional int64 renewal_recovery_duration_seconds = 7 [default = 0];
|
||||||
|
|
||||||
|
// All renewal requests for this license shall be directed to the
|
||||||
|
// specified URL.
|
||||||
|
optional string renewal_server_url = 8;
|
||||||
|
|
||||||
|
// How many seconds after license_start_time, before renewal is first
|
||||||
|
// attempted.
|
||||||
|
optional int64 renewal_delay_seconds = 9 [default = 0];
|
||||||
|
|
||||||
|
// Specifies the delay in seconds between subsequent license
|
||||||
|
// renewal requests, in case of failure.
|
||||||
|
optional int64 renewal_retry_interval_seconds = 10 [default = 0];
|
||||||
|
|
||||||
|
// Indicates that the license shall be sent for renewal when usage is
|
||||||
|
// started.
|
||||||
|
optional bool renew_with_usage = 11 [default = false];
|
||||||
|
|
||||||
|
// Indicates to client that license renewal and release requests ought to
|
||||||
|
// include ClientIdentification (client_id).
|
||||||
|
optional bool always_include_client_id = 12 [default = false];
|
||||||
|
|
||||||
|
// Duration of grace period before playback_duration_seconds (short window)
|
||||||
|
// goes into effect. Optional.
|
||||||
|
optional int64 play_start_grace_period_seconds = 13 [default = 0];
|
||||||
|
|
||||||
|
// Enables "soft enforcement" of playback_duration_seconds, letting the user
|
||||||
|
// finish playback even if short window expires. Optional.
|
||||||
|
optional bool soft_enforce_playback_duration = 14 [default = false];
|
||||||
|
|
||||||
|
// Enables "soft enforcement" of rental_duration_seconds. Initial playback
|
||||||
|
// must always start before rental duration expires. In order to allow
|
||||||
|
// subsequent playbacks to start after the rental duration expires,
|
||||||
|
// soft_enforce_playback_duration must be true. Otherwise, subsequent
|
||||||
|
// playbacks will not be allowed once rental duration expires. Optional.
|
||||||
|
optional bool soft_enforce_rental_duration = 15 [default = true];
|
||||||
|
}
|
||||||
|
|
||||||
|
message KeyContainer {
|
||||||
|
enum KeyType {
|
||||||
|
SIGNING = 1; // Exactly one key of this type must appear.
|
||||||
|
CONTENT = 2; // Content key.
|
||||||
|
KEY_CONTROL = 3; // Key control block for license renewals. No key.
|
||||||
|
OPERATOR_SESSION = 4; // wrapped keys for auxiliary crypto operations.
|
||||||
|
ENTITLEMENT = 5; // Entitlement keys.
|
||||||
|
OEM_CONTENT = 6; // Partner-specific content key.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The SecurityLevel enumeration allows the server to communicate the level
|
||||||
|
// of robustness required by the client, in order to use the key.
|
||||||
|
enum SecurityLevel {
|
||||||
|
// Software-based whitebox crypto is required.
|
||||||
|
SW_SECURE_CRYPTO = 1;
|
||||||
|
|
||||||
|
// Software crypto and an obfuscated decoder is required.
|
||||||
|
SW_SECURE_DECODE = 2;
|
||||||
|
|
||||||
|
// The key material and crypto operations must be performed within a
|
||||||
|
// hardware backed trusted execution environment.
|
||||||
|
HW_SECURE_CRYPTO = 3;
|
||||||
|
|
||||||
|
// The crypto and decoding of content must be performed within a hardware
|
||||||
|
// backed trusted execution environment.
|
||||||
|
HW_SECURE_DECODE = 4;
|
||||||
|
|
||||||
|
// The crypto, decoding and all handling of the media (compressed and
|
||||||
|
// uncompressed) must be handled within a hardware backed trusted
|
||||||
|
// execution environment.
|
||||||
|
HW_SECURE_ALL = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message KeyControl {
|
||||||
|
// |key_control| is documented in:
|
||||||
|
// Widevine Modular DRM Security Integration Guide for CENC
|
||||||
|
// If present, the key control must be communicated to the secure
|
||||||
|
// environment prior to any usage. This message is automatically generated
|
||||||
|
// by the Widevine License Server SDK.
|
||||||
|
optional bytes key_control_block = 1;
|
||||||
|
optional bytes iv = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OutputProtection {
|
||||||
|
// Indicates whether HDCP is required on digital outputs, and which
|
||||||
|
// version should be used.
|
||||||
|
enum HDCP {
|
||||||
|
HDCP_NONE = 0;
|
||||||
|
HDCP_V1 = 1;
|
||||||
|
HDCP_V2 = 2;
|
||||||
|
HDCP_V2_1 = 3;
|
||||||
|
HDCP_V2_2 = 4;
|
||||||
|
HDCP_V2_3 = 5;
|
||||||
|
HDCP_NO_DIGITAL_OUTPUT = 0xff;
|
||||||
|
}
|
||||||
|
optional HDCP hdcp = 1 [default = HDCP_NONE];
|
||||||
|
|
||||||
|
// Indicate the CGMS setting to be inserted on analog output.
|
||||||
|
enum CGMS {
|
||||||
|
CGMS_NONE = 42;
|
||||||
|
COPY_FREE = 0;
|
||||||
|
COPY_ONCE = 2;
|
||||||
|
COPY_NEVER = 3;
|
||||||
|
}
|
||||||
|
optional CGMS cgms_flags = 2 [default = CGMS_NONE];
|
||||||
|
|
||||||
|
enum HdcpSrmRule {
|
||||||
|
HDCP_SRM_RULE_NONE = 0;
|
||||||
|
// In 'required_protection', this means most current SRM is required.
|
||||||
|
// Update the SRM on the device. If update cannot happen,
|
||||||
|
// do not allow the key.
|
||||||
|
// In 'requested_protection', this means most current SRM is requested.
|
||||||
|
// Update the SRM on the device. If update cannot happen,
|
||||||
|
// allow use of the key anyway.
|
||||||
|
CURRENT_SRM = 1;
|
||||||
|
}
|
||||||
|
optional HdcpSrmRule hdcp_srm_rule = 3 [default = HDCP_SRM_RULE_NONE];
|
||||||
|
// Optional requirement to indicate analog output is not allowed.
|
||||||
|
optional bool disable_analog_output = 4 [default = false];
|
||||||
|
// Optional requirement to indicate digital output is not allowed.
|
||||||
|
optional bool disable_digital_output = 5 [default = false];
|
||||||
|
}
|
||||||
|
|
||||||
|
message VideoResolutionConstraint {
|
||||||
|
// Minimum and maximum video resolutions in the range (height x width).
|
||||||
|
optional uint32 min_resolution_pixels = 1;
|
||||||
|
optional uint32 max_resolution_pixels = 2;
|
||||||
|
// Optional output protection requirements for this range. If not
|
||||||
|
// specified, the OutputProtection in the KeyContainer applies.
|
||||||
|
optional OutputProtection required_protection = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OperatorSessionKeyPermissions {
|
||||||
|
// Permissions/key usage flags for operator service keys
|
||||||
|
// (type = OPERATOR_SESSION).
|
||||||
|
optional bool allow_encrypt = 1 [default = false];
|
||||||
|
optional bool allow_decrypt = 2 [default = false];
|
||||||
|
optional bool allow_sign = 3 [default = false];
|
||||||
|
optional bool allow_signature_verify = 4 [default = false];
|
||||||
|
}
|
||||||
|
|
||||||
|
optional bytes id = 1;
|
||||||
|
optional bytes iv = 2;
|
||||||
|
optional bytes key = 3;
|
||||||
|
optional KeyType type = 4;
|
||||||
|
optional SecurityLevel level = 5 [default = SW_SECURE_CRYPTO];
|
||||||
|
optional OutputProtection required_protection = 6;
|
||||||
|
// NOTE: Use of requested_protection is not recommended as it is only
|
||||||
|
// supported on a small number of platforms.
|
||||||
|
optional OutputProtection requested_protection = 7;
|
||||||
|
optional KeyControl key_control = 8;
|
||||||
|
optional OperatorSessionKeyPermissions operator_session_key_permissions = 9;
|
||||||
|
// Optional video resolution constraints. If the video resolution of the
|
||||||
|
// content being decrypted/decoded falls within one of the specified ranges,
|
||||||
|
// the optional required_protections may be applied. Otherwise an error will
|
||||||
|
// be reported.
|
||||||
|
// NOTE: Use of this feature is not recommended, as it is only supported on
|
||||||
|
// a small number of platforms.
|
||||||
|
repeated VideoResolutionConstraint video_resolution_constraints = 10;
|
||||||
|
// Optional flag to indicate the key must only be used if the client
|
||||||
|
// supports anti rollback of the user table. Content provider can query the
|
||||||
|
// client capabilities to determine if the client support this feature.
|
||||||
|
optional bool anti_rollback_usage_table = 11 [default = false];
|
||||||
|
// Optional not limited to commonly known track types such as SD, HD.
|
||||||
|
// It can be some provider defined label to identify the track.
|
||||||
|
optional string track_label = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional LicenseIdentification id = 1;
|
||||||
|
optional Policy policy = 2;
|
||||||
|
repeated KeyContainer key = 3;
|
||||||
|
// Time of the request in seconds (UTC) as set in
|
||||||
|
// LicenseRequest.request_time. If this time is not set in the request,
|
||||||
|
// the local time at the license service is used in this field.
|
||||||
|
optional int64 license_start_time = 4;
|
||||||
|
optional bool remote_attestation_verified = 5 [default = false];
|
||||||
|
// Client token generated by the content provider. Optional.
|
||||||
|
optional bytes provider_client_token = 6;
|
||||||
|
// 4cc code specifying the CENC protection scheme as defined in the CENC 3.0
|
||||||
|
// specification. Propagated from Widevine PSSH box. Optional.
|
||||||
|
optional uint32 protection_scheme = 7;
|
||||||
|
// 8 byte verification field "HDCPDATA" followed by unsigned 32 bit minimum
|
||||||
|
// HDCP SRM version (whether the version is for HDCP1 SRM or HDCP2 SRM
|
||||||
|
// depends on client max_hdcp_version).
|
||||||
|
// Additional details can be found in Widevine Modular DRM Security
|
||||||
|
// Integration Guide for CENC.
|
||||||
|
optional bytes srm_requirement = 8;
|
||||||
|
// If present this contains a signed SRM file (either HDCP1 SRM or HDCP2 SRM
|
||||||
|
// depending on client max_hdcp_version) that should be installed on the
|
||||||
|
// client device.
|
||||||
|
optional bytes srm_update = 9;
|
||||||
|
// Indicates the status of any type of platform verification performed by the
|
||||||
|
// server.
|
||||||
|
optional PlatformVerificationStatus platform_verification_status = 10
|
||||||
|
[default = PLATFORM_NO_VERIFICATION];
|
||||||
|
// IDs of the groups for which keys are delivered in this license, if any.
|
||||||
|
repeated bytes group_ids = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ProtocolVersion {
|
||||||
|
VERSION_2_0 = 20;
|
||||||
|
VERSION_2_1 = 21;
|
||||||
|
VERSION_2_2 = 22;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LicenseRequest {
|
||||||
|
message ContentIdentification {
|
||||||
|
message WidevinePsshData {
|
||||||
|
repeated bytes pssh_data = 1;
|
||||||
|
optional LicenseType license_type = 2;
|
||||||
|
optional bytes request_id = 3; // Opaque, client-specified.
|
||||||
|
}
|
||||||
|
|
||||||
|
message WebmKeyId {
|
||||||
|
optional bytes header = 1;
|
||||||
|
optional LicenseType license_type = 2;
|
||||||
|
optional bytes request_id = 3; // Opaque, client-specified.
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExistingLicense {
|
||||||
|
optional LicenseIdentification license_id = 1;
|
||||||
|
optional int64 seconds_since_started = 2;
|
||||||
|
optional int64 seconds_since_last_played = 3;
|
||||||
|
optional bytes session_usage_table_entry = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InitData {
|
||||||
|
enum InitDataType {
|
||||||
|
CENC = 1;
|
||||||
|
WEBM = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional InitDataType init_data_type = 1 [default = CENC];
|
||||||
|
optional bytes init_data = 2;
|
||||||
|
optional LicenseType license_type = 3;
|
||||||
|
optional bytes request_id = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
oneof content_id_variant {
|
||||||
|
// Exactly one of these must be present.
|
||||||
|
WidevinePsshData widevine_pssh_data = 1;
|
||||||
|
WebmKeyId webm_key_id = 2;
|
||||||
|
ExistingLicense existing_license = 3;
|
||||||
|
InitData init_data = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RequestType {
|
||||||
|
NEW = 1;
|
||||||
|
RENEWAL = 2;
|
||||||
|
RELEASE = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The client_id provides information authenticating the calling device. It
|
||||||
|
// contains the Widevine keybox token that was installed on the device at the
|
||||||
|
// factory. This field or encrypted_client_id below is required for a valid
|
||||||
|
// license request, but both should never be present in the same request.
|
||||||
|
optional ClientIdentification client_id = 1;
|
||||||
|
optional ContentIdentification content_id = 2;
|
||||||
|
optional RequestType type = 3;
|
||||||
|
// Time of the request in seconds (UTC) as set by the client.
|
||||||
|
optional int64 request_time = 4;
|
||||||
|
// Old-style decimal-encoded string key control nonce.
|
||||||
|
optional bytes key_control_nonce_deprecated = 5;
|
||||||
|
optional ProtocolVersion protocol_version = 6 [default = VERSION_2_0];
|
||||||
|
// New-style uint32 key control nonce, please use instead of
|
||||||
|
// key_control_nonce_deprecated.
|
||||||
|
optional uint32 key_control_nonce = 7;
|
||||||
|
// Encrypted ClientIdentification message, used for privacy purposes.
|
||||||
|
optional EncryptedClientIdentification encrypted_client_id = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MetricData {
|
||||||
|
enum MetricType {
|
||||||
|
// The time spent in the 'stage', specified in microseconds.
|
||||||
|
LATENCY = 1;
|
||||||
|
// The UNIX epoch timestamp at which the 'stage' was first accessed in
|
||||||
|
// microseconds.
|
||||||
|
TIMESTAMP = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TypeValue {
|
||||||
|
optional MetricType type = 1;
|
||||||
|
// The value associated with 'type'. For example if type == LATENCY, the
|
||||||
|
// value would be the time in microseconds spent in this 'stage'.
|
||||||
|
optional int64 value = 2 [default = 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'stage' that is currently processing the SignedMessage. Required.
|
||||||
|
optional string stage_name = 1;
|
||||||
|
// metric and associated value.
|
||||||
|
repeated TypeValue metric_data = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VersionInfo {
|
||||||
|
// License SDK version reported by the Widevine License SDK. This field
|
||||||
|
// is populated automatically by the SDK.
|
||||||
|
optional string license_sdk_version = 1;
|
||||||
|
// Version of the service hosting the license SDK. This field is optional.
|
||||||
|
// It may be provided by the hosting service.
|
||||||
|
optional string license_service_version = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SignedMessage {
|
||||||
|
enum MessageType {
|
||||||
|
LICENSE_REQUEST = 1;
|
||||||
|
LICENSE = 2;
|
||||||
|
ERROR_RESPONSE = 3;
|
||||||
|
SERVICE_CERTIFICATE_REQUEST = 4;
|
||||||
|
SERVICE_CERTIFICATE = 5;
|
||||||
|
SUB_LICENSE = 6;
|
||||||
|
CAS_LICENSE_REQUEST = 7;
|
||||||
|
CAS_LICENSE = 8;
|
||||||
|
EXTERNAL_LICENSE_REQUEST = 9;
|
||||||
|
EXTERNAL_LICENSE = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SessionKeyType {
|
||||||
|
UNDEFINED = 0;
|
||||||
|
WRAPPED_AES_KEY = 1;
|
||||||
|
EPHERMERAL_ECC_PUBLIC_KEY = 2;
|
||||||
|
}
|
||||||
|
optional MessageType type = 1;
|
||||||
|
optional bytes msg = 2;
|
||||||
|
// Required field that contains the signature of the bytes of msg.
|
||||||
|
// For license requests, the signing algorithm is determined by the
|
||||||
|
// certificate contained in the request.
|
||||||
|
// For license responses, the signing algorithm is HMAC with signing key based
|
||||||
|
// on |session_key|.
|
||||||
|
optional bytes signature = 3;
|
||||||
|
// If populated, the contents of this field will be signaled by the
|
||||||
|
// |session_key_type| type. If the |session_key_type| is WRAPPED_AES_KEY the
|
||||||
|
// key is the bytes of an encrypted AES key. If the |session_key_type| is
|
||||||
|
// EPHERMERAL_ECC_PUBLIC_KEY the field contains the bytes of an RFC5208 ASN1
|
||||||
|
// serialized ECC public key.
|
||||||
|
optional bytes session_key = 4;
|
||||||
|
// Remote attestation data which will be present in the initial license
|
||||||
|
// request for ChromeOS client devices operating in verified mode. Remote
|
||||||
|
// attestation challenge data is |msg| field above. Optional.
|
||||||
|
optional bytes remote_attestation = 5;
|
||||||
|
|
||||||
|
repeated MetricData metric_data = 6;
|
||||||
|
// Version information from the SDK and license service. This information is
|
||||||
|
// provided in the license response.
|
||||||
|
optional VersionInfo service_version_info = 7;
|
||||||
|
// Optional field that contains the algorithm type used to generate the
|
||||||
|
// session_key and signature in a LICENSE message.
|
||||||
|
optional SessionKeyType session_key_type = 8 [default = WRAPPED_AES_KEY];
|
||||||
|
// The core message is the simple serialization of fields used by OEMCrypto.
|
||||||
|
// This field was introduced in OEMCrypto API v16.
|
||||||
|
optional bytes oemcrypto_core_message = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum HashAlgorithmProto {
|
||||||
|
// Unspecified hash algorithm: SHA_256 shall be used for ECC based algorithms
|
||||||
|
// and SHA_1 shall be used otherwise.
|
||||||
|
HASH_ALGORITHM_UNSPECIFIED = 0;
|
||||||
|
HASH_ALGORITHM_SHA_1 = 1;
|
||||||
|
HASH_ALGORITHM_SHA_256 = 2;
|
||||||
|
HASH_ALGORITHM_SHA_384 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientIdentification message used to authenticate the client device.
|
||||||
|
message ClientIdentification {
|
||||||
|
enum TokenType {
|
||||||
|
KEYBOX = 0;
|
||||||
|
DRM_DEVICE_CERTIFICATE = 1;
|
||||||
|
REMOTE_ATTESTATION_CERTIFICATE = 2;
|
||||||
|
OEM_DEVICE_CERTIFICATE = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NameValue {
|
||||||
|
optional string name = 1;
|
||||||
|
optional string value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capabilities which not all clients may support. Used for the license
|
||||||
|
// exchange protocol only.
|
||||||
|
message ClientCapabilities {
|
||||||
|
enum HdcpVersion {
|
||||||
|
HDCP_NONE = 0;
|
||||||
|
HDCP_V1 = 1;
|
||||||
|
HDCP_V2 = 2;
|
||||||
|
HDCP_V2_1 = 3;
|
||||||
|
HDCP_V2_2 = 4;
|
||||||
|
HDCP_V2_3 = 5;
|
||||||
|
HDCP_NO_DIGITAL_OUTPUT = 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CertificateKeyType {
|
||||||
|
RSA_2048 = 0;
|
||||||
|
RSA_3072 = 1;
|
||||||
|
ECC_SECP256R1 = 2;
|
||||||
|
ECC_SECP384R1 = 3;
|
||||||
|
ECC_SECP521R1 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AnalogOutputCapabilities {
|
||||||
|
ANALOG_OUTPUT_UNKNOWN = 0;
|
||||||
|
ANALOG_OUTPUT_NONE = 1;
|
||||||
|
ANALOG_OUTPUT_SUPPORTED = 2;
|
||||||
|
ANALOG_OUTPUT_SUPPORTS_CGMS_A = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional bool client_token = 1 [default = false];
|
||||||
|
optional bool session_token = 2 [default = false];
|
||||||
|
optional bool video_resolution_constraints = 3 [default = false];
|
||||||
|
optional HdcpVersion max_hdcp_version = 4 [default = HDCP_NONE];
|
||||||
|
optional uint32 oem_crypto_api_version = 5;
|
||||||
|
// Client has hardware support for protecting the usage table, such as
|
||||||
|
// storing the generation number in secure memory. For Details, see:
|
||||||
|
// Widevine Modular DRM Security Integration Guide for CENC
|
||||||
|
optional bool anti_rollback_usage_table = 6 [default = false];
|
||||||
|
// The client shall report |srm_version| if available.
|
||||||
|
optional uint32 srm_version = 7;
|
||||||
|
// A device may have SRM data, and report a version, but may not be capable
|
||||||
|
// of updating SRM data.
|
||||||
|
optional bool can_update_srm = 8 [default = false];
|
||||||
|
repeated CertificateKeyType supported_certificate_key_type = 9;
|
||||||
|
optional AnalogOutputCapabilities analog_output_capabilities = 10
|
||||||
|
[default = ANALOG_OUTPUT_UNKNOWN];
|
||||||
|
optional bool can_disable_analog_output = 11 [default = false];
|
||||||
|
// Clients can indicate a performance level supported by OEMCrypto.
|
||||||
|
// This will allow applications and providers to choose an appropriate
|
||||||
|
// quality of content to serve. Currently defined tiers are
|
||||||
|
// 1 (low), 2 (medium) and 3 (high). Any other value indicates that
|
||||||
|
// the resource rating is unavailable or reporting erroneous values
|
||||||
|
// for that device. For details see,
|
||||||
|
// Widevine Modular DRM Security Integration Guide for CENC
|
||||||
|
optional uint32 resource_rating_tier = 12 [default = 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClientCredentials {
|
||||||
|
optional TokenType type = 1 [default = KEYBOX];
|
||||||
|
optional bytes token = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type of factory-provisioned device root of trust. Optional.
|
||||||
|
optional TokenType type = 1 [default = KEYBOX];
|
||||||
|
// Factory-provisioned device root of trust. Required.
|
||||||
|
optional bytes token = 2;
|
||||||
|
// Optional client information name/value pairs.
|
||||||
|
repeated NameValue client_info = 3;
|
||||||
|
// Client token generated by the content provider. Optional.
|
||||||
|
optional bytes provider_client_token = 4;
|
||||||
|
// Number of licenses received by the client to which the token above belongs.
|
||||||
|
// Only present if client_token is specified.
|
||||||
|
optional uint32 license_counter = 5;
|
||||||
|
// List of non-baseline client capabilities.
|
||||||
|
optional ClientCapabilities client_capabilities = 6;
|
||||||
|
// Serialized VmpData message. Optional.
|
||||||
|
optional bytes vmp_data = 7;
|
||||||
|
// Optional field that may contain additional provisioning credentials.
|
||||||
|
repeated ClientCredentials device_credentials = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncryptedClientIdentification message used to hold ClientIdentification
|
||||||
|
// messages encrypted for privacy purposes.
|
||||||
|
message EncryptedClientIdentification {
|
||||||
|
// Provider ID for which the ClientIdentifcation is encrypted (owner of
|
||||||
|
// service certificate).
|
||||||
|
optional string provider_id = 1;
|
||||||
|
// Serial number for the service certificate for which ClientIdentification is
|
||||||
|
// encrypted.
|
||||||
|
optional bytes service_certificate_serial_number = 2;
|
||||||
|
// Serialized ClientIdentification message, encrypted with the privacy key
|
||||||
|
// using AES-128-CBC with PKCS#5 padding.
|
||||||
|
optional bytes encrypted_client_id = 3;
|
||||||
|
// Initialization vector needed to decrypt encrypted_client_id.
|
||||||
|
optional bytes encrypted_client_id_iv = 4;
|
||||||
|
// AES-128 privacy key, encrypted with the service public key using RSA-OAEP.
|
||||||
|
optional bytes encrypted_privacy_key = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DRM certificate definition for user devices, intermediate, service, and root
|
||||||
|
// certificates.
|
||||||
|
message DrmCertificate {
|
||||||
|
enum Type {
|
||||||
|
ROOT = 0; // ProtoBestPractices: ignore.
|
||||||
|
DEVICE_MODEL = 1;
|
||||||
|
DEVICE = 2;
|
||||||
|
SERVICE = 3;
|
||||||
|
PROVISIONER = 4;
|
||||||
|
}
|
||||||
|
enum ServiceType {
|
||||||
|
UNKNOWN_SERVICE_TYPE = 0;
|
||||||
|
LICENSE_SERVER_SDK = 1;
|
||||||
|
LICENSE_SERVER_PROXY_SDK = 2;
|
||||||
|
PROVISIONING_SDK = 3;
|
||||||
|
CAS_PROXY_SDK = 4;
|
||||||
|
}
|
||||||
|
enum Algorithm {
|
||||||
|
UNKNOWN_ALGORITHM = 0;
|
||||||
|
RSA = 1;
|
||||||
|
ECC_SECP256R1 = 2;
|
||||||
|
ECC_SECP384R1 = 3;
|
||||||
|
ECC_SECP521R1 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EncryptionKey {
|
||||||
|
// Device public key. PKCS#1 ASN.1 DER-encoded. Required.
|
||||||
|
optional bytes public_key = 1;
|
||||||
|
// Required. The algorithm field contains the curve used to create the
|
||||||
|
// |public_key| if algorithm is one of the ECC types.
|
||||||
|
// The |algorithm| is used for both to determine the if the certificate is
|
||||||
|
// ECC or RSA. The |algorithm| also specifies the parameters that were used
|
||||||
|
// to create |public_key| and are used to create an ephemeral session key.
|
||||||
|
optional Algorithm algorithm = 2 [default = RSA];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type of certificate. Required.
|
||||||
|
optional Type type = 1;
|
||||||
|
// 128-bit globally unique serial number of certificate.
|
||||||
|
// Value is 0 for root certificate. Required.
|
||||||
|
optional bytes serial_number = 2;
|
||||||
|
// POSIX time, in seconds, when the certificate was created. Required.
|
||||||
|
optional uint32 creation_time_seconds = 3;
|
||||||
|
// POSIX time, in seconds, when the certificate should expire. Value of zero
|
||||||
|
// denotes indefinite expiry time. For more information on limited lifespan
|
||||||
|
// DRM certificates see (go/limited-lifespan-drm-certificates).
|
||||||
|
optional uint32 expiration_time_seconds = 12;
|
||||||
|
// Device public key. PKCS#1 ASN.1 DER-encoded. Required.
|
||||||
|
optional bytes public_key = 4;
|
||||||
|
// Widevine system ID for the device. Required for intermediate and
|
||||||
|
// user device certificates.
|
||||||
|
optional uint32 system_id = 5;
|
||||||
|
// Deprecated field, which used to indicate whether the device was a test
|
||||||
|
// (non-production) device. The test_device field in ProvisionedDeviceInfo
|
||||||
|
// below should be observed instead.
|
||||||
|
optional bool test_device_deprecated = 6 [deprecated = true];
|
||||||
|
// Service identifier (web origin) for the provider which owns the
|
||||||
|
// certificate. Required for service and provisioner certificates.
|
||||||
|
optional string provider_id = 7;
|
||||||
|
// This field is used only when type = SERVICE to specify which SDK uses
|
||||||
|
// service certificate. This repeated field is treated as a set. A certificate
|
||||||
|
// may be used for the specified service SDK if the appropriate ServiceType
|
||||||
|
// is specified in this field.
|
||||||
|
repeated ServiceType service_types = 8;
|
||||||
|
// Required. The algorithm field contains the curve used to create the
|
||||||
|
// |public_key| if algorithm is one of the ECC types.
|
||||||
|
// The |algorithm| is used for both to determine the if the certificate is ECC
|
||||||
|
// or RSA. The |algorithm| also specifies the parameters that were used to
|
||||||
|
// create |public_key| and are used to create an ephemeral session key.
|
||||||
|
optional Algorithm algorithm = 9 [default = RSA];
|
||||||
|
// Optional. May be present in DEVICE certificate types. This is the root
|
||||||
|
// of trust identifier that holds an encrypted value that identifies the
|
||||||
|
// keybox or other root of trust that was used to provision a DEVICE drm
|
||||||
|
// certificate.
|
||||||
|
optional bytes rot_id = 10;
|
||||||
|
// Optional. May be present in devices that explicitly support dual keys. When
|
||||||
|
// present the |public_key| is used for verification of received license
|
||||||
|
// request messages.
|
||||||
|
optional EncryptionKey encryption_key = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrmCertificate signed by a higher (CA) DRM certificate.
|
||||||
|
message SignedDrmCertificate {
|
||||||
|
// Serialized certificate. Required.
|
||||||
|
optional bytes drm_certificate = 1;
|
||||||
|
// Signature of certificate. Signed with root or intermediate
|
||||||
|
// certificate specified below. Required.
|
||||||
|
optional bytes signature = 2;
|
||||||
|
// SignedDrmCertificate used to sign this certificate.
|
||||||
|
optional SignedDrmCertificate signer = 3;
|
||||||
|
// Optional field that indicates the hash algorithm used in signature scheme.
|
||||||
|
optional HashAlgorithmProto hash_algorithm = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WidevinePsshData {
|
||||||
|
enum Type {
|
||||||
|
SINGLE = 0; // Single PSSH to be used to retrieve content keys.
|
||||||
|
ENTITLEMENT = 1; // Primary PSSH used to retrieve entitlement keys.
|
||||||
|
ENTITLED_KEY = 2; // Secondary PSSH containing entitled key(s).
|
||||||
|
}
|
||||||
|
|
||||||
|
message EntitledKey {
|
||||||
|
// ID of entitlement key used for wrapping |key|.
|
||||||
|
optional bytes entitlement_key_id = 1;
|
||||||
|
// ID of the entitled key.
|
||||||
|
optional bytes key_id = 2;
|
||||||
|
// Wrapped key. Required.
|
||||||
|
optional bytes key = 3;
|
||||||
|
// IV used for wrapping |key|. Required.
|
||||||
|
optional bytes iv = 4;
|
||||||
|
// Size of entitlement key used for wrapping |key|.
|
||||||
|
optional uint32 entitlement_key_size_bytes = 5 [default = 32];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entitlement or content key IDs. Can onnly present in SINGLE or ENTITLEMENT
|
||||||
|
// PSSHs. May be repeated to facilitate delivery of multiple keys in a
|
||||||
|
// single license. Cannot be used in conjunction with content_id or
|
||||||
|
// group_ids, which are the preferred mechanism.
|
||||||
|
repeated bytes key_ids = 2;
|
||||||
|
|
||||||
|
// Content identifier which may map to multiple entitlement or content key
|
||||||
|
// IDs to facilitate the delivery of multiple keys in a single license.
|
||||||
|
// Cannot be present in conjunction with key_ids, but if used must be in all
|
||||||
|
// PSSHs.
|
||||||
|
optional bytes content_id = 4;
|
||||||
|
|
||||||
|
// Crypto period index, for media using key rotation. Always corresponds to
|
||||||
|
// The content key period. This means that if using entitlement licensing
|
||||||
|
// the ENTITLED_KEY PSSHs will have sequential crypto_period_index's, whereas
|
||||||
|
// the ENTITELEMENT PSSHs will have gaps in the sequence. Required if doing
|
||||||
|
// key rotation.
|
||||||
|
optional uint32 crypto_period_index = 7;
|
||||||
|
|
||||||
|
// Protection scheme identifying the encryption algorithm. The protection
|
||||||
|
// scheme is represented as a uint32 value. The uint32 contains 4 bytes each
|
||||||
|
// representing a single ascii character in one of the 4CC protection scheme
|
||||||
|
// values. To be deprecated in favor of signaling from content.
|
||||||
|
// 'cenc' (AES-CTR) protection_scheme = 0x63656E63,
|
||||||
|
// 'cbc1' (AES-CBC) protection_scheme = 0x63626331,
|
||||||
|
// 'cens' (AES-CTR pattern encryption) protection_scheme = 0x63656E73,
|
||||||
|
// 'cbcs' (AES-CBC pattern encryption) protection_scheme = 0x63626373.
|
||||||
|
optional uint32 protection_scheme = 9;
|
||||||
|
|
||||||
|
// Optional. For media using key rotation, this represents the duration
|
||||||
|
// of each crypto period in seconds.
|
||||||
|
optional uint32 crypto_period_seconds = 10;
|
||||||
|
|
||||||
|
// Type of PSSH. Required if not SINGLE.
|
||||||
|
optional Type type = 11 [default = SINGLE];
|
||||||
|
|
||||||
|
// Key sequence for Widevine-managed keys. Optional.
|
||||||
|
optional uint32 key_sequence = 12;
|
||||||
|
|
||||||
|
// Group identifiers for all groups to which the content belongs. This can
|
||||||
|
// be used to deliver licenses to unlock multiple titles / channels.
|
||||||
|
// Optional, and may only be present in ENTITLEMENT and ENTITLED_KEY PSSHs, and
|
||||||
|
// not in conjunction with key_ids.
|
||||||
|
repeated bytes group_ids = 13;
|
||||||
|
|
||||||
|
// Copy/copies of the content key used to decrypt the media stream in which
|
||||||
|
// the PSSH box is embedded, each wrapped with a different entitlement key.
|
||||||
|
// May also contain sub-licenses to support devices with OEMCrypto 13 or
|
||||||
|
// older. May be repeated if using group entitlement keys. Present only in
|
||||||
|
// PSSHs of type ENTITLED_KEY.
|
||||||
|
repeated EntitledKey entitled_keys = 14;
|
||||||
|
|
||||||
|
// Video feature identifier, which is used in conjunction with |content_id|
|
||||||
|
// to determine the set of keys to be returned in the license. Cannot be
|
||||||
|
// present in conjunction with |key_ids|.
|
||||||
|
// Current values are "HDR".
|
||||||
|
optional string video_feature = 15;
|
||||||
|
|
||||||
|
//////////////////////////// Deprecated Fields ////////////////////////////
|
||||||
|
enum Algorithm {
|
||||||
|
UNENCRYPTED = 0;
|
||||||
|
AESCTR = 1;
|
||||||
|
};
|
||||||
|
optional Algorithm algorithm = 1 [deprecated = true];
|
||||||
|
|
||||||
|
// Content provider name.
|
||||||
|
optional string provider = 3 [deprecated = true];
|
||||||
|
|
||||||
|
// Track type. Acceptable values are SD, HD and AUDIO. Used to
|
||||||
|
// differentiate content keys used by an asset.
|
||||||
|
optional string track_type = 5 [deprecated = true];
|
||||||
|
|
||||||
|
// The name of a registered policy to be used for this asset.
|
||||||
|
optional string policy = 6 [deprecated = true];
|
||||||
|
|
||||||
|
// Optional protected context for group content. The grouped_license is a
|
||||||
|
// serialized SignedMessage.
|
||||||
|
optional bytes grouped_license = 8 [deprecated = true];
|
||||||
|
}
|
||||||
|
|
||||||
|
// File Hashes for Verified Media Path (VMP) support.
|
||||||
|
message FileHashes {
|
||||||
|
message Signature {
|
||||||
|
optional string filename = 1;
|
||||||
|
optional bool test_signing = 2; //0 - release, 1 - testing
|
||||||
|
optional bytes SHA512Hash = 3;
|
||||||
|
optional bool main_exe = 4; //0 for dlls, 1 for exe, this is field 3 in file
|
||||||
|
optional bytes signature = 5;
|
||||||
|
}
|
||||||
|
optional bytes signer = 1;
|
||||||
|
repeated Signature signatures = 2;
|
||||||
|
}
|
||||||
4996
modules/license_protocol.ts
Normal file
4996
modules/license_protocol.ts
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -82,7 +82,8 @@ export type ConfigObject = {
|
||||||
bin: {
|
bin: {
|
||||||
ffmpeg?: string,
|
ffmpeg?: string,
|
||||||
mkvmerge?: string,
|
mkvmerge?: string,
|
||||||
ffprobe?: string
|
ffprobe?: string,
|
||||||
|
mp4decrypt?: string
|
||||||
},
|
},
|
||||||
cli: {
|
cli: {
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
|
|
@ -146,7 +147,8 @@ const loadBinCfg = async () => {
|
||||||
const defaultBin = {
|
const defaultBin = {
|
||||||
ffmpeg: 'ffmpeg',
|
ffmpeg: 'ffmpeg',
|
||||||
mkvmerge: 'mkvmerge',
|
mkvmerge: 'mkvmerge',
|
||||||
ffprobe: 'ffprobe'
|
ffprobe: 'ffprobe',
|
||||||
|
mp4decrypt: 'mp4decrypt'
|
||||||
};
|
};
|
||||||
const keys = Object.keys(defaultBin) as (keyof typeof defaultBin)[];
|
const keys = Object.keys(defaultBin) as (keyof typeof defaultBin)[];
|
||||||
for(const dir of keys){
|
for(const dir of keys){
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,12 @@
|
||||||
"got": "^11.8.6",
|
"got": "^11.8.6",
|
||||||
"iso-639": "^0.2.2",
|
"iso-639": "^0.2.2",
|
||||||
"log4js": "^6.9.1",
|
"log4js": "^6.9.1",
|
||||||
|
"long": "^5.2.3",
|
||||||
"lookpath": "^1.2.2",
|
"lookpath": "^1.2.2",
|
||||||
"m3u8-parsed": "^1.3.0",
|
"m3u8-parsed": "^1.3.0",
|
||||||
"mpd-parser": "^1.3.0",
|
"mpd-parser": "^1.3.0",
|
||||||
"open": "^8.4.2",
|
"open": "^8.4.2",
|
||||||
|
"protobufjs": "^7.2.5",
|
||||||
"sei-helper": "^3.3.0",
|
"sei-helper": "^3.3.0",
|
||||||
"typescript-eslint": "0.0.1-alpha.0",
|
"typescript-eslint": "0.0.1-alpha.0",
|
||||||
"ws": "^8.13.0",
|
"ws": "^8.13.0",
|
||||||
|
|
@ -70,7 +72,6 @@
|
||||||
"@types/cors": "^2.8.13",
|
"@types/cors": "^2.8.13",
|
||||||
"@types/express": "^4.17.17",
|
"@types/express": "^4.17.17",
|
||||||
"@types/ffprobe": "^1.1.4",
|
"@types/ffprobe": "^1.1.4",
|
||||||
"@types/ffprobe-static": "^2.0.1",
|
|
||||||
"@types/fs-extra": "^11.0.1",
|
"@types/fs-extra": "^11.0.1",
|
||||||
"@types/node": "^18.15.11",
|
"@types/node": "^18.15.11",
|
||||||
"@types/ws": "^8.5.5",
|
"@types/ws": "^8.5.5",
|
||||||
|
|
@ -83,6 +84,7 @@
|
||||||
"eslint-plugin-import": "^2.27.5",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"eslint-plugin-react": "7.32.2",
|
"eslint-plugin-react": "7.32.2",
|
||||||
"pkg": "^5.8.1",
|
"pkg": "^5.8.1",
|
||||||
|
"protoc": "^1.1.3",
|
||||||
"removeNPMAbsolutePaths": "^3.0.1",
|
"removeNPMAbsolutePaths": "^3.0.1",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "5.1.6"
|
"typescript": "5.1.6"
|
||||||
|
|
|
||||||
290
pnpm-lock.yaml
290
pnpm-lock.yaml
|
|
@ -47,6 +47,9 @@ dependencies:
|
||||||
log4js:
|
log4js:
|
||||||
specifier: ^6.9.1
|
specifier: ^6.9.1
|
||||||
version: 6.9.1
|
version: 6.9.1
|
||||||
|
long:
|
||||||
|
specifier: ^5.2.3
|
||||||
|
version: 5.2.3
|
||||||
lookpath:
|
lookpath:
|
||||||
specifier: ^1.2.2
|
specifier: ^1.2.2
|
||||||
version: 1.2.2
|
version: 1.2.2
|
||||||
|
|
@ -59,6 +62,9 @@ dependencies:
|
||||||
open:
|
open:
|
||||||
specifier: ^8.4.2
|
specifier: ^8.4.2
|
||||||
version: 8.4.2
|
version: 8.4.2
|
||||||
|
protobufjs:
|
||||||
|
specifier: ^7.2.5
|
||||||
|
version: 7.2.5
|
||||||
sei-helper:
|
sei-helper:
|
||||||
specifier: ^3.3.0
|
specifier: ^3.3.0
|
||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
|
|
@ -85,9 +91,6 @@ devDependencies:
|
||||||
'@types/ffprobe':
|
'@types/ffprobe':
|
||||||
specifier: ^1.1.4
|
specifier: ^1.1.4
|
||||||
version: 1.1.4
|
version: 1.1.4
|
||||||
'@types/ffprobe-static':
|
|
||||||
specifier: ^2.0.1
|
|
||||||
version: 2.0.1
|
|
||||||
'@types/fs-extra':
|
'@types/fs-extra':
|
||||||
specifier: ^11.0.1
|
specifier: ^11.0.1
|
||||||
version: 11.0.1
|
version: 11.0.1
|
||||||
|
|
@ -121,6 +124,9 @@ devDependencies:
|
||||||
pkg:
|
pkg:
|
||||||
specifier: ^5.8.1
|
specifier: ^5.8.1
|
||||||
version: 5.8.1
|
version: 5.8.1
|
||||||
|
protoc:
|
||||||
|
specifier: ^1.1.3
|
||||||
|
version: 1.1.3
|
||||||
removeNPMAbsolutePaths:
|
removeNPMAbsolutePaths:
|
||||||
specifier: ^3.0.1
|
specifier: ^3.0.1
|
||||||
version: 3.0.1
|
version: 3.0.1
|
||||||
|
|
@ -1780,6 +1786,49 @@ packages:
|
||||||
'@nodelib/fs.scandir': 2.1.5
|
'@nodelib/fs.scandir': 2.1.5
|
||||||
fastq: 1.15.0
|
fastq: 1.15.0
|
||||||
|
|
||||||
|
/@protobufjs/aspromise@1.1.2:
|
||||||
|
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@protobufjs/base64@1.1.2:
|
||||||
|
resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@protobufjs/codegen@2.0.4:
|
||||||
|
resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@protobufjs/eventemitter@1.1.0:
|
||||||
|
resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@protobufjs/fetch@1.1.0:
|
||||||
|
resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
|
||||||
|
dependencies:
|
||||||
|
'@protobufjs/aspromise': 1.1.2
|
||||||
|
'@protobufjs/inquire': 1.1.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@protobufjs/float@1.0.2:
|
||||||
|
resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@protobufjs/inquire@1.1.0:
|
||||||
|
resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@protobufjs/path@1.1.2:
|
||||||
|
resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@protobufjs/pool@1.1.0:
|
||||||
|
resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@protobufjs/utf8@1.1.0:
|
||||||
|
resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@rushstack/eslint-patch@1.2.0:
|
/@rushstack/eslint-patch@1.2.0:
|
||||||
resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==}
|
resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
@ -1857,10 +1906,6 @@ packages:
|
||||||
'@types/serve-static': 1.15.1
|
'@types/serve-static': 1.15.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/ffprobe-static@2.0.1:
|
|
||||||
resolution: {integrity: sha512-V5CrKUfms0lBGSXliKmKzSFFZWgJusQks1YfjRI/+2dXFF+aK7qBAarCe/ryYHQI44jYQX7xtlgH0fCuJepuGQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/ffprobe@1.1.4:
|
/@types/ffprobe@1.1.4:
|
||||||
resolution: {integrity: sha512-gtfU+bD4FDoF1S2ybmIWEIz0K5ijeHpi+CgJUtXl3FTGnf+61HmsZksqDn8M9M9lRJU9SRyMLt5yrIwUSep4Uw==}
|
resolution: {integrity: sha512-gtfU+bD4FDoF1S2ybmIWEIz0K5ijeHpi+CgJUtXl3FTGnf+61HmsZksqDn8M9M9lRJU9SRyMLt5yrIwUSep4Uw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
@ -1968,7 +2013,7 @@ packages:
|
||||||
grapheme-splitter: 1.0.4
|
grapheme-splitter: 1.0.4
|
||||||
ignore: 5.2.4
|
ignore: 5.2.4
|
||||||
natural-compare-lite: 1.4.0
|
natural-compare-lite: 1.4.0
|
||||||
semver: 7.3.8
|
semver: 7.5.4
|
||||||
tsutils: 3.21.0(typescript@5.1.6)
|
tsutils: 3.21.0(typescript@5.1.6)
|
||||||
typescript: 5.1.6
|
typescript: 5.1.6
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
|
@ -2137,7 +2182,7 @@ packages:
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
globby: 11.1.0
|
globby: 11.1.0
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
semver: 7.3.8
|
semver: 7.5.4
|
||||||
tsutils: 3.21.0(typescript@5.1.6)
|
tsutils: 3.21.0(typescript@5.1.6)
|
||||||
typescript: 5.1.6
|
typescript: 5.1.6
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
|
@ -2178,7 +2223,7 @@ packages:
|
||||||
'@typescript-eslint/typescript-estree': 5.57.1(typescript@5.1.6)
|
'@typescript-eslint/typescript-estree': 5.57.1(typescript@5.1.6)
|
||||||
eslint: 8.45.0
|
eslint: 8.45.0
|
||||||
eslint-scope: 5.1.1
|
eslint-scope: 5.1.1
|
||||||
semver: 7.3.8
|
semver: 7.5.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
|
@ -2492,6 +2537,18 @@ packages:
|
||||||
/base64-js@1.5.1:
|
/base64-js@1.5.1:
|
||||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
|
||||||
|
/big-integer@1.6.52:
|
||||||
|
resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==}
|
||||||
|
engines: {node: '>=0.6'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/binary@0.3.0:
|
||||||
|
resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==}
|
||||||
|
dependencies:
|
||||||
|
buffers: 0.1.1
|
||||||
|
chainsaw: 0.1.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/bl@4.1.0:
|
/bl@4.1.0:
|
||||||
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
|
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -2499,6 +2556,10 @@ packages:
|
||||||
inherits: 2.0.4
|
inherits: 2.0.4
|
||||||
readable-stream: 3.6.2
|
readable-stream: 3.6.2
|
||||||
|
|
||||||
|
/bluebird@3.4.7:
|
||||||
|
resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/body-parser@1.20.1:
|
/body-parser@1.20.1:
|
||||||
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
|
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
|
||||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||||
|
|
@ -2556,12 +2617,22 @@ packages:
|
||||||
node-releases: 2.0.13
|
node-releases: 2.0.13
|
||||||
update-browserslist-db: 1.0.11(browserslist@4.21.9)
|
update-browserslist-db: 1.0.11(browserslist@4.21.9)
|
||||||
|
|
||||||
|
/buffer-indexof-polyfill@1.0.2:
|
||||||
|
resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==}
|
||||||
|
engines: {node: '>=0.10'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/buffer@5.7.1:
|
/buffer@5.7.1:
|
||||||
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
base64-js: 1.5.1
|
base64-js: 1.5.1
|
||||||
ieee754: 1.2.1
|
ieee754: 1.2.1
|
||||||
|
|
||||||
|
/buffers@0.1.1:
|
||||||
|
resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==}
|
||||||
|
engines: {node: '>=0.2.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/bytes@3.1.2:
|
/bytes@3.1.2:
|
||||||
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
@ -2602,6 +2673,12 @@ packages:
|
||||||
/caniuse-lite@1.0.30001516:
|
/caniuse-lite@1.0.30001516:
|
||||||
resolution: {integrity: sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==}
|
resolution: {integrity: sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==}
|
||||||
|
|
||||||
|
/chainsaw@0.1.0:
|
||||||
|
resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==}
|
||||||
|
dependencies:
|
||||||
|
traverse: 0.3.9
|
||||||
|
dev: true
|
||||||
|
|
||||||
/chalk@2.4.2:
|
/chalk@2.4.2:
|
||||||
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
|
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|
@ -2662,12 +2739,34 @@ packages:
|
||||||
wrap-ansi: 7.0.0
|
wrap-ansi: 7.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/clone-buffer@1.0.0:
|
||||||
|
resolution: {integrity: sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==}
|
||||||
|
engines: {node: '>= 0.10'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/clone-response@1.0.3:
|
/clone-response@1.0.3:
|
||||||
resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==}
|
resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
mimic-response: 1.0.1
|
mimic-response: 1.0.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/clone-stats@1.0.0:
|
||||||
|
resolution: {integrity: sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/clone@2.1.2:
|
||||||
|
resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/cloneable-readable@1.1.3:
|
||||||
|
resolution: {integrity: sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==}
|
||||||
|
dependencies:
|
||||||
|
inherits: 2.0.4
|
||||||
|
process-nextick-args: 2.0.1
|
||||||
|
readable-stream: 2.3.8
|
||||||
|
dev: true
|
||||||
|
|
||||||
/color-convert@1.9.3:
|
/color-convert@1.9.3:
|
||||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -2783,6 +2882,11 @@ packages:
|
||||||
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
|
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/data-uri-to-buffer@4.0.1:
|
||||||
|
resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
|
||||||
|
engines: {node: '>= 12'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/date-format@4.0.14:
|
/date-format@4.0.14:
|
||||||
resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==}
|
resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==}
|
||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
|
|
@ -2958,6 +3062,12 @@ packages:
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/duplexer2@0.1.4:
|
||||||
|
resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==}
|
||||||
|
dependencies:
|
||||||
|
readable-stream: 2.3.8
|
||||||
|
dev: true
|
||||||
|
|
||||||
/ee-first@1.1.1:
|
/ee-first@1.1.1:
|
||||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
@ -3537,6 +3647,14 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
reusify: 1.0.4
|
reusify: 1.0.4
|
||||||
|
|
||||||
|
/fetch-blob@3.2.0:
|
||||||
|
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
|
||||||
|
engines: {node: ^12.20 || >= 14.13}
|
||||||
|
dependencies:
|
||||||
|
node-domexception: 1.0.0
|
||||||
|
web-streams-polyfill: 3.2.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/ffprobe@1.1.2:
|
/ffprobe@1.1.2:
|
||||||
resolution: {integrity: sha512-a+oTbhyeM7Z8PRy+mpzmVUAnATZT7z4BO94HSKeqHupdmjiKZ1djzcZkyoyXA21zCOCG7oVRrsBMmvvtmzoz4g==}
|
resolution: {integrity: sha512-a+oTbhyeM7Z8PRy+mpzmVUAnATZT7z4BO94HSKeqHupdmjiKZ1djzcZkyoyXA21zCOCG7oVRrsBMmvvtmzoz4g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -3603,6 +3721,13 @@ packages:
|
||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/formdata-polyfill@4.0.10:
|
||||||
|
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
|
||||||
|
engines: {node: '>=12.20.0'}
|
||||||
|
dependencies:
|
||||||
|
fetch-blob: 3.2.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/forwarded@0.2.0:
|
/forwarded@0.2.0:
|
||||||
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
|
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
@ -3655,6 +3780,16 @@ packages:
|
||||||
/fs.realpath@1.0.0:
|
/fs.realpath@1.0.0:
|
||||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||||
|
|
||||||
|
/fstream@1.0.12:
|
||||||
|
resolution: {integrity: sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==}
|
||||||
|
engines: {node: '>=0.6'}
|
||||||
|
dependencies:
|
||||||
|
graceful-fs: 4.2.11
|
||||||
|
inherits: 2.0.4
|
||||||
|
mkdirp: 0.5.6
|
||||||
|
rimraf: 2.7.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/function-bind@1.1.1:
|
/function-bind@1.1.1:
|
||||||
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
|
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
|
||||||
|
|
||||||
|
|
@ -4195,6 +4330,10 @@ packages:
|
||||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/listenercount@1.0.1:
|
||||||
|
resolution: {integrity: sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/locate-path@6.0.0:
|
/locate-path@6.0.0:
|
||||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
@ -4225,6 +4364,10 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/long@5.2.3:
|
||||||
|
resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/lookpath@1.2.2:
|
/lookpath@1.2.2:
|
||||||
resolution: {integrity: sha512-k2Gmn8iV6qdME3ztZC2spubmQISimFOPLuQKiPaLcVdRz0IpdxrNClVepMlyTJlhodm/zG/VfbkWERm3kUIh+Q==}
|
resolution: {integrity: sha512-k2Gmn8iV6qdME3ztZC2spubmQISimFOPLuQKiPaLcVdRz0IpdxrNClVepMlyTJlhodm/zG/VfbkWERm3kUIh+Q==}
|
||||||
engines: {npm: '>=6.13.4'}
|
engines: {npm: '>=6.13.4'}
|
||||||
|
|
@ -4342,6 +4485,13 @@ packages:
|
||||||
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/mkdirp@0.5.6:
|
||||||
|
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
minimist: 1.2.8
|
||||||
|
dev: true
|
||||||
|
|
||||||
/mpd-parser@1.3.0:
|
/mpd-parser@1.3.0:
|
||||||
resolution: {integrity: sha512-WgeIwxAqkmb9uTn4ClicXpEQYCEduDqRKfmUdp4X8vmghKfBNXZLYpREn9eqrDx/Tf5LhzRcJLSpi4ohfV742Q==}
|
resolution: {integrity: sha512-WgeIwxAqkmb9uTn4ClicXpEQYCEduDqRKfmUdp4X8vmghKfBNXZLYpREn9eqrDx/Tf5LhzRcJLSpi4ohfV742Q==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -4393,7 +4543,12 @@ packages:
|
||||||
resolution: {integrity: sha512-jAlSOFR1Bls963NmFwxeQkNTzqjUF0NThm8Le7eRIRGzFUVJuMOFZDLv5Y30W/Oaw+KEebEJLAigwO9gQHoEmw==}
|
resolution: {integrity: sha512-jAlSOFR1Bls963NmFwxeQkNTzqjUF0NThm8Le7eRIRGzFUVJuMOFZDLv5Y30W/Oaw+KEebEJLAigwO9gQHoEmw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dependencies:
|
dependencies:
|
||||||
semver: 7.3.8
|
semver: 7.5.4
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/node-domexception@1.0.0:
|
||||||
|
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||||
|
engines: {node: '>=10.5.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/node-fetch@2.6.9:
|
/node-fetch@2.6.9:
|
||||||
|
|
@ -4408,6 +4563,15 @@ packages:
|
||||||
whatwg-url: 5.0.0
|
whatwg-url: 5.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/node-fetch@3.3.2:
|
||||||
|
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
|
||||||
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
|
dependencies:
|
||||||
|
data-uri-to-buffer: 4.0.1
|
||||||
|
fetch-blob: 3.2.0
|
||||||
|
formdata-polyfill: 4.0.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
/node-releases@2.0.10:
|
/node-releases@2.0.10:
|
||||||
resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==}
|
resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
@ -4614,7 +4778,7 @@ packages:
|
||||||
https-proxy-agent: 5.0.1
|
https-proxy-agent: 5.0.1
|
||||||
node-fetch: 2.6.9
|
node-fetch: 2.6.9
|
||||||
progress: 2.0.3
|
progress: 2.0.3
|
||||||
semver: 7.3.8
|
semver: 7.5.4
|
||||||
tar-fs: 2.1.1
|
tar-fs: 2.1.1
|
||||||
yargs: 16.2.0
|
yargs: 16.2.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
|
@ -4695,6 +4859,39 @@ packages:
|
||||||
react-is: 16.13.1
|
react-is: 16.13.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/protobufjs@7.2.5:
|
||||||
|
resolution: {integrity: sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
requiresBuild: true
|
||||||
|
dependencies:
|
||||||
|
'@protobufjs/aspromise': 1.1.2
|
||||||
|
'@protobufjs/base64': 1.1.2
|
||||||
|
'@protobufjs/codegen': 2.0.4
|
||||||
|
'@protobufjs/eventemitter': 1.1.0
|
||||||
|
'@protobufjs/fetch': 1.1.0
|
||||||
|
'@protobufjs/float': 1.0.2
|
||||||
|
'@protobufjs/inquire': 1.1.0
|
||||||
|
'@protobufjs/path': 1.1.2
|
||||||
|
'@protobufjs/pool': 1.1.0
|
||||||
|
'@protobufjs/utf8': 1.1.0
|
||||||
|
'@types/node': 18.15.11
|
||||||
|
long: 5.2.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/protoc@1.1.3:
|
||||||
|
resolution: {integrity: sha512-Vy4OBxCcF0W38YrZZRFix659gFu8ujIxVDP1SUBK9ELzyeMSBe8m8tYyYlX1PI5j9gse9hWu4c4nzQaHesAf8Q==}
|
||||||
|
hasBin: true
|
||||||
|
requiresBuild: true
|
||||||
|
dependencies:
|
||||||
|
glob: 7.2.3
|
||||||
|
mkdirp: 0.5.6
|
||||||
|
node-fetch: 3.3.2
|
||||||
|
rimraf: 3.0.2
|
||||||
|
unzipper: 0.10.14
|
||||||
|
uuid: 9.0.1
|
||||||
|
vinyl: 2.2.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/proxy-addr@2.0.7:
|
/proxy-addr@2.0.7:
|
||||||
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
|
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
|
|
@ -4824,12 +5021,21 @@ packages:
|
||||||
jsesc: 0.5.0
|
jsesc: 0.5.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/remove-trailing-separator@1.1.0:
|
||||||
|
resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/removeNPMAbsolutePaths@3.0.1:
|
/removeNPMAbsolutePaths@3.0.1:
|
||||||
resolution: {integrity: sha512-rJc1aHu5LT4rncs7gga/asiyQG+G1TkweO7L27D/oMBtfbHmSFSp7RgUtrfuZzk9c/4P2xHjHnD+cUNzWRFB4A==}
|
resolution: {integrity: sha512-rJc1aHu5LT4rncs7gga/asiyQG+G1TkweO7L27D/oMBtfbHmSFSp7RgUtrfuZzk9c/4P2xHjHnD+cUNzWRFB4A==}
|
||||||
engines: {node: '>=4.0.0'}
|
engines: {node: '>=4.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/replace-ext@1.0.1:
|
||||||
|
resolution: {integrity: sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==}
|
||||||
|
engines: {node: '>= 0.10'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/require-directory@2.1.1:
|
/require-directory@2.1.1:
|
||||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
@ -4873,6 +5079,13 @@ packages:
|
||||||
resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==}
|
resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/rimraf@2.7.1:
|
||||||
|
resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
glob: 7.2.3
|
||||||
|
dev: true
|
||||||
|
|
||||||
/rimraf@3.0.2:
|
/rimraf@3.0.2:
|
||||||
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
|
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -4914,14 +5127,6 @@ packages:
|
||||||
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
/semver@7.3.8:
|
|
||||||
resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
lru-cache: 6.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/semver@7.5.4:
|
/semver@7.5.4:
|
||||||
resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
|
resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
@ -4962,6 +5167,10 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/setimmediate@1.0.5:
|
||||||
|
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/setprototypeof@1.2.0:
|
/setprototypeof@1.2.0:
|
||||||
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
|
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
@ -5167,6 +5376,10 @@ packages:
|
||||||
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/traverse@0.3.9:
|
||||||
|
resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/ts-api-utils@1.0.1(typescript@5.1.6):
|
/ts-api-utils@1.0.1(typescript@5.1.6):
|
||||||
resolution: {integrity: sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==}
|
resolution: {integrity: sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==}
|
||||||
engines: {node: '>=16.13.0'}
|
engines: {node: '>=16.13.0'}
|
||||||
|
|
@ -5313,6 +5526,21 @@ packages:
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/unzipper@0.10.14:
|
||||||
|
resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==}
|
||||||
|
dependencies:
|
||||||
|
big-integer: 1.6.52
|
||||||
|
binary: 0.3.0
|
||||||
|
bluebird: 3.4.7
|
||||||
|
buffer-indexof-polyfill: 1.0.2
|
||||||
|
duplexer2: 0.1.4
|
||||||
|
fstream: 1.0.12
|
||||||
|
graceful-fs: 4.2.11
|
||||||
|
listenercount: 1.0.1
|
||||||
|
readable-stream: 2.3.8
|
||||||
|
setimmediate: 1.0.5
|
||||||
|
dev: true
|
||||||
|
|
||||||
/update-browserslist-db@1.0.10(browserslist@4.21.5):
|
/update-browserslist-db@1.0.10(browserslist@4.21.5):
|
||||||
resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==}
|
resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -5351,6 +5579,11 @@ packages:
|
||||||
engines: {node: '>= 0.4.0'}
|
engines: {node: '>= 0.4.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/uuid@9.0.1:
|
||||||
|
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
||||||
|
hasBin: true
|
||||||
|
dev: true
|
||||||
|
|
||||||
/v8-compile-cache-lib@3.0.1:
|
/v8-compile-cache-lib@3.0.1:
|
||||||
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
|
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
@ -5360,6 +5593,23 @@ packages:
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/vinyl@2.2.1:
|
||||||
|
resolution: {integrity: sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==}
|
||||||
|
engines: {node: '>= 0.10'}
|
||||||
|
dependencies:
|
||||||
|
clone: 2.1.2
|
||||||
|
clone-buffer: 1.0.0
|
||||||
|
clone-stats: 1.0.0
|
||||||
|
cloneable-readable: 1.1.3
|
||||||
|
remove-trailing-separator: 1.1.0
|
||||||
|
replace-ext: 1.0.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/web-streams-polyfill@3.2.1:
|
||||||
|
resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==}
|
||||||
|
engines: {node: '>= 8'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/webidl-conversions@3.0.1:
|
/webidl-conversions@3.0.1:
|
||||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
|
||||||
0
widevine/.gitkeep
Normal file
0
widevine/.gitkeep
Normal file
Loading…
Reference in a new issue