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 30104f8..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[], 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 +314,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 +335,40 @@ 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) { + x.start = previousBufferLine.start; + if (previousBufferLine.style == x.style) { + buffer.pop(); + x.text = previousBufferLine.text + '\\N' + x.text; + } + } 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 **`, @@ -438,11 +484,12 @@ function toSubTime(str: string) { return n.slice(0, 3).join(':') + '.' + n[3]; } -export default function vtt2ass(group: string | undefined, xFontSize: number | undefined, vttStr: string, cssStr: string, timeMargin?: number, replaceFont?: string) { +export default function vtt2ass(group: string | undefined, xFontSize: number | undefined, vttStr: string, cssStr: string, timeMargin?: number, replaceFont?: string, combineLines?: boolean) { relGroup = group ?? ''; fontSize = xFontSize && xFontSize > 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 = '';