mirror of
https://github.com/anidl/multi-downloader-nx.git
synced 2026-03-11 17:45:30 +00:00
Initial attempt to add --syncTiming flag
Add --syncTiming flag to attempt to detect timing differences in multi-dub downloads and sync them properly. Currently disabled by default since it's experimental and likely buggy. Potentially Resolved #471
This commit is contained in:
parent
54d3a14bea
commit
485433cd74
8 changed files with 183 additions and 23 deletions
13
@types/crunchyTypes.d.ts
vendored
13
@types/crunchyTypes.d.ts
vendored
|
|
@ -29,7 +29,8 @@ export type CrunchyDownloadOptions = {
|
|||
defaultAudio: LanguageItem,
|
||||
ccTag: string,
|
||||
dlVideoOnce: boolean,
|
||||
skipmux?: boolean
|
||||
skipmux?: boolean,
|
||||
syncTiming: boolean,
|
||||
}
|
||||
|
||||
export type CurnchyMultiDownload = {
|
||||
|
|
@ -52,7 +53,8 @@ export type CrunchyMuxOptions = {
|
|||
mkvmergeOptions: string[],
|
||||
defaultSub: LanguageItem,
|
||||
defaultAudio: LanguageItem,
|
||||
ccTag: string
|
||||
ccTag: string,
|
||||
syncTiming: boolean,
|
||||
}
|
||||
|
||||
export type CrunchyEpMeta = {
|
||||
|
|
@ -60,7 +62,9 @@ export type CrunchyEpMeta = {
|
|||
mediaId: string,
|
||||
lang?: LanguageItem,
|
||||
playback?: string,
|
||||
versions?: EpisodeVersion[] | null
|
||||
versions?: EpisodeVersion[] | null,
|
||||
isSubbed: boolean,
|
||||
isDubbed: boolean,
|
||||
}[],
|
||||
seriesTitle: string,
|
||||
seasonTitle: string,
|
||||
|
|
@ -76,7 +80,8 @@ export type CrunchyEpMeta = {
|
|||
export type DownloadedMedia = {
|
||||
type: 'Video',
|
||||
lang: LanguageItem,
|
||||
path: string
|
||||
path: string,
|
||||
isPrimary?: boolean
|
||||
} | ({
|
||||
type: 'Subtitle',
|
||||
cc: boolean
|
||||
|
|
|
|||
36
crunchy.ts
36
crunchy.ts
|
|
@ -816,7 +816,9 @@ export default class Crunchy implements ServiceClass {
|
|||
{
|
||||
mediaId: item.id,
|
||||
versions: null,
|
||||
lang: langsData.languages.find(a => a.code == yargs.appArgv(this.cfg.cli).dubLang[0])
|
||||
lang: langsData.languages.find(a => a.code == yargs.appArgv(this.cfg.cli).dubLang[0]),
|
||||
isSubbed: item.is_subbed,
|
||||
isDubbed: item.is_dubbed
|
||||
}
|
||||
],
|
||||
seriesTitle: item.series_title,
|
||||
|
|
@ -974,7 +976,9 @@ export default class Crunchy implements ServiceClass {
|
|||
epMeta.data = [
|
||||
{
|
||||
mediaId: 'E:'+ item.id,
|
||||
versions: item.episode_metadata.versions
|
||||
versions: item.episode_metadata.versions,
|
||||
isSubbed: item.episode_metadata.is_subbed,
|
||||
isDubbed: item.episode_metadata.is_dubbed
|
||||
}
|
||||
];
|
||||
epMeta.seriesTitle = item.episode_metadata.series_title;
|
||||
|
|
@ -986,7 +990,9 @@ export default class Crunchy implements ServiceClass {
|
|||
item.f_num = 'F:' + item.id;
|
||||
epMeta.data = [
|
||||
{
|
||||
mediaId: 'M:'+ item.id
|
||||
mediaId: 'M:'+ item.id,
|
||||
isSubbed: item.movie_listing_metadata.is_subbed,
|
||||
isDubbed: item.movie_listing_metadata.is_dubbed
|
||||
}
|
||||
];
|
||||
epMeta.seriesTitle = item.title;
|
||||
|
|
@ -997,7 +1003,9 @@ export default class Crunchy implements ServiceClass {
|
|||
item.f_num = 'F:' + item.id;
|
||||
epMeta.data = [
|
||||
{
|
||||
mediaId: 'M:'+ item.id
|
||||
mediaId: 'M:'+ item.id,
|
||||
isSubbed: item.movie_metadata.is_subbed,
|
||||
isDubbed: item.movie_metadata.is_dubbed
|
||||
}
|
||||
];
|
||||
epMeta.season = 0;
|
||||
|
|
@ -1053,6 +1061,8 @@ export default class Crunchy implements ServiceClass {
|
|||
|
||||
//Make sure token is up to date
|
||||
await this.refreshToken(true, true);
|
||||
let currentVersion;
|
||||
let isPrimary = mMeta.isSubbed;
|
||||
const AuthHeaders = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token.access_token}`,
|
||||
|
|
@ -1063,11 +1073,13 @@ export default class Crunchy implements ServiceClass {
|
|||
//Get Media GUID
|
||||
let mediaId = mMeta.mediaId;
|
||||
if (mMeta.versions && mMeta.lang) {
|
||||
mediaId = mMeta.versions.find(a => a.audio_locale == mMeta.lang?.cr_locale)?.media_guid as string;
|
||||
if (!mediaId) {
|
||||
currentVersion = mMeta.versions.find(a => a.audio_locale == mMeta.lang?.cr_locale);
|
||||
if (!currentVersion?.media_guid) {
|
||||
console.error('Selected language not found.');
|
||||
return undefined;
|
||||
continue;
|
||||
}
|
||||
isPrimary = currentVersion.original;
|
||||
mediaId = currentVersion?.media_guid;
|
||||
}
|
||||
|
||||
// If for whatever reason mediaId has a :, return the ID only
|
||||
|
|
@ -1352,7 +1364,8 @@ export default class Crunchy implements ServiceClass {
|
|||
files.push({
|
||||
type: 'Video',
|
||||
path: `${tsFile}.ts`,
|
||||
lang: lang
|
||||
lang: lang,
|
||||
isPrimary: isPrimary
|
||||
});
|
||||
dlVideoOnce = true;
|
||||
}
|
||||
|
|
@ -1489,6 +1502,9 @@ export default class Crunchy implements ServiceClass {
|
|||
// collect fonts info
|
||||
// mergers
|
||||
let isMuxed = false;
|
||||
if (options.syncTiming) {
|
||||
await merger.createDelays();
|
||||
}
|
||||
if (bin.MKVmerge) {
|
||||
await merger.merge('mkvmerge', bin.MKVmerge);
|
||||
isMuxed = true;
|
||||
|
|
@ -1657,7 +1673,9 @@ export default class Crunchy implements ServiceClass {
|
|||
data: [
|
||||
{
|
||||
mediaId: item.id,
|
||||
versions: item.versions
|
||||
versions: item.versions,
|
||||
isSubbed: item.is_subbed,
|
||||
isDubbed: item.is_dubbed
|
||||
}
|
||||
],
|
||||
seriesTitle: itemE.items.find(a => !a.series_title.match(/\(\w+ Dub\)/))?.series_title ?? itemE.items[0].series_title.replace(/\(\w+ Dub\)/g, '').trimEnd(),
|
||||
|
|
|
|||
|
|
@ -824,6 +824,9 @@ export default class Hidive implements ServiceClass {
|
|||
// collect fonts info
|
||||
// mergers
|
||||
let isMuxed = false;
|
||||
if (options.syncTiming) {
|
||||
await merger.createDelays();
|
||||
}
|
||||
if (bin.MKVmerge) {
|
||||
await merger.merge('mkvmerge', bin.MKVmerge);
|
||||
isMuxed = true;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ let argvC: {
|
|||
removeBumpers: boolean;
|
||||
originalFontSize: boolean;
|
||||
keepAllVideos: boolean;
|
||||
syncTiming: boolean;
|
||||
};
|
||||
|
||||
export type ArgvType = typeof argvC;
|
||||
|
|
|
|||
|
|
@ -419,6 +419,20 @@ const args: TAppArg<boolean|number|string|unknown[]>[] = [
|
|||
default: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'syncTiming',
|
||||
group: 'mux',
|
||||
describe: 'Attempts to sync timing for multi-dub downloads EXPERIMENTAL',
|
||||
docDescribe: 'In enabled attempts to sync timing for multi-dub downloads.'
|
||||
+ '\nNOTE: This is currently experimental and syncs audio and subtitles, though subtitles has a lot of guesswork'
|
||||
+ '\nIf you find bugs with this, please report it in the discord or github',
|
||||
service: ['crunchy','hidive'],
|
||||
type: 'boolean',
|
||||
usage: '',
|
||||
default: {
|
||||
default: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'skipmux',
|
||||
describe: 'Skip muxing video, audio and subtitles',
|
||||
|
|
|
|||
|
|
@ -6,16 +6,22 @@ import { LanguageItem } from './module.langsData';
|
|||
import { AvailableMuxer } from './module.args';
|
||||
import { exec } from './sei-helper-fixes';
|
||||
import { console } from './log';
|
||||
import ffprobe from 'ffprobe';
|
||||
import ffprobeStatic from 'ffprobe-static';
|
||||
|
||||
export type MergerInput = {
|
||||
path: string,
|
||||
lang: LanguageItem
|
||||
lang: LanguageItem,
|
||||
duration?: number,
|
||||
delay?: number,
|
||||
isPrimary?: boolean,
|
||||
}
|
||||
|
||||
export type SubtitleInput = {
|
||||
language: LanguageItem,
|
||||
file: string,
|
||||
closedCaption?: boolean
|
||||
closedCaption?: boolean,
|
||||
delay?: number
|
||||
}
|
||||
|
||||
export type Font = keyof typeof fontFamilies;
|
||||
|
|
@ -58,6 +64,43 @@ class Merger {
|
|||
this.options.videoTitle = this.options.videoTitle.replace(/"/g, '\'');
|
||||
}
|
||||
|
||||
public async createDelays() {
|
||||
//Don't bother scanning it if there is only 1 vna stream
|
||||
if (this.options.videoAndAudio.length > 1) {
|
||||
const vnas = this.options.videoAndAudio;
|
||||
//get and set durations on each videoAndAudio Stream
|
||||
for (const [vnaIndex, vna] of vnas.entries()) {
|
||||
const streamInfo = await ffprobe(vna.path, { path: ffprobeStatic.path });
|
||||
const videoInfo = streamInfo.streams.filter(stream => stream.codec_type == 'video');
|
||||
vnas[vnaIndex].duration = videoInfo[0].duration;
|
||||
}
|
||||
//Sort videoAndAudio streams by duration (shortest first)
|
||||
vnas.sort((a,b) => {
|
||||
if (!a.duration || !b.duration) return -1;
|
||||
return a.duration - b.duration;
|
||||
});
|
||||
//Set Delays
|
||||
const shortestDuration = vnas[0].duration;
|
||||
for (const [vnaIndex, vna] of vnas.entries()) {
|
||||
//Don't calculate the shortestDuration track
|
||||
if (vnaIndex == 0) continue;
|
||||
if (vna.duration && shortestDuration) {
|
||||
//Calculate the tracks delay
|
||||
vna.delay = Math.ceil((vna.duration-shortestDuration) * 1000) / 1000;
|
||||
//TODO: set primary language for audio so it can be used to determine which track needs the delay
|
||||
//The above is a problem in the event that it isn't the dub that needs the delay, but rather the sub.
|
||||
//Alternatively: Might not work: it could be checked if there are multiple of the same video language, and if there is
|
||||
//more than 1 of the same video language, then do the subtitle delay on CC, else normal language.
|
||||
const subtitles = this.options.subtitles.filter(sub => sub.language.code == vna.lang.code);
|
||||
for (const [subIndex, sub] of subtitles.entries()) {
|
||||
if (vna.isPrimary) subtitles[subIndex].delay = vna.delay;
|
||||
else if (sub.closedCaption) subtitles[subIndex].delay = vna.delay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FFmpeg() : string {
|
||||
const args: string[] = [];
|
||||
const metaData: string[] = [];
|
||||
|
|
@ -67,6 +110,11 @@ class Merger {
|
|||
let hasVideo = false;
|
||||
|
||||
for (const vid of this.options.videoAndAudio) {
|
||||
if (vid.delay && hasVideo) {
|
||||
args.push(
|
||||
`-itsoffset -${Math.ceil(vid.delay*1000)}ms`
|
||||
);
|
||||
}
|
||||
args.push(`-i "${vid.path}"`);
|
||||
if (!hasVideo || this.options.keepAllVideos) {
|
||||
metaData.push(`-map ${index}:a -map ${index}:v`);
|
||||
|
|
@ -101,6 +149,11 @@ class Merger {
|
|||
|
||||
for (const index in this.options.subtitles) {
|
||||
const sub = this.options.subtitles[index];
|
||||
if (sub.delay) {
|
||||
args.push(
|
||||
`-itsoffset -${Math.ceil(sub.delay*1000)}ms`
|
||||
);
|
||||
}
|
||||
args.push(`-i "${sub.file}"`);
|
||||
}
|
||||
|
||||
|
|
@ -164,6 +217,11 @@ class Merger {
|
|||
for (const vid of this.options.videoAndAudio) {
|
||||
const audioTrackNum = this.options.inverseTrackOrder ? '0' : '1';
|
||||
const videoTrackNum = this.options.inverseTrackOrder ? '1' : '0';
|
||||
if (vid.delay) {
|
||||
args.push(
|
||||
`--sync ${audioTrackNum}:-${Math.ceil(vid.delay*1000)}`
|
||||
);
|
||||
}
|
||||
if (!hasVideo || this.options.keepAllVideos) {
|
||||
args.push(
|
||||
`--video-tracks ${videoTrackNum}`,
|
||||
|
|
@ -213,6 +271,11 @@ class Merger {
|
|||
|
||||
if (this.options.subtitles.length > 0) {
|
||||
for (const subObj of this.options.subtitles) {
|
||||
if (subObj.delay) {
|
||||
args.push(
|
||||
`--sync 0:-${Math.ceil(subObj.delay*1000)}`
|
||||
);
|
||||
}
|
||||
args.push('--track-name', `0:"${(subObj.language.language || subObj.language.name) + `${subObj.closedCaption === true ? ` ${this.options.ccTag}` : ''}`}"`);
|
||||
args.push('--language', `0:"${subObj.language.code}"`);
|
||||
//TODO: look into making Closed Caption default if it's the only sub of the default language downloaded
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "multi-downloader-nx",
|
||||
"short_name": "aniDL",
|
||||
"version": "4.3.0b8",
|
||||
"version": "4.3.0",
|
||||
"description": "Downloader for Crunchyroll, Funimation, or Hidive via CLI or GUI",
|
||||
"keywords": [
|
||||
"download",
|
||||
|
|
@ -50,6 +50,8 @@
|
|||
"dotenv": "^16.3.1",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"express": "^4.18.2",
|
||||
"ffprobe": "^1.1.2",
|
||||
"ffprobe-static": "^3.1.0",
|
||||
"form-data": "^4.0.0",
|
||||
"fs-extra": "^11.1.1",
|
||||
"got": "^11.8.6",
|
||||
|
|
@ -67,6 +69,8 @@
|
|||
"devDependencies": {
|
||||
"@types/cors": "^2.8.13",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/ffprobe": "^1.1.4",
|
||||
"@types/ffprobe-static": "^2.0.1",
|
||||
"@types/fs-extra": "^11.0.1",
|
||||
"@types/node": "^18.15.11",
|
||||
"@types/ws": "^8.5.5",
|
||||
|
|
|
|||
|
|
@ -29,6 +29,12 @@ dependencies:
|
|||
express:
|
||||
specifier: ^4.18.2
|
||||
version: 4.18.2
|
||||
ffprobe:
|
||||
specifier: ^1.1.2
|
||||
version: 1.1.2
|
||||
ffprobe-static:
|
||||
specifier: ^3.1.0
|
||||
version: 3.1.0
|
||||
form-data:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0
|
||||
|
|
@ -76,6 +82,12 @@ devDependencies:
|
|||
'@types/express':
|
||||
specifier: ^4.17.17
|
||||
version: 4.17.17
|
||||
'@types/ffprobe':
|
||||
specifier: ^1.1.4
|
||||
version: 1.1.4
|
||||
'@types/ffprobe-static':
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1
|
||||
'@types/fs-extra':
|
||||
specifier: ^11.0.1
|
||||
version: 11.0.1
|
||||
|
|
@ -1845,6 +1857,14 @@ packages:
|
|||
'@types/serve-static': 1.15.1
|
||||
dev: true
|
||||
|
||||
/@types/ffprobe-static@2.0.1:
|
||||
resolution: {integrity: sha512-V5CrKUfms0lBGSXliKmKzSFFZWgJusQks1YfjRI/+2dXFF+aK7qBAarCe/ryYHQI44jYQX7xtlgH0fCuJepuGQ==}
|
||||
dev: true
|
||||
|
||||
/@types/ffprobe@1.1.4:
|
||||
resolution: {integrity: sha512-gtfU+bD4FDoF1S2ybmIWEIz0K5ijeHpi+CgJUtXl3FTGnf+61HmsZksqDn8M9M9lRJU9SRyMLt5yrIwUSep4Uw==}
|
||||
dev: true
|
||||
|
||||
/@types/fs-extra@11.0.1:
|
||||
resolution: {integrity: sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA==}
|
||||
dependencies:
|
||||
|
|
@ -2214,6 +2234,14 @@ packages:
|
|||
url-toolkit: 2.2.5
|
||||
dev: false
|
||||
|
||||
/JSONStream@1.3.5:
|
||||
resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
jsonparse: 1.3.1
|
||||
through: 2.3.8
|
||||
dev: false
|
||||
|
||||
/accepts@1.3.8:
|
||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
|
@ -2449,7 +2477,6 @@ packages:
|
|||
|
||||
/base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
dev: true
|
||||
|
||||
/bl@4.1.0:
|
||||
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
|
||||
|
|
@ -2457,7 +2484,6 @@ packages:
|
|||
buffer: 5.7.1
|
||||
inherits: 2.0.4
|
||||
readable-stream: 3.6.2
|
||||
dev: true
|
||||
|
||||
/body-parser@1.20.1:
|
||||
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
|
||||
|
|
@ -2521,7 +2547,6 @@ packages:
|
|||
dependencies:
|
||||
base64-js: 1.5.1
|
||||
ieee754: 1.2.1
|
||||
dev: true
|
||||
|
||||
/bytes@3.1.2:
|
||||
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
||||
|
|
@ -2822,6 +2847,12 @@ packages:
|
|||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/deferential@1.0.0:
|
||||
resolution: {integrity: sha512-QyFNvptDP8bypD6WK6ZOXFSBHN6CFLZmQ59QyvRGDvN9+DoX01mxw28QrJwSVPrrwnMWqHgTRiXybH6Y0cBbWw==}
|
||||
dependencies:
|
||||
native-promise-only: 0.8.1
|
||||
dev: false
|
||||
|
||||
/define-lazy-prop@2.0.0:
|
||||
resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
|
||||
engines: {node: '>=8'}
|
||||
|
|
@ -3492,6 +3523,18 @@ packages:
|
|||
dependencies:
|
||||
reusify: 1.0.4
|
||||
|
||||
/ffprobe-static@3.1.0:
|
||||
resolution: {integrity: sha512-Dvpa9uhVMOYivhHKWLGDoa512J751qN1WZAIO+Xw4L/mrUSPxS4DApzSUDbCFE/LUq2+xYnznEahTd63AqBSpA==}
|
||||
dev: false
|
||||
|
||||
/ffprobe@1.1.2:
|
||||
resolution: {integrity: sha512-a+oTbhyeM7Z8PRy+mpzmVUAnATZT7z4BO94HSKeqHupdmjiKZ1djzcZkyoyXA21zCOCG7oVRrsBMmvvtmzoz4g==}
|
||||
dependencies:
|
||||
JSONStream: 1.3.5
|
||||
bl: 4.1.0
|
||||
deferential: 1.0.0
|
||||
dev: false
|
||||
|
||||
/file-entry-cache@6.0.1:
|
||||
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
|
||||
engines: {node: ^10.12.0 || >=12.0.0}
|
||||
|
|
@ -3825,7 +3868,6 @@ packages:
|
|||
|
||||
/ieee754@1.2.1:
|
||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||
dev: true
|
||||
|
||||
/ignore@5.2.4:
|
||||
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
|
||||
|
|
@ -4103,6 +4145,11 @@ packages:
|
|||
optionalDependencies:
|
||||
graceful-fs: 4.2.11
|
||||
|
||||
/jsonparse@1.3.1:
|
||||
resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
|
||||
engines: {'0': node >= 0.2.0}
|
||||
dev: false
|
||||
|
||||
/jsx-ast-utils@3.3.3:
|
||||
resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==}
|
||||
engines: {node: '>=4.0'}
|
||||
|
|
@ -4306,6 +4353,10 @@ packages:
|
|||
resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
|
||||
dev: true
|
||||
|
||||
/native-promise-only@0.8.1:
|
||||
resolution: {integrity: sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==}
|
||||
dev: false
|
||||
|
||||
/natural-compare-lite@1.4.0:
|
||||
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
|
||||
dev: true
|
||||
|
|
@ -4705,7 +4756,6 @@ packages:
|
|||
inherits: 2.0.4
|
||||
string_decoder: 1.3.0
|
||||
util-deprecate: 1.0.2
|
||||
dev: true
|
||||
|
||||
/regenerate-unicode-properties@10.1.0:
|
||||
resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==}
|
||||
|
|
@ -5015,7 +5065,6 @@ packages:
|
|||
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
dev: true
|
||||
|
||||
/strip-ansi@6.0.1:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
|
|
@ -5075,6 +5124,10 @@ packages:
|
|||
/text-table@0.2.0:
|
||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||
|
||||
/through@2.3.8:
|
||||
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
|
||||
dev: false
|
||||
|
||||
/to-fast-properties@2.0.0:
|
||||
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
||||
engines: {node: '>=4'}
|
||||
|
|
@ -5272,7 +5325,6 @@ packages:
|
|||
|
||||
/util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
dev: true
|
||||
|
||||
/utils-merge@1.0.1:
|
||||
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
||||
|
|
|
|||
Loading…
Reference in a new issue