@storyteller-platform/audiobook 0.3.5 → 0.3.7

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.
package/dist/ffmpeg.cjs CHANGED
@@ -53,12 +53,18 @@ async function execCmdBuffer(command, args) {
53
53
  try {
54
54
  const { stdout } = await execFilePromise(command, args, {
55
55
  encoding: "buffer",
56
- maxBuffer: 10 * 1024 * 1024,
56
+ // let's be very generous
57
+ maxBuffer: 50 * 1024 * 1024,
57
58
  cwd: process.cwd()
58
59
  });
59
60
  return stdout;
60
61
  } catch (error) {
61
62
  console.error(error);
63
+ if (error instanceof RangeError && error.message.includes("stdout maxBuffer length exceeded")) {
64
+ throw new Error(
65
+ "stdout maxBuffer length exceeded. This likely means that youre trying to process a very large file, and the ffmpeg process is running out of memory. Maybe check the image size of your cover art."
66
+ );
67
+ }
62
68
  if (error && typeof error === "object" && "stdout" in error) {
63
69
  console.warn((_a = error.stdout) == null ? void 0 : _a.toString());
64
70
  throw new Error((_b = error.stdout) == null ? void 0 : _b.toString());
@@ -90,7 +96,7 @@ function lookup(codecName) {
90
96
  }
91
97
  }
92
98
  async function getTrackMetadata(path) {
93
- var _a, _b;
99
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
94
100
  const stdout = await execCmd(
95
101
  `ffprobe -i ${quotePath(path)} -v quiet -show_format -show_chapters -show_streams -output_format json`
96
102
  );
@@ -133,17 +139,17 @@ async function getTrackMetadata(path) {
133
139
  duration: parseFloat(format.duration),
134
140
  bitRate: format.bit_rate !== void 0 ? parseFloat(format.bit_rate) : format.bit_rate,
135
141
  tags: {
136
- title: format.tags.title ?? format.tags.Title,
137
- subtitle: format.tags.subtitle ?? format.tags.Subtitle,
138
- date: format.tags.date ?? format.tags.Date,
139
- album: format.tags.album ?? format.tags.Album,
140
- albumArtist: format.tags.album_artist ?? format.tags.Album_Artist,
141
- artist: format.tags.artist ?? format.tags.Artist,
142
- performer: format.tags.performer ?? format.tags.Performer,
143
- composer: format.tags.composer ?? format.tags.Composer,
144
- comment: format.tags.comment ?? format.tags.Comment,
145
- description: format.tags.description ?? format.tags.Description,
146
- publisher: format.tags.publisher ?? format.tags.Publisher
142
+ title: ((_c = format.tags) == null ? void 0 : _c.title) ?? ((_d = format.tags) == null ? void 0 : _d.Title),
143
+ subtitle: ((_e = format.tags) == null ? void 0 : _e.subtitle) ?? ((_f = format.tags) == null ? void 0 : _f.Subtitle),
144
+ date: ((_g = format.tags) == null ? void 0 : _g.date) ?? ((_h = format.tags) == null ? void 0 : _h.Date),
145
+ album: ((_i = format.tags) == null ? void 0 : _i.album) ?? ((_j = format.tags) == null ? void 0 : _j.Album),
146
+ albumArtist: ((_k = format.tags) == null ? void 0 : _k.album_artist) ?? ((_l = format.tags) == null ? void 0 : _l.Album_Artist),
147
+ artist: ((_m = format.tags) == null ? void 0 : _m.artist) ?? ((_n = format.tags) == null ? void 0 : _n.Artist),
148
+ performer: ((_o = format.tags) == null ? void 0 : _o.performer) ?? ((_p = format.tags) == null ? void 0 : _p.Performer),
149
+ composer: ((_q = format.tags) == null ? void 0 : _q.composer) ?? ((_r = format.tags) == null ? void 0 : _r.Composer),
150
+ comment: ((_s = format.tags) == null ? void 0 : _s.comment) ?? ((_t = format.tags) == null ? void 0 : _t.Comment),
151
+ description: ((_u = format.tags) == null ? void 0 : _u.description) ?? ((_v = format.tags) == null ? void 0 : _v.Description),
152
+ publisher: ((_w = format.tags) == null ? void 0 : _w.publisher) ?? ((_x = format.tags) == null ? void 0 : _x.Publisher)
147
153
  },
148
154
  chapters: chapters.map(
149
155
  (chapter) => ({
package/dist/ffmpeg.js CHANGED
@@ -27,12 +27,18 @@ async function execCmdBuffer(command, args) {
27
27
  try {
28
28
  const { stdout } = await execFilePromise(command, args, {
29
29
  encoding: "buffer",
30
- maxBuffer: 10 * 1024 * 1024,
30
+ // let's be very generous
31
+ maxBuffer: 50 * 1024 * 1024,
31
32
  cwd: process.cwd()
32
33
  });
33
34
  return stdout;
34
35
  } catch (error) {
35
36
  console.error(error);
37
+ if (error instanceof RangeError && error.message.includes("stdout maxBuffer length exceeded")) {
38
+ throw new Error(
39
+ "stdout maxBuffer length exceeded. This likely means that youre trying to process a very large file, and the ffmpeg process is running out of memory. Maybe check the image size of your cover art."
40
+ );
41
+ }
36
42
  if (error && typeof error === "object" && "stdout" in error) {
37
43
  console.warn((_a = error.stdout) == null ? void 0 : _a.toString());
38
44
  throw new Error((_b = error.stdout) == null ? void 0 : _b.toString());
@@ -64,7 +70,7 @@ function lookup(codecName) {
64
70
  }
65
71
  }
66
72
  async function getTrackMetadata(path) {
67
- var _a, _b;
73
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
68
74
  const stdout = await execCmd(
69
75
  `ffprobe -i ${quotePath(path)} -v quiet -show_format -show_chapters -show_streams -output_format json`
70
76
  );
@@ -107,17 +113,17 @@ async function getTrackMetadata(path) {
107
113
  duration: parseFloat(format.duration),
108
114
  bitRate: format.bit_rate !== void 0 ? parseFloat(format.bit_rate) : format.bit_rate,
109
115
  tags: {
110
- title: format.tags.title ?? format.tags.Title,
111
- subtitle: format.tags.subtitle ?? format.tags.Subtitle,
112
- date: format.tags.date ?? format.tags.Date,
113
- album: format.tags.album ?? format.tags.Album,
114
- albumArtist: format.tags.album_artist ?? format.tags.Album_Artist,
115
- artist: format.tags.artist ?? format.tags.Artist,
116
- performer: format.tags.performer ?? format.tags.Performer,
117
- composer: format.tags.composer ?? format.tags.Composer,
118
- comment: format.tags.comment ?? format.tags.Comment,
119
- description: format.tags.description ?? format.tags.Description,
120
- publisher: format.tags.publisher ?? format.tags.Publisher
116
+ title: ((_c = format.tags) == null ? void 0 : _c.title) ?? ((_d = format.tags) == null ? void 0 : _d.Title),
117
+ subtitle: ((_e = format.tags) == null ? void 0 : _e.subtitle) ?? ((_f = format.tags) == null ? void 0 : _f.Subtitle),
118
+ date: ((_g = format.tags) == null ? void 0 : _g.date) ?? ((_h = format.tags) == null ? void 0 : _h.Date),
119
+ album: ((_i = format.tags) == null ? void 0 : _i.album) ?? ((_j = format.tags) == null ? void 0 : _j.Album),
120
+ albumArtist: ((_k = format.tags) == null ? void 0 : _k.album_artist) ?? ((_l = format.tags) == null ? void 0 : _l.Album_Artist),
121
+ artist: ((_m = format.tags) == null ? void 0 : _m.artist) ?? ((_n = format.tags) == null ? void 0 : _n.Artist),
122
+ performer: ((_o = format.tags) == null ? void 0 : _o.performer) ?? ((_p = format.tags) == null ? void 0 : _p.Performer),
123
+ composer: ((_q = format.tags) == null ? void 0 : _q.composer) ?? ((_r = format.tags) == null ? void 0 : _r.Composer),
124
+ comment: ((_s = format.tags) == null ? void 0 : _s.comment) ?? ((_t = format.tags) == null ? void 0 : _t.Comment),
125
+ description: ((_u = format.tags) == null ? void 0 : _u.description) ?? ((_v = format.tags) == null ? void 0 : _v.Description),
126
+ publisher: ((_w = format.tags) == null ? void 0 : _w.publisher) ?? ((_x = format.tags) == null ? void 0 : _x.Publisher)
121
127
  },
122
128
  chapters: chapters.map(
123
129
  (chapter) => ({
package/dist/index.cjs CHANGED
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
9
7
  var __typeError = (msg) => {
@@ -21,14 +19,6 @@ var __copyProps = (to, from, except, desc) => {
21
19
  }
22
20
  return to;
23
21
  };
24
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
- // If the importer is in node compatibility mode or this is not an ESM
26
- // file that has been converted to a CommonJS file using a Babel-
27
- // compatible transform (i.e. "__esModule" has not been set), then set
28
- // "default" to the CommonJS "module.exports" for node compatibility.
29
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
- mod
31
- ));
32
22
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
23
  var __using = (stack, value, async) => {
34
24
  if (value != null) {
@@ -92,30 +82,12 @@ var import_node_crypto = require("node:crypto");
92
82
  var import_node_fs = require("node:fs");
93
83
  var import_promises = require("node:fs/promises");
94
84
  var import_node_os = require("node:os");
95
- var util = __toESM(require("node:util"), 1);
85
+ var import_promises2 = require("node:stream/promises");
96
86
  var import_mime_types = require("mime-types");
97
- var import_yauzl = __toESM(require("yauzl"), 1);
87
+ var import_yauzl_promise = require("yauzl-promise");
98
88
  var import_yazl = require("yazl");
99
89
  var import_path = require("@storyteller-platform/path");
100
90
  var import_entry = require("./entry.cjs");
101
- function promisify(api) {
102
- return function(arg, options) {
103
- return new Promise(function(resolve, reject) {
104
- api(arg, options, function(err, response) {
105
- if (err) {
106
- reject(err);
107
- return;
108
- }
109
- resolve(response);
110
- });
111
- });
112
- };
113
- }
114
- const unzipFromPath = promisify(
115
- (arg, options, callback) => {
116
- import_yauzl.default.open(arg, options, callback);
117
- }
118
- );
119
91
  const COVER_IMAGE_FILE_EXTENSIONS = [
120
92
  ".jpeg",
121
93
  ".jpg",
@@ -162,54 +134,47 @@ class Audiobook {
162
134
  }
163
135
  async getEntries() {
164
136
  if (this.isZip) {
165
- var _stack = [];
137
+ const [first] = this.inputs;
138
+ const extractPath = (0, import_path.join)(
139
+ (0, import_node_os.tmpdir)(),
140
+ `storyteller-platform-audiobook-${(0, import_node_crypto.randomUUID)()}`
141
+ );
142
+ this.extractPath = extractPath;
143
+ const entries = [];
166
144
  try {
167
- const [first] = this.inputs;
168
- const extractPath = (0, import_path.join)(
169
- (0, import_node_os.tmpdir)(),
170
- `storyteller-platform-audiobook-${(0, import_node_crypto.randomUUID)()}`
171
- );
172
- this.extractPath = extractPath;
173
- await (0, import_promises.mkdir)(this.extractPath, { recursive: true });
174
- const zipfile = await unzipFromPath(first, { lazyEntries: true });
175
- const stack = __using(_stack, new DisposableStack());
176
- stack.defer(() => {
177
- zipfile.close();
178
- });
179
- const entries = [];
180
- const { promise, resolve } = Promise.withResolvers();
181
- zipfile.on("end", () => {
182
- resolve();
183
- });
184
- const openReadStream = util.promisify(
185
- zipfile.openReadStream.bind(zipfile)
186
- );
187
- zipfile.readEntry();
188
- zipfile.on("entry", async (entry) => {
189
- if (entry.fileName.endsWith("/")) {
190
- zipfile.readEntry();
191
- } else {
192
- entries.push(entry.fileName);
193
- const readStream = await openReadStream(entry);
194
- readStream.on("end", function() {
195
- zipfile.readEntry();
196
- });
197
- const writePath = (0, import_path.join)(extractPath, entry.fileName);
198
- await (0, import_promises.mkdir)((0, import_path.dirname)(writePath), { recursive: true });
199
- readStream.pipe((0, import_node_fs.createWriteStream)(writePath));
145
+ var _stack = [];
146
+ try {
147
+ const zipfile = await (0, import_yauzl_promise.open)(first);
148
+ const stack = __using(_stack, new AsyncDisposableStack(), true);
149
+ stack.defer(async () => {
150
+ await zipfile.close();
151
+ });
152
+ for await (const entry of zipfile) {
153
+ if (entry.filename.endsWith("/")) {
154
+ } else {
155
+ entries.push(entry.filename);
156
+ const readStream = await entry.openReadStream();
157
+ const writePath = (0, import_path.join)(extractPath, entry.filename);
158
+ await (0, import_promises.mkdir)((0, import_path.dirname)(writePath), { recursive: true });
159
+ const writeStream = (0, import_node_fs.createWriteStream)(writePath);
160
+ await (0, import_promises2.pipeline)(readStream, writeStream);
161
+ }
200
162
  }
201
- });
202
- await promise;
203
- return entries.filter(
204
- (entry) => AUDIO_FILE_EXTENSIONS.includes(
205
- (0, import_path.extname)(entry)
206
- )
207
- ).map((entry) => new import_entry.AudiobookEntry((0, import_path.join)(extractPath, entry)));
208
- } catch (_) {
209
- var _error = _, _hasError = true;
210
- } finally {
211
- __callDispose(_stack, _error, _hasError);
163
+ } catch (_) {
164
+ var _error = _, _hasError = true;
165
+ } finally {
166
+ var _promise = __callDispose(_stack, _error, _hasError);
167
+ _promise && await _promise;
168
+ }
169
+ } catch (error) {
170
+ (0, import_node_fs.rmSync)(extractPath, { force: true, recursive: true });
171
+ throw error;
212
172
  }
173
+ return entries.filter(
174
+ (entry) => AUDIO_FILE_EXTENSIONS.includes(
175
+ (0, import_path.extname)(entry)
176
+ )
177
+ ).map((entry) => new import_entry.AudiobookEntry((0, import_path.join)(extractPath, entry)));
213
178
  } else {
214
179
  return this.inputs.map((input) => new import_entry.AudiobookEntry(input));
215
180
  }
package/dist/index.js CHANGED
@@ -6,30 +6,12 @@ import { randomUUID } from "node:crypto";
6
6
  import { createWriteStream, rmSync } from "node:fs";
7
7
  import { cp, mkdir, readFile, readdir, rm } from "node:fs/promises";
8
8
  import { tmpdir } from "node:os";
9
- import * as util from "node:util";
9
+ import { pipeline } from "node:stream/promises";
10
10
  import { lookup } from "mime-types";
11
- import yauzl from "yauzl";
11
+ import { open } from "yauzl-promise";
12
12
  import { ZipFile } from "yazl";
13
13
  import { basename, dirname, extname, join } from "@storyteller-platform/path";
14
14
  import { AudiobookEntry } from "./entry.js";
15
- function promisify(api) {
16
- return function(arg, options) {
17
- return new Promise(function(resolve, reject) {
18
- api(arg, options, function(err, response) {
19
- if (err) {
20
- reject(err);
21
- return;
22
- }
23
- resolve(response);
24
- });
25
- });
26
- };
27
- }
28
- const unzipFromPath = promisify(
29
- (arg, options, callback) => {
30
- yauzl.open(arg, options, callback);
31
- }
32
- );
33
15
  const COVER_IMAGE_FILE_EXTENSIONS = [
34
16
  ".jpeg",
35
17
  ".jpg",
@@ -76,54 +58,47 @@ class Audiobook {
76
58
  }
77
59
  async getEntries() {
78
60
  if (this.isZip) {
79
- var _stack = [];
61
+ const [first] = this.inputs;
62
+ const extractPath = join(
63
+ tmpdir(),
64
+ `storyteller-platform-audiobook-${randomUUID()}`
65
+ );
66
+ this.extractPath = extractPath;
67
+ const entries = [];
80
68
  try {
81
- const [first] = this.inputs;
82
- const extractPath = join(
83
- tmpdir(),
84
- `storyteller-platform-audiobook-${randomUUID()}`
85
- );
86
- this.extractPath = extractPath;
87
- await mkdir(this.extractPath, { recursive: true });
88
- const zipfile = await unzipFromPath(first, { lazyEntries: true });
89
- const stack = __using(_stack, new DisposableStack());
90
- stack.defer(() => {
91
- zipfile.close();
92
- });
93
- const entries = [];
94
- const { promise, resolve } = Promise.withResolvers();
95
- zipfile.on("end", () => {
96
- resolve();
97
- });
98
- const openReadStream = util.promisify(
99
- zipfile.openReadStream.bind(zipfile)
100
- );
101
- zipfile.readEntry();
102
- zipfile.on("entry", async (entry) => {
103
- if (entry.fileName.endsWith("/")) {
104
- zipfile.readEntry();
105
- } else {
106
- entries.push(entry.fileName);
107
- const readStream = await openReadStream(entry);
108
- readStream.on("end", function() {
109
- zipfile.readEntry();
110
- });
111
- const writePath = join(extractPath, entry.fileName);
112
- await mkdir(dirname(writePath), { recursive: true });
113
- readStream.pipe(createWriteStream(writePath));
69
+ var _stack = [];
70
+ try {
71
+ const zipfile = await open(first);
72
+ const stack = __using(_stack, new AsyncDisposableStack(), true);
73
+ stack.defer(async () => {
74
+ await zipfile.close();
75
+ });
76
+ for await (const entry of zipfile) {
77
+ if (entry.filename.endsWith("/")) {
78
+ } else {
79
+ entries.push(entry.filename);
80
+ const readStream = await entry.openReadStream();
81
+ const writePath = join(extractPath, entry.filename);
82
+ await mkdir(dirname(writePath), { recursive: true });
83
+ const writeStream = createWriteStream(writePath);
84
+ await pipeline(readStream, writeStream);
85
+ }
114
86
  }
115
- });
116
- await promise;
117
- return entries.filter(
118
- (entry) => AUDIO_FILE_EXTENSIONS.includes(
119
- extname(entry)
120
- )
121
- ).map((entry) => new AudiobookEntry(join(extractPath, entry)));
122
- } catch (_) {
123
- var _error = _, _hasError = true;
124
- } finally {
125
- __callDispose(_stack, _error, _hasError);
87
+ } catch (_) {
88
+ var _error = _, _hasError = true;
89
+ } finally {
90
+ var _promise = __callDispose(_stack, _error, _hasError);
91
+ _promise && await _promise;
92
+ }
93
+ } catch (error) {
94
+ rmSync(extractPath, { force: true, recursive: true });
95
+ throw error;
126
96
  }
97
+ return entries.filter(
98
+ (entry) => AUDIO_FILE_EXTENSIONS.includes(
99
+ extname(entry)
100
+ )
101
+ ).map((entry) => new AudiobookEntry(join(extractPath, entry)));
127
102
  } else {
128
103
  return this.inputs.map((input) => new AudiobookEntry(input));
129
104
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storyteller-platform/audiobook",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "module": "dist/index.js",
@@ -32,7 +32,9 @@
32
32
  "devDependencies": {
33
33
  "@storyteller-platform/tsup": "^0.1.0",
34
34
  "@tsconfig/strictest": "^2.0.5",
35
+ "@types/yauzl-promise": "^4",
35
36
  "@types/yazl": "^3",
37
+ "eslint": "^8.0.0",
36
38
  "markdown-toc": "^1.2.0",
37
39
  "remark-toc": "^9.0.0",
38
40
  "tsup": "^8.5.0",
@@ -43,14 +45,14 @@
43
45
  "typescript": "^5.9.2"
44
46
  },
45
47
  "dependencies": {
46
- "@storyteller-platform/fs": "^0.1.3",
48
+ "@storyteller-platform/eslint": "0.1.0",
49
+ "@storyteller-platform/fs": "^0.1.4",
47
50
  "@storyteller-platform/path": "^0.1.1",
48
51
  "@types/mime-types": "^2",
49
52
  "@types/node": "^24.0.0",
50
- "@types/yauzl": "^2.10.3",
51
53
  "mime-types": "^3.0.1",
52
54
  "music-metadata": "^11.9.0",
53
- "yauzl": "^3.2.0",
55
+ "yauzl-promise": "^4.0.0",
54
56
  "yazl": "^3.3.1"
55
57
  },
56
58
  "publishConfig": {