@storyteller-platform/audiobook 0.3.4 → 0.3.6
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/entry.cjs +20 -1
- package/dist/entry.d.cts +1 -0
- package/dist/entry.d.ts +1 -0
- package/dist/entry.js +20 -1
- package/dist/ffmpeg.cjs +53 -16
- package/dist/ffmpeg.d.cts +3 -1
- package/dist/ffmpeg.d.ts +3 -1
- package/dist/ffmpeg.js +53 -16
- package/dist/index.cjs +7 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -0
- package/package.json +1 -1
package/dist/entry.cjs
CHANGED
|
@@ -144,9 +144,28 @@ class AudiobookEntry {
|
|
|
144
144
|
start: chapter.startTime
|
|
145
145
|
}));
|
|
146
146
|
}
|
|
147
|
+
async setChapters(chapters) {
|
|
148
|
+
const info = await this.getInfo();
|
|
149
|
+
const duration = await this.getDuration();
|
|
150
|
+
const ffmpegChapters = [];
|
|
151
|
+
for (let i = 0; i < ffmpegChapters.length; i++) {
|
|
152
|
+
const chapter = chapters[i];
|
|
153
|
+
const prevFfmpegChapter = ffmpegChapters[i - 1];
|
|
154
|
+
ffmpegChapters.push({
|
|
155
|
+
id: i,
|
|
156
|
+
startTime: chapter.start ?? 0,
|
|
157
|
+
title: chapter.title ?? `ch${i}`,
|
|
158
|
+
endTime: duration
|
|
159
|
+
});
|
|
160
|
+
if (prevFfmpegChapter) {
|
|
161
|
+
prevFfmpegChapter.endTime = chapter.start ?? 0;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
info.chapters = ffmpegChapters;
|
|
165
|
+
}
|
|
147
166
|
async saveAndClose() {
|
|
148
167
|
const info = await this.getInfo();
|
|
149
|
-
await (0, import_ffmpeg.writeTrackMetadata)(this.filename, info
|
|
168
|
+
await (0, import_ffmpeg.writeTrackMetadata)(this.filename, info);
|
|
150
169
|
}
|
|
151
170
|
}
|
|
152
171
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/entry.d.cts
CHANGED
|
@@ -33,6 +33,7 @@ declare class AudiobookEntry {
|
|
|
33
33
|
getBitRate(): Promise<number | undefined>;
|
|
34
34
|
getResource(): Promise<AudiobookResource>;
|
|
35
35
|
getChapters(): Promise<AudiobookChapter[]>;
|
|
36
|
+
setChapters(chapters: AudiobookChapter[]): Promise<void>;
|
|
36
37
|
saveAndClose(): Promise<void>;
|
|
37
38
|
}
|
|
38
39
|
|
package/dist/entry.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ declare class AudiobookEntry {
|
|
|
33
33
|
getBitRate(): Promise<number | undefined>;
|
|
34
34
|
getResource(): Promise<AudiobookResource>;
|
|
35
35
|
getChapters(): Promise<AudiobookChapter[]>;
|
|
36
|
+
setChapters(chapters: AudiobookChapter[]): Promise<void>;
|
|
36
37
|
saveAndClose(): Promise<void>;
|
|
37
38
|
}
|
|
38
39
|
|
package/dist/entry.js
CHANGED
|
@@ -125,9 +125,28 @@ class AudiobookEntry {
|
|
|
125
125
|
start: chapter.startTime
|
|
126
126
|
}));
|
|
127
127
|
}
|
|
128
|
+
async setChapters(chapters) {
|
|
129
|
+
const info = await this.getInfo();
|
|
130
|
+
const duration = await this.getDuration();
|
|
131
|
+
const ffmpegChapters = [];
|
|
132
|
+
for (let i = 0; i < ffmpegChapters.length; i++) {
|
|
133
|
+
const chapter = chapters[i];
|
|
134
|
+
const prevFfmpegChapter = ffmpegChapters[i - 1];
|
|
135
|
+
ffmpegChapters.push({
|
|
136
|
+
id: i,
|
|
137
|
+
startTime: chapter.start ?? 0,
|
|
138
|
+
title: chapter.title ?? `ch${i}`,
|
|
139
|
+
endTime: duration
|
|
140
|
+
});
|
|
141
|
+
if (prevFfmpegChapter) {
|
|
142
|
+
prevFfmpegChapter.endTime = chapter.start ?? 0;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
info.chapters = ffmpegChapters;
|
|
146
|
+
}
|
|
128
147
|
async saveAndClose() {
|
|
129
148
|
const info = await this.getInfo();
|
|
130
|
-
await writeTrackMetadata(this.filename, info
|
|
149
|
+
await writeTrackMetadata(this.filename, info);
|
|
131
150
|
}
|
|
132
151
|
}
|
|
133
152
|
export {
|
package/dist/ffmpeg.cjs
CHANGED
|
@@ -90,11 +90,19 @@ function lookup(codecName) {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
async function getTrackMetadata(path) {
|
|
93
|
-
var _a, _b;
|
|
93
|
+
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
94
|
const stdout = await execCmd(
|
|
95
95
|
`ffprobe -i ${quotePath(path)} -v quiet -show_format -show_chapters -show_streams -output_format json`
|
|
96
96
|
);
|
|
97
97
|
const { chapters, streams, format } = JSON.parse(stdout);
|
|
98
|
+
let id3v2Version = null;
|
|
99
|
+
if ((0, import_path.extname)(path).toLowerCase() === ".mp3") {
|
|
100
|
+
const { stderr: id3v2VersionOut } = await execPromise(
|
|
101
|
+
`ffprobe -i ${quotePath(path)} -v debug`
|
|
102
|
+
);
|
|
103
|
+
const id3v2VersionMatch = id3v2VersionOut.match(/id3v2 ver:(3|4)/);
|
|
104
|
+
id3v2Version = (id3v2VersionMatch == null ? void 0 : id3v2VersionMatch[1]) ?? null;
|
|
105
|
+
}
|
|
98
106
|
const attachedPicStream = streams.find(
|
|
99
107
|
(stream) => !!stream.disposition.attached_pic
|
|
100
108
|
);
|
|
@@ -121,20 +129,21 @@ async function getTrackMetadata(path) {
|
|
|
121
129
|
])
|
|
122
130
|
};
|
|
123
131
|
return {
|
|
132
|
+
id3v2Version,
|
|
124
133
|
duration: parseFloat(format.duration),
|
|
125
134
|
bitRate: format.bit_rate !== void 0 ? parseFloat(format.bit_rate) : format.bit_rate,
|
|
126
135
|
tags: {
|
|
127
|
-
title: format.tags.title ?? format.tags.Title,
|
|
128
|
-
subtitle: format.tags.subtitle ?? format.tags.Subtitle,
|
|
129
|
-
date: format.tags.date ?? format.tags.Date,
|
|
130
|
-
album: format.tags.album ?? format.tags.Album,
|
|
131
|
-
albumArtist: format.tags.album_artist ?? format.tags.Album_Artist,
|
|
132
|
-
artist: format.tags.artist ?? format.tags.Artist,
|
|
133
|
-
performer: format.tags.performer ?? format.tags.Performer,
|
|
134
|
-
composer: format.tags.composer ?? format.tags.Composer,
|
|
135
|
-
comment: format.tags.comment ?? format.tags.Comment,
|
|
136
|
-
description: format.tags.description ?? format.tags.Description,
|
|
137
|
-
publisher: format.tags.publisher ?? format.tags.Publisher
|
|
136
|
+
title: ((_c = format.tags) == null ? void 0 : _c.title) ?? ((_d = format.tags) == null ? void 0 : _d.Title),
|
|
137
|
+
subtitle: ((_e = format.tags) == null ? void 0 : _e.subtitle) ?? ((_f = format.tags) == null ? void 0 : _f.Subtitle),
|
|
138
|
+
date: ((_g = format.tags) == null ? void 0 : _g.date) ?? ((_h = format.tags) == null ? void 0 : _h.Date),
|
|
139
|
+
album: ((_i = format.tags) == null ? void 0 : _i.album) ?? ((_j = format.tags) == null ? void 0 : _j.Album),
|
|
140
|
+
albumArtist: ((_k = format.tags) == null ? void 0 : _k.album_artist) ?? ((_l = format.tags) == null ? void 0 : _l.Album_Artist),
|
|
141
|
+
artist: ((_m = format.tags) == null ? void 0 : _m.artist) ?? ((_n = format.tags) == null ? void 0 : _n.Artist),
|
|
142
|
+
performer: ((_o = format.tags) == null ? void 0 : _o.performer) ?? ((_p = format.tags) == null ? void 0 : _p.Performer),
|
|
143
|
+
composer: ((_q = format.tags) == null ? void 0 : _q.composer) ?? ((_r = format.tags) == null ? void 0 : _r.Composer),
|
|
144
|
+
comment: ((_s = format.tags) == null ? void 0 : _s.comment) ?? ((_t = format.tags) == null ? void 0 : _t.Comment),
|
|
145
|
+
description: ((_u = format.tags) == null ? void 0 : _u.description) ?? ((_v = format.tags) == null ? void 0 : _v.Description),
|
|
146
|
+
publisher: ((_w = format.tags) == null ? void 0 : _w.publisher) ?? ((_x = format.tags) == null ? void 0 : _x.Publisher)
|
|
138
147
|
},
|
|
139
148
|
chapters: chapters.map(
|
|
140
149
|
(chapter) => ({
|
|
@@ -147,9 +156,16 @@ async function getTrackMetadata(path) {
|
|
|
147
156
|
attachedPic
|
|
148
157
|
};
|
|
149
158
|
}
|
|
150
|
-
|
|
159
|
+
function escapeFfmetadata(str) {
|
|
160
|
+
return str.replaceAll(/\\/g, "\\\\").replaceAll(/=/g, "\\=").replaceAll(/;/g, "\\;").replaceAll(/#/g, "\\#").replaceAll(/\n/g, "\\n");
|
|
161
|
+
}
|
|
162
|
+
async function writeTrackMetadata(path, trackInfo) {
|
|
163
|
+
const { tags: metadata, id3v2Version, chapters, attachedPic } = trackInfo;
|
|
151
164
|
const args = [];
|
|
152
165
|
const metadataArgs = [];
|
|
166
|
+
if (id3v2Version) {
|
|
167
|
+
metadataArgs.push(`-id3v2_version ${id3v2Version}`);
|
|
168
|
+
}
|
|
153
169
|
if (metadata.title) {
|
|
154
170
|
metadataArgs.push(`-metadata title="${escapeQuotes(metadata.title)}"`);
|
|
155
171
|
}
|
|
@@ -191,13 +207,34 @@ async function writeTrackMetadata(path, metadata, attachedPic) {
|
|
|
191
207
|
`-metadata publisher="${escapeQuotes(metadata.publisher)}"`
|
|
192
208
|
);
|
|
193
209
|
}
|
|
210
|
+
metadataArgs.push("-map 0:a -map_metadata 0");
|
|
194
211
|
const ext = (0, import_path.extname)(path);
|
|
195
212
|
const tmpPath = (0, import_node_path.join)(
|
|
196
213
|
(0, import_node_os.tmpdir)(),
|
|
197
214
|
`storyteller-platform-audiobook-${(0, import_node_crypto.randomUUID)()}${ext}`
|
|
198
215
|
);
|
|
216
|
+
const chapterFilePath = (0, import_node_path.join)(
|
|
217
|
+
(0, import_node_os.tmpdir)(),
|
|
218
|
+
`storyteller-platform-audiobook-${(0, import_node_crypto.randomUUID)()}.txt`
|
|
219
|
+
);
|
|
199
220
|
let picPath = null;
|
|
200
221
|
try {
|
|
222
|
+
let chapterFileContents = ";FFMETADATA1\n\n";
|
|
223
|
+
for (const chapter of chapters) {
|
|
224
|
+
chapterFileContents += `[CHAPTER]
|
|
225
|
+
TIMEBASE=1/1000
|
|
226
|
+
START=${Math.floor(chapter.startTime * 1e3)}
|
|
227
|
+
END=${Math.floor(chapter.endTime * 1e3)}
|
|
228
|
+
`;
|
|
229
|
+
if (chapter.title) {
|
|
230
|
+
chapterFileContents += `TITLE=${escapeFfmetadata(chapter.title)}
|
|
231
|
+
`;
|
|
232
|
+
}
|
|
233
|
+
chapterFileContents += "\n";
|
|
234
|
+
}
|
|
235
|
+
await (0, import_promises.writeFile)(chapterFilePath, chapterFileContents);
|
|
236
|
+
args.push(`-i ${chapterFilePath}`);
|
|
237
|
+
metadataArgs.push(`-map_chapters 1`);
|
|
201
238
|
if (attachedPic) {
|
|
202
239
|
const imageExt = attachedPic.mimeType.split("/")[1];
|
|
203
240
|
picPath = (0, import_node_path.join)(
|
|
@@ -205,9 +242,9 @@ async function writeTrackMetadata(path, metadata, attachedPic) {
|
|
|
205
242
|
`storyteller-platform-audiobook-${(0, import_node_crypto.randomUUID)()}.${imageExt}`
|
|
206
243
|
);
|
|
207
244
|
await (0, import_promises.writeFile)(picPath, attachedPic.data);
|
|
208
|
-
args.push(`-i ${
|
|
209
|
-
|
|
210
|
-
|
|
245
|
+
args.push(`-i ${picPath}`);
|
|
246
|
+
metadataArgs.push(`-map 2:v`);
|
|
247
|
+
metadataArgs.push(`-disposition:v:0 attached_pic`);
|
|
211
248
|
if (attachedPic.name) {
|
|
212
249
|
metadataArgs.push(
|
|
213
250
|
`-metadata:s:v title="${escapeQuotes(attachedPic.name)}"`
|
package/dist/ffmpeg.d.cts
CHANGED
|
@@ -15,6 +15,7 @@ type AttachedPic = {
|
|
|
15
15
|
description?: string | undefined;
|
|
16
16
|
};
|
|
17
17
|
declare function getTrackMetadata(path: string): Promise<{
|
|
18
|
+
id3v2Version: 3 | 4 | null;
|
|
18
19
|
duration: number;
|
|
19
20
|
bitRate: number | undefined;
|
|
20
21
|
tags: {
|
|
@@ -38,8 +39,9 @@ declare function getTrackMetadata(path: string): Promise<{
|
|
|
38
39
|
}[];
|
|
39
40
|
attachedPic: AttachedPic | undefined;
|
|
40
41
|
}>;
|
|
41
|
-
declare function writeTrackMetadata(path: string,
|
|
42
|
+
declare function writeTrackMetadata(path: string, trackInfo: TrackInfo): Promise<void>;
|
|
42
43
|
declare function getTrackMetadataFromBuffer(buffer: Uint8Array): Promise<{
|
|
44
|
+
id3v2Version: 3 | 4 | null;
|
|
43
45
|
duration: number;
|
|
44
46
|
bitRate: number | undefined;
|
|
45
47
|
tags: {
|
package/dist/ffmpeg.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ type AttachedPic = {
|
|
|
15
15
|
description?: string | undefined;
|
|
16
16
|
};
|
|
17
17
|
declare function getTrackMetadata(path: string): Promise<{
|
|
18
|
+
id3v2Version: 3 | 4 | null;
|
|
18
19
|
duration: number;
|
|
19
20
|
bitRate: number | undefined;
|
|
20
21
|
tags: {
|
|
@@ -38,8 +39,9 @@ declare function getTrackMetadata(path: string): Promise<{
|
|
|
38
39
|
}[];
|
|
39
40
|
attachedPic: AttachedPic | undefined;
|
|
40
41
|
}>;
|
|
41
|
-
declare function writeTrackMetadata(path: string,
|
|
42
|
+
declare function writeTrackMetadata(path: string, trackInfo: TrackInfo): Promise<void>;
|
|
42
43
|
declare function getTrackMetadataFromBuffer(buffer: Uint8Array): Promise<{
|
|
44
|
+
id3v2Version: 3 | 4 | null;
|
|
43
45
|
duration: number;
|
|
44
46
|
bitRate: number | undefined;
|
|
45
47
|
tags: {
|
package/dist/ffmpeg.js
CHANGED
|
@@ -64,11 +64,19 @@ function lookup(codecName) {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
async function getTrackMetadata(path) {
|
|
67
|
-
var _a, _b;
|
|
67
|
+
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
68
|
const stdout = await execCmd(
|
|
69
69
|
`ffprobe -i ${quotePath(path)} -v quiet -show_format -show_chapters -show_streams -output_format json`
|
|
70
70
|
);
|
|
71
71
|
const { chapters, streams, format } = JSON.parse(stdout);
|
|
72
|
+
let id3v2Version = null;
|
|
73
|
+
if (extname(path).toLowerCase() === ".mp3") {
|
|
74
|
+
const { stderr: id3v2VersionOut } = await execPromise(
|
|
75
|
+
`ffprobe -i ${quotePath(path)} -v debug`
|
|
76
|
+
);
|
|
77
|
+
const id3v2VersionMatch = id3v2VersionOut.match(/id3v2 ver:(3|4)/);
|
|
78
|
+
id3v2Version = (id3v2VersionMatch == null ? void 0 : id3v2VersionMatch[1]) ?? null;
|
|
79
|
+
}
|
|
72
80
|
const attachedPicStream = streams.find(
|
|
73
81
|
(stream) => !!stream.disposition.attached_pic
|
|
74
82
|
);
|
|
@@ -95,20 +103,21 @@ async function getTrackMetadata(path) {
|
|
|
95
103
|
])
|
|
96
104
|
};
|
|
97
105
|
return {
|
|
106
|
+
id3v2Version,
|
|
98
107
|
duration: parseFloat(format.duration),
|
|
99
108
|
bitRate: format.bit_rate !== void 0 ? parseFloat(format.bit_rate) : format.bit_rate,
|
|
100
109
|
tags: {
|
|
101
|
-
title: format.tags.title ?? format.tags.Title,
|
|
102
|
-
subtitle: format.tags.subtitle ?? format.tags.Subtitle,
|
|
103
|
-
date: format.tags.date ?? format.tags.Date,
|
|
104
|
-
album: format.tags.album ?? format.tags.Album,
|
|
105
|
-
albumArtist: format.tags.album_artist ?? format.tags.Album_Artist,
|
|
106
|
-
artist: format.tags.artist ?? format.tags.Artist,
|
|
107
|
-
performer: format.tags.performer ?? format.tags.Performer,
|
|
108
|
-
composer: format.tags.composer ?? format.tags.Composer,
|
|
109
|
-
comment: format.tags.comment ?? format.tags.Comment,
|
|
110
|
-
description: format.tags.description ?? format.tags.Description,
|
|
111
|
-
publisher: format.tags.publisher ?? format.tags.Publisher
|
|
110
|
+
title: ((_c = format.tags) == null ? void 0 : _c.title) ?? ((_d = format.tags) == null ? void 0 : _d.Title),
|
|
111
|
+
subtitle: ((_e = format.tags) == null ? void 0 : _e.subtitle) ?? ((_f = format.tags) == null ? void 0 : _f.Subtitle),
|
|
112
|
+
date: ((_g = format.tags) == null ? void 0 : _g.date) ?? ((_h = format.tags) == null ? void 0 : _h.Date),
|
|
113
|
+
album: ((_i = format.tags) == null ? void 0 : _i.album) ?? ((_j = format.tags) == null ? void 0 : _j.Album),
|
|
114
|
+
albumArtist: ((_k = format.tags) == null ? void 0 : _k.album_artist) ?? ((_l = format.tags) == null ? void 0 : _l.Album_Artist),
|
|
115
|
+
artist: ((_m = format.tags) == null ? void 0 : _m.artist) ?? ((_n = format.tags) == null ? void 0 : _n.Artist),
|
|
116
|
+
performer: ((_o = format.tags) == null ? void 0 : _o.performer) ?? ((_p = format.tags) == null ? void 0 : _p.Performer),
|
|
117
|
+
composer: ((_q = format.tags) == null ? void 0 : _q.composer) ?? ((_r = format.tags) == null ? void 0 : _r.Composer),
|
|
118
|
+
comment: ((_s = format.tags) == null ? void 0 : _s.comment) ?? ((_t = format.tags) == null ? void 0 : _t.Comment),
|
|
119
|
+
description: ((_u = format.tags) == null ? void 0 : _u.description) ?? ((_v = format.tags) == null ? void 0 : _v.Description),
|
|
120
|
+
publisher: ((_w = format.tags) == null ? void 0 : _w.publisher) ?? ((_x = format.tags) == null ? void 0 : _x.Publisher)
|
|
112
121
|
},
|
|
113
122
|
chapters: chapters.map(
|
|
114
123
|
(chapter) => ({
|
|
@@ -121,9 +130,16 @@ async function getTrackMetadata(path) {
|
|
|
121
130
|
attachedPic
|
|
122
131
|
};
|
|
123
132
|
}
|
|
124
|
-
|
|
133
|
+
function escapeFfmetadata(str) {
|
|
134
|
+
return str.replaceAll(/\\/g, "\\\\").replaceAll(/=/g, "\\=").replaceAll(/;/g, "\\;").replaceAll(/#/g, "\\#").replaceAll(/\n/g, "\\n");
|
|
135
|
+
}
|
|
136
|
+
async function writeTrackMetadata(path, trackInfo) {
|
|
137
|
+
const { tags: metadata, id3v2Version, chapters, attachedPic } = trackInfo;
|
|
125
138
|
const args = [];
|
|
126
139
|
const metadataArgs = [];
|
|
140
|
+
if (id3v2Version) {
|
|
141
|
+
metadataArgs.push(`-id3v2_version ${id3v2Version}`);
|
|
142
|
+
}
|
|
127
143
|
if (metadata.title) {
|
|
128
144
|
metadataArgs.push(`-metadata title="${escapeQuotes(metadata.title)}"`);
|
|
129
145
|
}
|
|
@@ -165,13 +181,34 @@ async function writeTrackMetadata(path, metadata, attachedPic) {
|
|
|
165
181
|
`-metadata publisher="${escapeQuotes(metadata.publisher)}"`
|
|
166
182
|
);
|
|
167
183
|
}
|
|
184
|
+
metadataArgs.push("-map 0:a -map_metadata 0");
|
|
168
185
|
const ext = extname(path);
|
|
169
186
|
const tmpPath = join(
|
|
170
187
|
tmpdir(),
|
|
171
188
|
`storyteller-platform-audiobook-${randomUUID()}${ext}`
|
|
172
189
|
);
|
|
190
|
+
const chapterFilePath = join(
|
|
191
|
+
tmpdir(),
|
|
192
|
+
`storyteller-platform-audiobook-${randomUUID()}.txt`
|
|
193
|
+
);
|
|
173
194
|
let picPath = null;
|
|
174
195
|
try {
|
|
196
|
+
let chapterFileContents = ";FFMETADATA1\n\n";
|
|
197
|
+
for (const chapter of chapters) {
|
|
198
|
+
chapterFileContents += `[CHAPTER]
|
|
199
|
+
TIMEBASE=1/1000
|
|
200
|
+
START=${Math.floor(chapter.startTime * 1e3)}
|
|
201
|
+
END=${Math.floor(chapter.endTime * 1e3)}
|
|
202
|
+
`;
|
|
203
|
+
if (chapter.title) {
|
|
204
|
+
chapterFileContents += `TITLE=${escapeFfmetadata(chapter.title)}
|
|
205
|
+
`;
|
|
206
|
+
}
|
|
207
|
+
chapterFileContents += "\n";
|
|
208
|
+
}
|
|
209
|
+
await writeFile(chapterFilePath, chapterFileContents);
|
|
210
|
+
args.push(`-i ${chapterFilePath}`);
|
|
211
|
+
metadataArgs.push(`-map_chapters 1`);
|
|
175
212
|
if (attachedPic) {
|
|
176
213
|
const imageExt = attachedPic.mimeType.split("/")[1];
|
|
177
214
|
picPath = join(
|
|
@@ -179,9 +216,9 @@ async function writeTrackMetadata(path, metadata, attachedPic) {
|
|
|
179
216
|
`storyteller-platform-audiobook-${randomUUID()}.${imageExt}`
|
|
180
217
|
);
|
|
181
218
|
await writeFile(picPath, attachedPic.data);
|
|
182
|
-
args.push(`-i ${
|
|
183
|
-
|
|
184
|
-
|
|
219
|
+
args.push(`-i ${picPath}`);
|
|
220
|
+
metadataArgs.push(`-map 2:v`);
|
|
221
|
+
metadataArgs.push(`-disposition:v:0 attached_pic`);
|
|
185
222
|
if (attachedPic.name) {
|
|
186
223
|
metadataArgs.push(
|
|
187
224
|
`-metadata:s:v title="${escapeQuotes(attachedPic.name)}"`
|
package/dist/index.cjs
CHANGED
|
@@ -331,6 +331,13 @@ class Audiobook {
|
|
|
331
331
|
this.metadata.chapters = chapters;
|
|
332
332
|
return chapters;
|
|
333
333
|
}
|
|
334
|
+
async setChapters(chapters) {
|
|
335
|
+
if (this.entries.length > 1) {
|
|
336
|
+
throw new Error("Unable to set chapters for multi-file audiobook");
|
|
337
|
+
}
|
|
338
|
+
this.metadata.chapters = chapters;
|
|
339
|
+
await this.setValue((entry) => entry.setChapters(chapters));
|
|
340
|
+
}
|
|
334
341
|
async getResources() {
|
|
335
342
|
if (this.metadata.resources) return this.metadata.resources;
|
|
336
343
|
const resources = [];
|
package/dist/index.d.cts
CHANGED
|
@@ -55,6 +55,7 @@ declare class Audiobook {
|
|
|
55
55
|
setReleaseDate(date: Date): Promise<void>;
|
|
56
56
|
getDuration(): Promise<number>;
|
|
57
57
|
getChapters(): Promise<AudiobookChapter[]>;
|
|
58
|
+
setChapters(chapters: AudiobookChapter[]): Promise<void>;
|
|
58
59
|
getResources(): Promise<AudiobookResource[]>;
|
|
59
60
|
saveAndClose(): Promise<void>;
|
|
60
61
|
discardAndClose(): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -55,6 +55,7 @@ declare class Audiobook {
|
|
|
55
55
|
setReleaseDate(date: Date): Promise<void>;
|
|
56
56
|
getDuration(): Promise<number>;
|
|
57
57
|
getChapters(): Promise<AudiobookChapter[]>;
|
|
58
|
+
setChapters(chapters: AudiobookChapter[]): Promise<void>;
|
|
58
59
|
getResources(): Promise<AudiobookResource[]>;
|
|
59
60
|
saveAndClose(): Promise<void>;
|
|
60
61
|
discardAndClose(): void;
|
package/dist/index.js
CHANGED
|
@@ -245,6 +245,13 @@ class Audiobook {
|
|
|
245
245
|
this.metadata.chapters = chapters;
|
|
246
246
|
return chapters;
|
|
247
247
|
}
|
|
248
|
+
async setChapters(chapters) {
|
|
249
|
+
if (this.entries.length > 1) {
|
|
250
|
+
throw new Error("Unable to set chapters for multi-file audiobook");
|
|
251
|
+
}
|
|
252
|
+
this.metadata.chapters = chapters;
|
|
253
|
+
await this.setValue((entry) => entry.setChapters(chapters));
|
|
254
|
+
}
|
|
248
255
|
async getResources() {
|
|
249
256
|
if (this.metadata.resources) return this.metadata.resources;
|
|
250
257
|
const resources = [];
|