@storyteller-platform/align 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +3 -0
  3. package/dist/align/align.cjs +525 -0
  4. package/dist/align/align.d.cts +58 -0
  5. package/dist/align/align.d.ts +58 -0
  6. package/dist/align/align.js +458 -0
  7. package/dist/align/fuzzy.cjs +164 -0
  8. package/dist/align/fuzzy.d.cts +6 -0
  9. package/dist/align/fuzzy.d.ts +6 -0
  10. package/dist/align/fuzzy.js +141 -0
  11. package/dist/align/getSentenceRanges.cjs +304 -0
  12. package/dist/align/getSentenceRanges.d.cts +31 -0
  13. package/dist/align/getSentenceRanges.d.ts +31 -0
  14. package/dist/align/getSentenceRanges.js +277 -0
  15. package/dist/align/parse.cjs +63 -0
  16. package/dist/align/parse.d.cts +30 -0
  17. package/dist/align/parse.d.ts +30 -0
  18. package/dist/align/parse.js +51 -0
  19. package/dist/chunk-BIEQXUOY.js +50 -0
  20. package/dist/cli/bin.cjs +368 -0
  21. package/dist/cli/bin.d.cts +1 -0
  22. package/dist/cli/bin.d.ts +1 -0
  23. package/dist/cli/bin.js +319 -0
  24. package/dist/common/ffmpeg.cjs +232 -0
  25. package/dist/common/ffmpeg.d.cts +33 -0
  26. package/dist/common/ffmpeg.d.ts +33 -0
  27. package/dist/common/ffmpeg.js +196 -0
  28. package/dist/common/logging.cjs +45 -0
  29. package/dist/common/logging.d.cts +5 -0
  30. package/dist/common/logging.d.ts +5 -0
  31. package/dist/common/logging.js +12 -0
  32. package/dist/common/parse.cjs +73 -0
  33. package/dist/common/parse.d.cts +28 -0
  34. package/dist/common/parse.d.ts +28 -0
  35. package/dist/common/parse.js +56 -0
  36. package/dist/common/shell.cjs +30 -0
  37. package/dist/common/shell.d.cts +3 -0
  38. package/dist/common/shell.d.ts +3 -0
  39. package/dist/common/shell.js +7 -0
  40. package/dist/index.cjs +37 -0
  41. package/dist/index.d.cts +12 -0
  42. package/dist/index.d.ts +12 -0
  43. package/dist/index.js +11 -0
  44. package/dist/markup/__tests__/markup.test.cjs +464 -0
  45. package/dist/markup/__tests__/markup.test.d.cts +2 -0
  46. package/dist/markup/__tests__/markup.test.d.ts +2 -0
  47. package/dist/markup/__tests__/markup.test.js +441 -0
  48. package/dist/markup/markup.cjs +316 -0
  49. package/dist/markup/markup.d.cts +24 -0
  50. package/dist/markup/markup.d.ts +24 -0
  51. package/dist/markup/markup.js +254 -0
  52. package/dist/markup/parse.cjs +55 -0
  53. package/dist/markup/parse.d.cts +17 -0
  54. package/dist/markup/parse.d.ts +17 -0
  55. package/dist/markup/parse.js +43 -0
  56. package/dist/markup/segmentation.cjs +87 -0
  57. package/dist/markup/segmentation.d.cts +8 -0
  58. package/dist/markup/segmentation.d.ts +8 -0
  59. package/dist/markup/segmentation.js +67 -0
  60. package/dist/markup/semantics.cjs +79 -0
  61. package/dist/markup/semantics.d.cts +6 -0
  62. package/dist/markup/semantics.d.ts +6 -0
  63. package/dist/markup/semantics.js +53 -0
  64. package/dist/process/AudioEncoding.cjs +16 -0
  65. package/dist/process/AudioEncoding.d.cts +8 -0
  66. package/dist/process/AudioEncoding.d.ts +8 -0
  67. package/dist/process/AudioEncoding.js +0 -0
  68. package/dist/process/__tests__/processAudiobook.test.cjs +232 -0
  69. package/dist/process/__tests__/processAudiobook.test.d.cts +2 -0
  70. package/dist/process/__tests__/processAudiobook.test.d.ts +2 -0
  71. package/dist/process/__tests__/processAudiobook.test.js +209 -0
  72. package/dist/process/mime.cjs +43 -0
  73. package/dist/process/mime.d.cts +3 -0
  74. package/dist/process/mime.d.ts +3 -0
  75. package/dist/process/mime.js +24 -0
  76. package/dist/process/parse.cjs +84 -0
  77. package/dist/process/parse.d.cts +28 -0
  78. package/dist/process/parse.d.ts +28 -0
  79. package/dist/process/parse.js +73 -0
  80. package/dist/process/processAudiobook.cjs +220 -0
  81. package/dist/process/processAudiobook.d.cts +24 -0
  82. package/dist/process/processAudiobook.d.ts +24 -0
  83. package/dist/process/processAudiobook.js +166 -0
  84. package/dist/process/ranges.cjs +203 -0
  85. package/dist/process/ranges.d.cts +15 -0
  86. package/dist/process/ranges.d.ts +15 -0
  87. package/dist/process/ranges.js +137 -0
  88. package/dist/transcribe/parse.cjs +149 -0
  89. package/dist/transcribe/parse.d.cts +114 -0
  90. package/dist/transcribe/parse.d.ts +114 -0
  91. package/dist/transcribe/parse.js +143 -0
  92. package/dist/transcribe/transcribe.cjs +400 -0
  93. package/dist/transcribe/transcribe.d.cts +41 -0
  94. package/dist/transcribe/transcribe.d.ts +41 -0
  95. package/dist/transcribe/transcribe.js +330 -0
  96. package/package.json +96 -0
