From 6bf7e9721f0e14810364c8a8ff9e70b7158c037c Mon Sep 17 00:00:00 2001 From: IONI0 Date: Tue, 2 Apr 2024 16:45:29 +1100 Subject: [PATCH 1/2] Fixes/enchancements for vtt2ass with new Hidive Q styles --- modules/module.vtt2ass.ts | 91 ++++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 24 deletions(-) diff --git a/modules/module.vtt2ass.ts b/modules/module.vtt2ass.ts index 30104f8..f790eac 100644 --- a/modules/module.vtt2ass.ts +++ b/modules/module.vtt2ass.ts @@ -239,6 +239,42 @@ function timestampToCentiseconds(timestamp: string) { return 360000 * hour + 6000 * minute + 100 * second + centisecond; } +function combineLines(events: string[]): string[] { + // This function is for combining adjacent lines with same information + const newLines: string[] = []; + for (const currentLine of events) { + let hasCombined: boolean = false; + // Check previous 7 elements, arbritary lookback amount + for (let j = 1; j < 8 && j < newLines.length; j++) { + const checkLine = newLines[newLines.length - j]; + let checkLineSplit = checkLine.split(','); + let currentLineSplit = currentLine.split(','); + // 1 = start, 2 = end, 3 = style, 9+ = text + if (checkLineSplit.slice(9).join(',') == currentLineSplit.slice(9).join(',') && + checkLineSplit[3] == currentLineSplit[3] && + checkLineSplit[2] == currentLineSplit[1] + ) { + checkLineSplit[2] = currentLineSplit[2]; + newLines[newLines.length - j] = checkLineSplit.join(','); + hasCombined = true; + break; + } + } + if (!hasCombined) { + newLines.push(currentLine); + } + } + return newLines; +} + +function pushBuffer(buffer: ReturnType[], events: string[]) { + buffer.reverse(); + const bufferStrings: string[] = buffer.map(line => + `Dialogue: 1,${line.start},${line.end},${line.style},,0,0,0,,${line.text}`); + events.push(...bufferStrings); + buffer.splice(0,buffer.length); +} + function convert(css: Css, vtt: Vtt[]) { const stylesMap: Record = {}; let ass = [ @@ -274,8 +310,8 @@ function convert(css: Css, vtt: Vtt[]) { song_cap: [], }; const linesMap: Record = {}; - let previousLine: ReturnType | undefined = undefined; - const buffer: string[] = []; + const buffer: ReturnType[] = []; + const captionsBuffer: string[] = []; for (const l in vtt) { const x = convertLine(stylesMap, vtt[l]); if (x.ind !== '' && linesMap[x.ind] !== undefined) { @@ -295,34 +331,41 @@ function convert(css: Css, vtt: Vtt[]) { } /** * What cursed code have I brought upon this land? - * This checks if a subtitle should be multi-line, and if it is, pops the just inserted - * subtitle and the previous subtitle, and merges them into a single subtitle. + * This handles making lines multi-line when neccesary and reverses + * order of subtitles so that they display correctly */ - if (previousLine) { - const previousStart = timestampToCentiseconds(previousLine.start); + if (x.type != 'subtitle') { + // Do nothing + } else if (x.text.includes('\\pos')) { + events['subtitle'].pop(); + captionsBuffer.push(x.res); + } else if (buffer.length > 0) { + const previousBufferLine = buffer[buffer.length - 1]; + const previousStart = timestampToCentiseconds(previousBufferLine.start); const currentStart = timestampToCentiseconds(x.start); - if ( - (currentStart - previousStart) <= 2 && - previousLine.type == x.type && - previousLine.style == x.style && - !previousLine.text.includes('\\pos') && - !x.text.includes('\\pos') - ) { - events[x.type as keyof typeof events].pop(); - const previousLinePop = events[x.type as keyof typeof events].pop(); - events[x.type as keyof typeof events].push(previousLinePop + '\\N'+x.text); - } else if ((currentStart - previousStart) <= 3) { - const currentLinePop = events[x.type as keyof typeof events].pop(); - const previousLinePop = events[previousLine.type as keyof typeof events].pop(); - buffer.push(previousLinePop as string, currentLinePop as string); - } else if ((currentStart - previousStart) >= 3 && buffer.length > 0) { - events[x.type as keyof typeof events].push(...buffer.reverse()); - buffer.splice(0,buffer.length); + events['subtitle'].pop(); + if ((currentStart - previousStart) <= 2) { + if (previousBufferLine.style == x.style) { + buffer.pop(); + x.text = previousBufferLine.text + '\\N' + x.text; + } else { + x.start = previousBufferLine.start; + } + } else { + pushBuffer(buffer, events['subtitle']); } + buffer.push(x); + } + else { + events['subtitle'].pop(); + buffer.push(x); } - previousLine = x; } + pushBuffer(buffer, events['subtitle']); + events['subtitle'].push(...captionsBuffer); + events['subtitle'] = combineLines(events['subtitle']); + if (events.subtitle.length > 0) { ass = ass.concat( //`Comment: 0,0:00:00.00,0:00:00.00,${defaultStyleName},,0,0,0,,** Subtitles **`, -- 2.45.2 From 2885913205e77f83f92680b0925b6c848d6c14c2 Mon Sep 17 00:00:00 2001 From: IONI0 Date: Thu, 4 Apr 2024 09:42:41 +1100 Subject: [PATCH 2/2] Fix Eslint errors, logic error, and add combineLines argument --- hidive.ts | 4 ++-- modules/module.app-args.ts | 1 + modules/module.args.ts | 9 +++++++++ modules/module.vtt2ass.ts | 22 +++++++++++++--------- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/hidive.ts b/hidive.ts index 1b632cf..b2d63f4 100644 --- a/hidive.ts +++ b/hidive.ts @@ -1424,7 +1424,7 @@ export default class Hidive implements ServiceClass { if (getVttContent.ok && getVttContent.res) { console.info(`Subtitle Downloaded: ${sub.url}`); //vttConvert(getVttContent.res.body, false, subLang.name, fontSize); - const sBody = vtt2ass(undefined, chosenFontSize, getVttContent.res.body, '', subsMargin, options.fontName); + const sBody = vtt2ass(undefined, chosenFontSize, getVttContent.res.body, '', subsMargin, options.fontName, options.combineLines); sxData.title = `${subLang.language} / ${sxData.title}`; sxData.fonts = fontsData.assFonts(sBody) as Font[]; fs.writeFileSync(sxData.path, sBody); @@ -1678,7 +1678,7 @@ export default class Hidive implements ServiceClass { if (getCssContent.ok && getVttContent.ok && getCssContent.res && getVttContent.res) { console.info(`Subtitle Downloaded: ${await this.genSubsUrl('vtt', subsXUrl)}`); //vttConvert(getVttContent.res.body, false, subLang.name, fontSize); - const sBody = vtt2ass(undefined, chosenFontSize, getVttContent.res.body, getCssContent.res.body, subsMargin, options.fontName); + const sBody = vtt2ass(undefined, chosenFontSize, getVttContent.res.body, getCssContent.res.body, subsMargin, options.fontName, options.combineLines); sxData.title = `${subLang.language} / ${sxData.title}`; sxData.fonts = fontsData.assFonts(sBody) as Font[]; fs.writeFileSync(sxData.path, sBody); diff --git a/modules/module.app-args.ts b/modules/module.app-args.ts index 16e48cf..00014c8 100644 --- a/modules/module.app-args.ts +++ b/modules/module.app-args.ts @@ -48,6 +48,7 @@ let argvC: { dubLang: string[]; all: boolean; fontSize: number; + combineLines: boolean; allDubs: boolean; timeout: number; waittime: number; diff --git a/modules/module.args.ts b/modules/module.args.ts index 4b49eb8..daf2098 100644 --- a/modules/module.args.ts +++ b/modules/module.args.ts @@ -391,6 +391,15 @@ const args: TAppArg[] = [ type: 'number', usage: '${fontSize}' }, + { + name: 'combineLines', + describe: 'Merge adjacent lines with same style and text', + docDescribe: 'If selected, will prevent a line from shifting downwards', + group: 'dl', + service: ['hidive'], + type: 'boolean', + usage: '' + }, { name: 'allDubs', describe: 'If selected, all available dubs will get downloaded', diff --git a/modules/module.vtt2ass.ts b/modules/module.vtt2ass.ts index f790eac..b85668d 100644 --- a/modules/module.vtt2ass.ts +++ b/modules/module.vtt2ass.ts @@ -13,6 +13,7 @@ let relGroup = ''; let fontSize = 0; let tmMrg = 0; let rFont = ''; +let doCombineLines = false; type Css = Record 0 ? xFontSize : 34; // 1em to pix tmMrg = timeMargin ? timeMargin : 0; // rFont = replaceFont ? replaceFont : rFont; + doCombineLines = combineLines ? combineLines : doCombineLines; if (vttStr.match(/::cue(?:.(.+)\) *)?{([^}]+)}/g)) { const cssLines = []; let defaultCss = ''; -- 2.45.2