@@ -0,0 +1,368 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
10
+ var __typeError = (msg) => {
11
+ throw TypeError(msg);
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __using = (stack, value, async) => {
30
+ if (value != null) {
31
+ if (typeof value !== "object" && typeof value !== "function") __typeError("Object expected");
32
+ var dispose, inner;
33
+ if (async) dispose = value[__knownSymbol("asyncDispose")];
34
+ if (dispose === void 0) {
35
+ dispose = value[__knownSymbol("dispose")];
36
+ if (async) inner = dispose;
37
+ }
38
+ if (typeof dispose !== "function") __typeError("Object not disposable");
39
+ if (inner) dispose = function() {
40
+ try {
41
+ inner.call(this);
42
+ } catch (e) {
43
+ return Promise.reject(e);
44
+ }
45
+ };
46
+ stack.push([async, dispose, value]);
47
+ } else if (async) {
48
+ stack.push([async]);
49
+ }
50
+ return value;
51
+ };
52
+ var __callDispose = (stack, error, hasError) => {
53
+ var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
54
+ return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
55
+ };
56
+ var fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e);
57
+ var next = (it) => {
58
+ while (it = stack.pop()) {
59
+ try {
60
+ var result = it[1] && it[1].call(it[2]);
61
+ if (it[0]) return Promise.resolve(result).then(next, (e) => (fail(e), next()));
62
+ } catch (e) {
63
+ fail(e);
64
+ }
65
+ }
66
+ if (hasError) throw error;
67
+ };
68
+ return next();
69
+ };
70
+ var import_node_crypto = require("node:crypto");
71
+ var import_node_fs = require("node:fs");
72
+ var os = __toESM(require("node:os"), 1);
73
+ var import_node_path = require("node:path");
74
+ var import_core = require("@optique/core");
75
+ var import_run = require("@optique/run");
76
+ var import_valueparser = require("@optique/run/valueparser");
77
+ var import_cli_progress = require("cli-progress");
78
+ var import_epub = require("@storyteller-platform/epub");
79
+ var import_package = __toESM(require("../../package.json"), 1);
80
+ var import_align = require("../align/align.cjs");
81
+ var import_parse = require("../align/parse.cjs");
82
+ var import_logging = require("../common/logging.cjs");
83
+ var import_parse2 = require("../common/parse.cjs");
84
+ var import_markup = require("../markup/markup.cjs");
85
+ var import_parse3 = require("../markup/parse.cjs");
86
+ var import_parse4 = require("../process/parse.cjs");
87
+ var import_processAudiobook = require("../process/processAudiobook.cjs");
88
+ var import_parse5 = require("../transcribe/parse.cjs");
89
+ var import_transcribe = require("../transcribe/transcribe.cjs");
90
+ const pipelineCommand = (0, import_core.merge)(
91
+ (0, import_core.object)({
92
+ action: (0, import_core.constant)("pipeline"),
93
+ processedAudio: (0, import_core.optional)(
94
+ (0, import_core.option)("--processed-audio", (0, import_valueparser.path)({ type: "directory" }))
95
+ ),
96
+ transcriptions: (0, import_core.optional)(
97
+ (0, import_core.option)("--transcriptions", (0, import_valueparser.path)({ type: "directory" }))
98
+ ),
99
+ markedup: (0, import_core.optional)(
100
+ (0, import_core.option)("--markedup", (0, import_valueparser.path)({ type: "file", extensions: [".epub"] }))
101
+ ),
102
+ parallelTranscodes: (0, import_core.withDefault)(
103
+ (0, import_core.option)("--parallel-transcodes", (0, import_core.integer)()),
104
+ 1
105
+ ),
106
+ parallelTranscribes: (0, import_core.withDefault)(
107
+ (0, import_core.option)("--parallel-transcribes", (0, import_core.integer)()),
108
+ 1
109
+ ),
110
+ output: (0, import_core.option)("--output", (0, import_valueparser.path)({ type: "file", extensions: [".epub"] }))
111
+ }),
112
+ import_parse4.processParser,
113
+ (0, import_core.group)("Transcription", import_parse5.transcribeParser),
114
+ import_parse2.granularityParser,
115
+ import_parse2.languageParser,
116
+ import_parse.alignParser,
117
+ import_parse2.loggingParser
118
+ );
119
+ const parser = (0, import_core.or)(
120
+ import_parse4.processCommand,
121
+ import_parse5.transcribeCommand,
122
+ import_parse3.markupCommand,
123
+ import_parse.alignCommand,
124
+ pipelineCommand
125
+ );
126
+ async function main() {
127
+ var _stack2 = [];
128
+ try {
129
+ const parsed = (0, import_run.run)(parser, {
130
+ showChoices: true,
131
+ showDefault: true,
132
+ version: import_package.default.version,
133
+ completion: "command",
134
+ help: "both",
135
+ description: import_core.message`A CLI to automatically align audiobooks and EPUB files, producing EPUBs with Media Overlays.`
136
+ });
137
+ const controller = new AbortController();
138
+ let progressBar;
139
+ function resetProgressBar() {
140
+ progressBar == null ? void 0 : progressBar.stop();
141
+ progressBar = new import_cli_progress.SingleBar(
142
+ { etaBuffer: 4, hideCursor: null, noTTYOutput: !process.stderr.isTTY },
143
+ import_cli_progress.Presets.shades_classic
144
+ );
145
+ }
146
+ function startProgressBar() {
147
+ if (!parsed.noProgress && parsed.logLevel === "silent") {
148
+ progressBar.start(100, 0);
149
+ }
150
+ }
151
+ resetProgressBar();
152
+ process.on("SIGINT", () => {
153
+ controller.abort();
154
+ process.exit();
155
+ });
156
+ const stack = __using(_stack2, new DisposableStack());
157
+ stack.defer(() => {
158
+ progressBar.stop();
159
+ });
160
+ startProgressBar();
161
+ const logger = (0, import_logging.createLogger)(parsed.logLevel);
162
+ switch (parsed.action) {
163
+ case "process": {
164
+ const timing = await (0, import_processAudiobook.processAudiobook)(parsed.input, parsed.output, {
165
+ encoding: { codec: parsed.codec, bitrate: parsed.bitrate },
166
+ maxLength: parsed.maxLength / 60,
167
+ parallelism: parsed.parallelism,
168
+ signal: controller.signal,
169
+ logger,
170
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
171
+ onProgress: (progress) => {
172
+ progressBar.update(Math.floor(progress * 100));
173
+ }
174
+ }
175
+ });
176
+ if (parsed.time) {
177
+ timing.print("Process audiobook");
178
+ }
179
+ break;
180
+ }
181
+ case "transcribe": {
182
+ const timing = await (0, import_transcribe.transcribe)(
183
+ parsed.input,
184
+ parsed.output,
185
+ parsed.language ?? new Intl.Locale("en-US"),
186
+ {
187
+ ...parsed,
188
+ signal: controller.signal,
189
+ logger,
190
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
191
+ onProgress: (progress) => {
192
+ progressBar.update(Math.floor(progress * 100));
193
+ }
194
+ }
195
+ }
196
+ );
197
+ if (parsed.time) {
198
+ timing.print("Process audiobook");
199
+ }
200
+ break;
201
+ }
202
+ case "markup": {
203
+ const timing = await (0, import_markup.markup)(parsed.input, parsed.output, {
204
+ primaryLocale: parsed.language ?? new Intl.Locale("en-US"),
205
+ granularity: parsed.granularity,
206
+ logger,
207
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
208
+ onProgress: (progress) => {
209
+ progressBar.update(Math.floor(progress * 100));
210
+ }
211
+ }
212
+ });
213
+ if (parsed.time) {
214
+ timing.print("Mark up EPUB");
215
+ }
216
+ break;
217
+ }
218
+ case "align": {
219
+ const timing = await (0, import_align.align)(
220
+ parsed.epub,
221
+ parsed.output,
222
+ parsed.transcriptions,
223
+ parsed.audiobook,
224
+ {
225
+ granularity: parsed.granularity,
226
+ primaryLocale: parsed.language,
227
+ logger,
228
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
229
+ onProgress: (progress) => {
230
+ progressBar.update(Math.floor(progress * 100));
231
+ }
232
+ }
233
+ }
234
+ );
235
+ if (parsed.time) {
236
+ timing.print("Align EPUB and audiobook");
237
+ }
238
+ break;
239
+ }
240
+ case "pipeline": {
241
+ var _stack = [];
242
+ try {
243
+ const epub = __using(_stack, await import_epub.Epub.from(parsed.epub));
244
+ const primaryLocale = parsed.language ?? await epub.getLanguage() ?? new Intl.Locale("en-US");
245
+ const processedAudio = parsed.processedAudio ?? (0, import_node_path.join)(os.tmpdir(), `stalign-processed-${(0, import_node_crypto.randomUUID)()}`);
246
+ if (!parsed.processedAudio) {
247
+ stack.defer(() => {
248
+ (0, import_node_fs.rmSync)(processedAudio, { recursive: true, force: true });
249
+ });
250
+ }
251
+ const processTiming = await (0, import_processAudiobook.processAudiobook)(
252
+ parsed.audiobook,
253
+ processedAudio,
254
+ {
255
+ encoding: {
256
+ codec: parsed.codec,
257
+ bitrate: parsed.bitrate
258
+ },
259
+ maxLength: parsed.maxLength / 60,
260
+ parallelism: parsed.parallelTranscodes,
261
+ signal: controller.signal,
262
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
263
+ onProgress: (progress) => {
264
+ progressBar.update(Math.floor(progress * 100));
265
+ }
266
+ }
267
+ }
268
+ );
269
+ resetProgressBar();
270
+ logger.info(
271
+ `Processing audiobook complete, processed files saved to ${processedAudio}.`
272
+ );
273
+ if (parsed.time) {
274
+ processTiming.print();
275
+ }
276
+ logger.info("Transcribing...");
277
+ startProgressBar();
278
+ const transcriptions = parsed.transcriptions ?? (0, import_node_path.join)(os.tmpdir(), `stalign-transcriptions-${(0, import_node_crypto.randomUUID)()}`);
279
+ if (!parsed.transcriptions) {
280
+ stack.defer(() => {
281
+ (0, import_node_fs.rmSync)(transcriptions, { recursive: true, force: true });
282
+ });
283
+ }
284
+ const transcribeTiming = await (0, import_transcribe.transcribe)(
285
+ processedAudio,
286
+ transcriptions,
287
+ primaryLocale,
288
+ {
289
+ ...parsed,
290
+ parallelism: parsed.parallelTranscribes,
291
+ signal: controller.signal,
292
+ logger,
293
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
294
+ onProgress: (progress) => {
295
+ progressBar.update(Math.floor(progress * 100));
296
+ }
297
+ }
298
+ }
299
+ );
300
+ resetProgressBar();
301
+ logger.info(
302
+ `Transcribing audiobook complete, transcriptions saved to ${transcriptions}.`
303
+ );
304
+ if (parsed.time) {
305
+ transcribeTiming.print();
306
+ }
307
+ logger.info("Marking up EPUB...");
308
+ startProgressBar();
309
+ const markedup = parsed.markedup ?? (0, import_node_path.join)(os.tmpdir(), `stalign-markedup-${(0, import_node_crypto.randomUUID)()}.epub`);
310
+ if (!parsed.markedup) {
311
+ stack.defer(() => {
312
+ (0, import_node_fs.rmSync)(markedup, { recursive: true, force: true });
313
+ });
314
+ }
315
+ const markupTiming = await (0, import_markup.markup)(parsed.epub, markedup, {
316
+ granularity: parsed.granularity,
317
+ primaryLocale,
318
+ logger,
319
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
320
+ onProgress: (progress) => {
321
+ progressBar.update(Math.floor(progress * 100));
322
+ }
323
+ }
324
+ });
325
+ resetProgressBar();
326
+ logger.info(`Markup complete, marked up EPUB saved to ${markedup}.`);
327
+ if (parsed.time) {
328
+ markupTiming.print();
329
+ }
330
+ logger.info("Aligning EPUB with audiobook...");
331
+ startProgressBar();
332
+ const alignTiming = await (0, import_align.align)(
333
+ markedup,
334
+ parsed.output,
335
+ transcriptions,
336
+ processedAudio,
337
+ {
338
+ granularity: parsed.granularity,
339
+ primaryLocale,
340
+ logger,
341
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
342
+ onProgress: (progress) => {
343
+ progressBar.update(Math.floor(progress * 100));
344
+ }
345
+ }
346
+ }
347
+ );
348
+ resetProgressBar();
349
+ logger.info(`Alignment complete, aligned EPUB saved to ${parsed.output}`);
350
+ if (parsed.time) {
351
+ alignTiming.print();
352
+ }
353
+ } catch (_) {
354
+ var _error = _, _hasError = true;
355
+ } finally {
356
+ __callDispose(_stack, _error, _hasError);
357
+ }
358
+ }
359
+ }
360
+ } catch (_2) {
361
+ var _error2 = _2, _hasError2 = true;
362
+ } finally {
363
+ __callDispose(_stack2, _error2, _hasError2);
364
+ }
365
+ }
366
+ main().catch((e) => {
367
+ console.error(e);
368
+ });
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,319 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ __callDispose,
4
+ __using
5
+ } from "../chunk-BIEQXUOY.js";
6
+ import { randomUUID } from "node:crypto";
7
+ import { rmSync } from "node:fs";
8
+ import * as os from "node:os";
9
+ import { join } from "node:path";
10
+ import {
11
+ constant,
12
+ group,
13
+ integer,
14
+ merge,
15
+ message,
16
+ object,
17
+ option,
18
+ optional,
19
+ or,
20
+ withDefault
21
+ } from "@optique/core";
22
+ import { run } from "@optique/run";
23
+ import { path } from "@optique/run/valueparser";
24
+ import { Presets, SingleBar } from "cli-progress";
25
+ import { Epub } from "@storyteller-platform/epub";
26
+ import packageJson from "../../package.json";
27
+ import { align } from "../align/align.js";
28
+ import { alignCommand, alignParser } from "../align/parse.js";
29
+ import { createLogger } from "../common/logging.js";
30
+ import {
31
+ granularityParser,
32
+ languageParser,
33
+ loggingParser
34
+ } from "../common/parse.js";
35
+ import { markup } from "../markup/markup.js";
36
+ import { markupCommand } from "../markup/parse.js";
37
+ import { processCommand, processParser } from "../process/parse.js";
38
+ import { processAudiobook } from "../process/processAudiobook.js";
39
+ import { transcribeCommand, transcribeParser } from "../transcribe/parse.js";
40
+ import { transcribe } from "../transcribe/transcribe.js";
41
+ const pipelineCommand = merge(
42
+ object({
43
+ action: constant("pipeline"),
44
+ processedAudio: optional(
45
+ option("--processed-audio", path({ type: "directory" }))
46
+ ),
47
+ transcriptions: optional(
48
+ option("--transcriptions", path({ type: "directory" }))
49
+ ),
50
+ markedup: optional(
51
+ option("--markedup", path({ type: "file", extensions: [".epub"] }))
52
+ ),
53
+ parallelTranscodes: withDefault(
54
+ option("--parallel-transcodes", integer()),
55
+ 1
56
+ ),
57
+ parallelTranscribes: withDefault(
58
+ option("--parallel-transcribes", integer()),
59
+ 1
60
+ ),
61
+ output: option("--output", path({ type: "file", extensions: [".epub"] }))
62
+ }),
63
+ processParser,
64
+ group("Transcription", transcribeParser),
65
+ granularityParser,
66
+ languageParser,
67
+ alignParser,
68
+ loggingParser
69
+ );
70
+ const parser = or(
71
+ processCommand,
72
+ transcribeCommand,
73
+ markupCommand,
74
+ alignCommand,
75
+ pipelineCommand
76
+ );
77
+ async function main() {
78
+ var _stack2 = [];
79
+ try {
80
+ const parsed = run(parser, {
81
+ showChoices: true,
82
+ showDefault: true,
83
+ version: packageJson.version,
84
+ completion: "command",
85
+ help: "both",
86
+ description: message`A CLI to automatically align audiobooks and EPUB files, producing EPUBs with Media Overlays.`
87
+ });
88
+ const controller = new AbortController();
89
+ let progressBar;
90
+ function resetProgressBar() {
91
+ progressBar == null ? void 0 : progressBar.stop();
92
+ progressBar = new SingleBar(
93
+ { etaBuffer: 4, hideCursor: null, noTTYOutput: !process.stderr.isTTY },
94
+ Presets.shades_classic
95
+ );
96
+ }
97
+ function startProgressBar() {
98
+ if (!parsed.noProgress && parsed.logLevel === "silent") {
99
+ progressBar.start(100, 0);
100
+ }
101
+ }
102
+ resetProgressBar();
103
+ process.on("SIGINT", () => {
104
+ controller.abort();
105
+ process.exit();
106
+ });
107
+ const stack = __using(_stack2, new DisposableStack());
108
+ stack.defer(() => {
109
+ progressBar.stop();
110
+ });
111
+ startProgressBar();
112
+ const logger = createLogger(parsed.logLevel);
113
+ switch (parsed.action) {
114
+ case "process": {
115
+ const timing = await processAudiobook(parsed.input, parsed.output, {
116
+ encoding: { codec: parsed.codec, bitrate: parsed.bitrate },
117
+ maxLength: parsed.maxLength / 60,
118
+ parallelism: parsed.parallelism,
119
+ signal: controller.signal,
120
+ logger,
121
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
122
+ onProgress: (progress) => {
123
+ progressBar.update(Math.floor(progress * 100));
124
+ }
125
+ }
126
+ });
127
+ if (parsed.time) {
128
+ timing.print("Process audiobook");
129
+ }
130
+ break;
131
+ }
132
+ case "transcribe": {
133
+ const timing = await transcribe(
134
+ parsed.input,
135
+ parsed.output,
136
+ parsed.language ?? new Intl.Locale("en-US"),
137
+ {
138
+ ...parsed,
139
+ signal: controller.signal,
140
+ logger,
141
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
142
+ onProgress: (progress) => {
143
+ progressBar.update(Math.floor(progress * 100));
144
+ }
145
+ }
146
+ }
147
+ );
148
+ if (parsed.time) {
149
+ timing.print("Process audiobook");
150
+ }
151
+ break;
152
+ }
153
+ case "markup": {
154
+ const timing = await markup(parsed.input, parsed.output, {
155
+ primaryLocale: parsed.language ?? new Intl.Locale("en-US"),
156
+ granularity: parsed.granularity,
157
+ logger,
158
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
159
+ onProgress: (progress) => {
160
+ progressBar.update(Math.floor(progress * 100));
161
+ }
162
+ }
163
+ });
164
+ if (parsed.time) {
165
+ timing.print("Mark up EPUB");
166
+ }
167
+ break;
168
+ }
169
+ case "align": {
170
+ const timing = await align(
171
+ parsed.epub,
172
+ parsed.output,
173
+ parsed.transcriptions,
174
+ parsed.audiobook,
175
+ {
176
+ granularity: parsed.granularity,
177
+ primaryLocale: parsed.language,
178
+ logger,
179
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
180
+ onProgress: (progress) => {
181
+ progressBar.update(Math.floor(progress * 100));
182
+ }
183
+ }
184
+ }
185
+ );
186
+ if (parsed.time) {
187
+ timing.print("Align EPUB and audiobook");
188
+ }
189
+ break;
190
+ }
191
+ case "pipeline": {
192
+ var _stack = [];
193
+ try {
194
+ const epub = __using(_stack, await Epub.from(parsed.epub));
195
+ const primaryLocale = parsed.language ?? await epub.getLanguage() ?? new Intl.Locale("en-US");
196
+ const processedAudio = parsed.processedAudio ?? join(os.tmpdir(), `stalign-processed-${randomUUID()}`);
197
+ if (!parsed.processedAudio) {
198
+ stack.defer(() => {
199
+ rmSync(processedAudio, { recursive: true, force: true });
200
+ });
201
+ }
202
+ const processTiming = await processAudiobook(
203
+ parsed.audiobook,
204
+ processedAudio,
205
+ {
206
+ encoding: {
207
+ codec: parsed.codec,
208
+ bitrate: parsed.bitrate
209
+ },
210
+ maxLength: parsed.maxLength / 60,
211
+ parallelism: parsed.parallelTranscodes,
212
+ signal: controller.signal,
213
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
214
+ onProgress: (progress) => {
215
+ progressBar.update(Math.floor(progress * 100));
216
+ }
217
+ }
218
+ }
219
+ );
220
+ resetProgressBar();
221
+ logger.info(
222
+ `Processing audiobook complete, processed files saved to ${processedAudio}.`
223
+ );
224
+ if (parsed.time) {
225
+ processTiming.print();
226
+ }
227
+ logger.info("Transcribing...");
228
+ startProgressBar();
229
+ const transcriptions = parsed.transcriptions ?? join(os.tmpdir(), `stalign-transcriptions-${randomUUID()}`);
230
+ if (!parsed.transcriptions) {
231
+ stack.defer(() => {
232
+ rmSync(transcriptions, { recursive: true, force: true });
233
+ });
234
+ }
235
+ const transcribeTiming = await transcribe(
236
+ processedAudio,
237
+ transcriptions,
238
+ primaryLocale,
239
+ {
240
+ ...parsed,
241
+ parallelism: parsed.parallelTranscribes,
242
+ signal: controller.signal,
243
+ logger,
244
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
245
+ onProgress: (progress) => {
246
+ progressBar.update(Math.floor(progress * 100));
247
+ }
248
+ }
249
+ }
250
+ );
251
+ resetProgressBar();
252
+ logger.info(
253
+ `Transcribing audiobook complete, transcriptions saved to ${transcriptions}.`
254
+ );
255
+ if (parsed.time) {
256
+ transcribeTiming.print();
257
+ }
258
+ logger.info("Marking up EPUB...");
259
+ startProgressBar();
260
+ const markedup = parsed.markedup ?? join(os.tmpdir(), `stalign-markedup-${randomUUID()}.epub`);
261
+ if (!parsed.markedup) {
262
+ stack.defer(() => {
263
+ rmSync(markedup, { recursive: true, force: true });
264
+ });
265
+ }
266
+ const markupTiming = await markup(parsed.epub, markedup, {
267
+ granularity: parsed.granularity,
268
+ primaryLocale,
269
+ logger,
270
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
271
+ onProgress: (progress) => {
272
+ progressBar.update(Math.floor(progress * 100));
273
+ }
274
+ }
275
+ });
276
+ resetProgressBar();
277
+ logger.info(`Markup complete, marked up EPUB saved to ${markedup}.`);
278
+ if (parsed.time) {
279
+ markupTiming.print();
280
+ }
281
+ logger.info("Aligning EPUB with audiobook...");
282
+ startProgressBar();
283
+ const alignTiming = await align(
284
+ markedup,
285
+ parsed.output,
286
+ transcriptions,
287
+ processedAudio,
288
+ {
289
+ granularity: parsed.granularity,
290
+ primaryLocale,
291
+ logger,
292
+ ...!parsed.noProgress && parsed.logLevel === "silent" && {
293
+ onProgress: (progress) => {
294
+ progressBar.update(Math.floor(progress * 100));
295
+ }
296
+ }
297
+ }
298
+ );
299
+ resetProgressBar();
300
+ logger.info(`Alignment complete, aligned EPUB saved to ${parsed.output}`);
301
+ if (parsed.time) {
302
+ alignTiming.print();
303
+ }
304
+ } catch (_) {
305
+ var _error = _, _hasError = true;
306
+ } finally {
307
+ __callDispose(_stack, _error, _hasError);
308
+ }
309
+ }
310
+ }
311
+ } catch (_2) {
312
+ var _error2 = _2, _hasError2 = true;
313
+ } finally {
314
+ __callDispose(_stack2, _error2, _hasError2);
315
+ }
316
+ }
317
+ main().catch((e) => {
318
+ console.error(e);
319
+ });