@storyteller-platform/audiobook 0.2.0 → 0.3.3
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 +56 -194
- package/dist/entry.d.cts +14 -15
- package/dist/entry.d.ts +14 -15
- package/dist/entry.js +58 -207
- package/dist/ffmpeg.cjs +199 -19
- package/dist/ffmpeg.d.cts +60 -4
- package/dist/ffmpeg.d.ts +60 -4
- package/dist/ffmpeg.js +196 -18
- package/dist/index.cjs +52 -56
- package/dist/index.d.cts +10 -15
- package/dist/index.d.ts +10 -15
- package/dist/index.js +54 -58
- package/dist/mime.cjs +112 -0
- package/dist/mime.d.cts +40 -0
- package/dist/mime.d.ts +40 -0
- package/dist/mime.js +75 -0
- package/dist/resources.d.cts +1 -1
- package/dist/resources.d.ts +1 -1
- package/package.json +1 -2
- package/dist/bufferEntry.cjs +0 -59
- package/dist/bufferEntry.d.cts +0 -16
- package/dist/bufferEntry.d.ts +0 -16
- package/dist/bufferEntry.js +0 -35
- package/dist/fileEntry.cjs +0 -58
- package/dist/fileEntry.d.cts +0 -16
- package/dist/fileEntry.d.ts +0 -16
- package/dist/fileEntry.js +0 -34
- package/dist/tagMaps.cjs +0 -120
- package/dist/tagMaps.d.cts +0 -24
- package/dist/tagMaps.d.ts +0 -24
- package/dist/tagMaps.js +0 -95
- package/dist/zipFsEntry.cjs +0 -65
- package/dist/zipFsEntry.d.cts +0 -19
- package/dist/zipFsEntry.d.ts +0 -19
- package/dist/zipFsEntry.js +0 -41
package/dist/entry.cjs
CHANGED
|
@@ -21,265 +21,127 @@ __export(entry_exports, {
|
|
|
21
21
|
AudiobookEntry: () => AudiobookEntry
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(entry_exports);
|
|
24
|
-
var
|
|
25
|
-
var
|
|
24
|
+
var import_ffmpeg = require("./ffmpeg.cjs");
|
|
25
|
+
var import_mime = require("./mime.cjs");
|
|
26
26
|
function splitNames(names) {
|
|
27
|
+
if (!names) return [];
|
|
27
28
|
return names.split(/[;,/]/).map((name) => name.trim());
|
|
28
29
|
}
|
|
29
30
|
class AudiobookEntry {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.
|
|
36
|
-
return this.
|
|
31
|
+
constructor(filename) {
|
|
32
|
+
this.filename = filename;
|
|
33
|
+
}
|
|
34
|
+
info = null;
|
|
35
|
+
async getInfo() {
|
|
36
|
+
this.info ??= await (0, import_ffmpeg.getTrackMetadata)(this.filename);
|
|
37
|
+
return this.info;
|
|
37
38
|
}
|
|
38
|
-
async
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
switch (inputFormat) {
|
|
42
|
-
case import_mediabunny.MP3: {
|
|
43
|
-
return new import_mediabunny.Mp3OutputFormat();
|
|
44
|
-
}
|
|
45
|
-
case import_mediabunny.MP4: {
|
|
46
|
-
return new import_mediabunny.Mp4OutputFormat();
|
|
47
|
-
}
|
|
48
|
-
case import_mediabunny.WAVE: {
|
|
49
|
-
return new import_mediabunny.WavOutputFormat();
|
|
50
|
-
}
|
|
51
|
-
case import_mediabunny.OGG: {
|
|
52
|
-
return new import_mediabunny.OggOutputFormat();
|
|
53
|
-
}
|
|
54
|
-
case import_mediabunny.FLAC: {
|
|
55
|
-
return new import_mediabunny.FlacOutputFormat();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return null;
|
|
39
|
+
async getMetadataTags() {
|
|
40
|
+
const info = await this.getInfo();
|
|
41
|
+
return info.tags;
|
|
59
42
|
}
|
|
60
43
|
async getTitle() {
|
|
61
44
|
const tags = await this.getMetadataTags();
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
return null;
|
|
45
|
+
return tags.album ?? tags.title ?? null;
|
|
46
|
+
}
|
|
47
|
+
async setTitle(title) {
|
|
48
|
+
const tags = await this.getMetadataTags();
|
|
49
|
+
tags.album = title;
|
|
69
50
|
}
|
|
70
51
|
async getTrackTitle() {
|
|
71
52
|
const tags = await this.getMetadataTags();
|
|
72
|
-
|
|
73
|
-
for (const tag of import_tagMaps.readTagMap.trackTitle) {
|
|
74
|
-
if (typeof tags.raw[tag] === "string") {
|
|
75
|
-
return tags.raw[tag];
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return null;
|
|
53
|
+
return tags.title ?? null;
|
|
79
54
|
}
|
|
80
|
-
async
|
|
55
|
+
async setTrackTitle(trackTitle) {
|
|
81
56
|
const tags = await this.getMetadataTags();
|
|
82
|
-
|
|
83
|
-
const inputFormat = await input.getFormat();
|
|
84
|
-
const writeTags = (0, import_tagMaps.getWriteTags)(inputFormat, "title");
|
|
85
|
-
tags.raw ??= {};
|
|
86
|
-
for (const tag of writeTags) {
|
|
87
|
-
tags.raw[tag] = title;
|
|
88
|
-
}
|
|
57
|
+
tags.title = trackTitle;
|
|
89
58
|
}
|
|
90
59
|
async getSubtitle() {
|
|
91
60
|
const tags = await this.getMetadataTags();
|
|
92
|
-
|
|
93
|
-
for (const subtitleTag of import_tagMaps.readTagMap.subtitle) {
|
|
94
|
-
if (typeof tags.raw[subtitleTag] === "string") {
|
|
95
|
-
return tags.raw[subtitleTag];
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return null;
|
|
61
|
+
return tags.subtitle ?? null;
|
|
99
62
|
}
|
|
100
63
|
async setSubtitle(subtitle) {
|
|
101
64
|
const tags = await this.getMetadataTags();
|
|
102
|
-
|
|
103
|
-
const inputFormat = await input.getFormat();
|
|
104
|
-
const writeTags = (0, import_tagMaps.getWriteTags)(inputFormat, "subtitle");
|
|
105
|
-
tags.raw ??= {};
|
|
106
|
-
for (const tag of writeTags) {
|
|
107
|
-
tags.raw[tag] = subtitle;
|
|
108
|
-
}
|
|
65
|
+
tags.subtitle = subtitle;
|
|
109
66
|
}
|
|
110
67
|
async getDescription() {
|
|
111
68
|
const tags = await this.getMetadataTags();
|
|
112
|
-
|
|
113
|
-
for (const tag of import_tagMaps.readTagMap.description) {
|
|
114
|
-
if (typeof tags.raw[tag] === "string") {
|
|
115
|
-
return tags.raw[tag];
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return null;
|
|
69
|
+
return tags.description ?? tags.comment ?? null;
|
|
119
70
|
}
|
|
120
71
|
async setDescription(description) {
|
|
121
72
|
const tags = await this.getMetadataTags();
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const writeTags = (0, import_tagMaps.getWriteTags)(inputFormat, "description");
|
|
125
|
-
tags.raw ??= {};
|
|
126
|
-
for (const tag of writeTags) {
|
|
127
|
-
tags.raw[tag] = description;
|
|
128
|
-
}
|
|
73
|
+
tags.description = description;
|
|
74
|
+
tags.comment = description;
|
|
129
75
|
}
|
|
130
76
|
async getAuthors() {
|
|
131
77
|
const tags = await this.getMetadataTags();
|
|
132
|
-
|
|
133
|
-
for (const tag of import_tagMaps.readTagMap.authors) {
|
|
134
|
-
if (typeof tags.raw[tag] === "string") {
|
|
135
|
-
return splitNames(tags.raw[tag]);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return [];
|
|
78
|
+
return splitNames(tags.albumArtist ?? tags.artist);
|
|
139
79
|
}
|
|
140
80
|
async setAuthors(authors) {
|
|
141
81
|
const tags = await this.getMetadataTags();
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const writeTags = (0, import_tagMaps.getWriteTags)(inputFormat, "authors");
|
|
145
|
-
tags.raw ??= {};
|
|
146
|
-
for (const tag of writeTags) {
|
|
147
|
-
tags.raw[tag] = authors.join(";");
|
|
148
|
-
}
|
|
82
|
+
tags.artist = authors.join(";");
|
|
83
|
+
tags.albumArtist = authors.join(";");
|
|
149
84
|
}
|
|
150
85
|
async getNarrators() {
|
|
151
86
|
const tags = await this.getMetadataTags();
|
|
152
|
-
|
|
153
|
-
for (const tag of import_tagMaps.readTagMap.narrators) {
|
|
154
|
-
if (typeof tags.raw[tag] === "string") {
|
|
155
|
-
return splitNames(tags.raw[tag]);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
return [];
|
|
87
|
+
return splitNames(tags.composer ?? tags.performer);
|
|
159
88
|
}
|
|
160
89
|
async setNarrators(narrators) {
|
|
161
90
|
const tags = await this.getMetadataTags();
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const writeTags = (0, import_tagMaps.getWriteTags)(inputFormat, "narrators");
|
|
165
|
-
tags.raw ??= {};
|
|
166
|
-
for (const tag of writeTags) {
|
|
167
|
-
tags.raw[tag] = narrators.join(";");
|
|
168
|
-
}
|
|
91
|
+
tags.composer = narrators.join(";");
|
|
92
|
+
tags.performer = narrators.join(";");
|
|
169
93
|
}
|
|
170
94
|
async getCoverArt() {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return ((_a = tags.images) == null ? void 0 : _a.find((image) => image.kind === "coverFront")) ?? null;
|
|
95
|
+
const info = await this.getInfo();
|
|
96
|
+
return info.attachedPic || null;
|
|
174
97
|
}
|
|
175
98
|
async setCoverArt(picture) {
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
const frontCover = images.find((image) => image.kind === "coverFront");
|
|
179
|
-
if (frontCover) {
|
|
180
|
-
Object.assign(frontCover, picture);
|
|
181
|
-
} else {
|
|
182
|
-
images.push(picture);
|
|
183
|
-
}
|
|
184
|
-
tags.images = images;
|
|
99
|
+
const info = await this.getInfo();
|
|
100
|
+
info.attachedPic = picture;
|
|
185
101
|
}
|
|
186
102
|
async getPublisher() {
|
|
187
103
|
const tags = await this.getMetadataTags();
|
|
188
|
-
|
|
189
|
-
for (const tag of import_tagMaps.readTagMap.publisher) {
|
|
190
|
-
if (typeof tags.raw[tag] === "string") {
|
|
191
|
-
return tags.raw[tag];
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return null;
|
|
104
|
+
return tags.publisher ?? null;
|
|
195
105
|
}
|
|
196
106
|
async setPublisher(publisher) {
|
|
197
107
|
const tags = await this.getMetadataTags();
|
|
198
|
-
|
|
199
|
-
const inputFormat = await input.getFormat();
|
|
200
|
-
const writeTags = (0, import_tagMaps.getWriteTags)(inputFormat, "publisher");
|
|
201
|
-
tags.raw ??= {};
|
|
202
|
-
for (const tag of writeTags) {
|
|
203
|
-
tags.raw[tag] = publisher;
|
|
204
|
-
}
|
|
108
|
+
tags.publisher = publisher;
|
|
205
109
|
}
|
|
206
110
|
async getReleaseDate() {
|
|
207
111
|
const tags = await this.getMetadataTags();
|
|
208
|
-
|
|
209
|
-
for (const tag of import_tagMaps.readTagMap.releaseDate) {
|
|
210
|
-
if (typeof tags.raw[tag] === "string") {
|
|
211
|
-
return new Date(tags.raw[tag]);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return null;
|
|
112
|
+
return tags.date ? new Date(tags.date) : null;
|
|
215
113
|
}
|
|
216
114
|
async setReleaseDate(date) {
|
|
217
115
|
const tags = await this.getMetadataTags();
|
|
218
|
-
|
|
219
|
-
const inputFormat = await input.getFormat();
|
|
220
|
-
const writeTags = (0, import_tagMaps.getWriteTags)(inputFormat, "releaseDate");
|
|
221
|
-
tags.raw ??= {};
|
|
222
|
-
for (const tag of writeTags) {
|
|
223
|
-
tags.raw[tag] = `${date.getDate().toString().padStart(2, "0")}-${date.getMonth().toString().padStart(2, "0")}-${date.getFullYear()}`;
|
|
224
|
-
}
|
|
116
|
+
tags.date = `${date.getDate().toString().padStart(2, "0")}-${date.getMonth().toString().padStart(2, "0")}-${date.getFullYear()}`;
|
|
225
117
|
}
|
|
226
118
|
async getDuration() {
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
return this.duration;
|
|
119
|
+
const info = await this.getInfo();
|
|
120
|
+
return info.duration;
|
|
230
121
|
}
|
|
231
122
|
async getResource() {
|
|
232
|
-
const
|
|
233
|
-
this.duration ??= await input.computeDuration();
|
|
123
|
+
const duration = await this.getDuration();
|
|
234
124
|
const title = await this.getTrackTitle() ?? null;
|
|
235
|
-
const type =
|
|
125
|
+
const type = (0, import_mime.lookupAudioMime)(this.filename);
|
|
236
126
|
return {
|
|
237
127
|
filename: this.filename,
|
|
238
128
|
title,
|
|
239
129
|
type,
|
|
240
|
-
duration
|
|
130
|
+
duration,
|
|
241
131
|
bitrate: null
|
|
242
132
|
};
|
|
243
133
|
}
|
|
244
|
-
async
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
target: new import_mediabunny.BufferTarget()
|
|
256
|
-
});
|
|
257
|
-
const tags = await this.getMetadataTags();
|
|
258
|
-
const conversion = await import_mediabunny.Conversion.init({
|
|
259
|
-
input,
|
|
260
|
-
output,
|
|
261
|
-
tags: {
|
|
262
|
-
// Since we only write raw metadata tags, we
|
|
263
|
-
// only copy those into the output. Otherwise
|
|
264
|
-
// the unchanged parsed metadata tags will overwrite
|
|
265
|
-
// our changes to raw!
|
|
266
|
-
raw: tags.raw ?? {},
|
|
267
|
-
images: tags.images ?? []
|
|
268
|
-
},
|
|
269
|
-
showWarnings: false
|
|
270
|
-
});
|
|
271
|
-
if (!conversion.isValid) {
|
|
272
|
-
throw new Error(
|
|
273
|
-
conversion.discardedTracks.map((track) => track.reason).join(";")
|
|
274
|
-
);
|
|
275
|
-
}
|
|
276
|
-
await conversion.execute();
|
|
277
|
-
input.dispose();
|
|
278
|
-
return {
|
|
279
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
280
|
-
data: new Uint8Array(output.target.buffer),
|
|
281
|
-
filename: this.filename
|
|
282
|
-
};
|
|
134
|
+
async getChapters() {
|
|
135
|
+
const info = await this.getInfo();
|
|
136
|
+
return info.chapters.map((chapter) => ({
|
|
137
|
+
filename: this.filename,
|
|
138
|
+
title: chapter.title ?? null,
|
|
139
|
+
start: chapter.startTime
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
async saveAndClose() {
|
|
143
|
+
const info = await this.getInfo();
|
|
144
|
+
await (0, import_ffmpeg.writeTrackMetadata)(this.filename, info.tags, info.attachedPic);
|
|
283
145
|
}
|
|
284
146
|
}
|
|
285
147
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/entry.d.cts
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { TrackInfo, AttachedPic } from './ffmpeg.cjs';
|
|
2
|
+
import { AudiobookResource, AudiobookChapter } from './resources.cjs';
|
|
3
3
|
|
|
4
4
|
interface Uint8ArrayEntry {
|
|
5
5
|
filename: string;
|
|
6
6
|
data: Uint8Array;
|
|
7
7
|
}
|
|
8
|
-
declare
|
|
9
|
-
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
abstract saveAndClose(): Promise<void>;
|
|
15
|
-
getMetadataTags(): Promise<MetadataTags>;
|
|
16
|
-
getOutputFormat(): Promise<OutputFormat | null>;
|
|
8
|
+
declare class AudiobookEntry {
|
|
9
|
+
filename: string;
|
|
10
|
+
private info;
|
|
11
|
+
constructor(filename: string);
|
|
12
|
+
getInfo(): Promise<TrackInfo>;
|
|
13
|
+
getMetadataTags(): Promise<TrackInfo["tags"]>;
|
|
17
14
|
getTitle(): Promise<string | null>;
|
|
18
|
-
getTrackTitle(): Promise<string | null>;
|
|
19
15
|
setTitle(title: string): Promise<void>;
|
|
16
|
+
getTrackTitle(): Promise<string | null>;
|
|
17
|
+
setTrackTitle(trackTitle: string): Promise<void>;
|
|
20
18
|
getSubtitle(): Promise<string | null>;
|
|
21
19
|
setSubtitle(subtitle: string): Promise<void>;
|
|
22
20
|
getDescription(): Promise<string | null>;
|
|
@@ -25,15 +23,16 @@ declare abstract class AudiobookEntry {
|
|
|
25
23
|
setAuthors(authors: string[]): Promise<void>;
|
|
26
24
|
getNarrators(): Promise<string[]>;
|
|
27
25
|
setNarrators(narrators: string[]): Promise<void>;
|
|
28
|
-
getCoverArt(): Promise<
|
|
29
|
-
setCoverArt(picture:
|
|
26
|
+
getCoverArt(): Promise<AttachedPic | null>;
|
|
27
|
+
setCoverArt(picture: AttachedPic): Promise<void>;
|
|
30
28
|
getPublisher(): Promise<string | null>;
|
|
31
29
|
setPublisher(publisher: string): Promise<void>;
|
|
32
30
|
getReleaseDate(): Promise<Date | null>;
|
|
33
31
|
setReleaseDate(date: Date): Promise<void>;
|
|
34
32
|
getDuration(): Promise<number>;
|
|
35
33
|
getResource(): Promise<AudiobookResource>;
|
|
36
|
-
|
|
34
|
+
getChapters(): Promise<AudiobookChapter[]>;
|
|
35
|
+
saveAndClose(): Promise<void>;
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
export { AudiobookEntry, type Uint8ArrayEntry };
|
package/dist/entry.d.ts
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { TrackInfo, AttachedPic } from './ffmpeg.js';
|
|
2
|
+
import { AudiobookResource, AudiobookChapter } from './resources.js';
|
|
3
3
|
|
|
4
4
|
interface Uint8ArrayEntry {
|
|
5
5
|
filename: string;
|
|
6
6
|
data: Uint8Array;
|
|
7
7
|
}
|
|
8
|
-
declare
|
|
9
|
-
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
abstract saveAndClose(): Promise<void>;
|
|
15
|
-
getMetadataTags(): Promise<MetadataTags>;
|
|
16
|
-
getOutputFormat(): Promise<OutputFormat | null>;
|
|
8
|
+
declare class AudiobookEntry {
|
|
9
|
+
filename: string;
|
|
10
|
+
private info;
|
|
11
|
+
constructor(filename: string);
|
|
12
|
+
getInfo(): Promise<TrackInfo>;
|
|
13
|
+
getMetadataTags(): Promise<TrackInfo["tags"]>;
|
|
17
14
|
getTitle(): Promise<string | null>;
|
|
18
|
-
getTrackTitle(): Promise<string | null>;
|
|
19
15
|
setTitle(title: string): Promise<void>;
|
|
16
|
+
getTrackTitle(): Promise<string | null>;
|
|
17
|
+
setTrackTitle(trackTitle: string): Promise<void>;
|
|
20
18
|
getSubtitle(): Promise<string | null>;
|
|
21
19
|
setSubtitle(subtitle: string): Promise<void>;
|
|
22
20
|
getDescription(): Promise<string | null>;
|
|
@@ -25,15 +23,16 @@ declare abstract class AudiobookEntry {
|
|
|
25
23
|
setAuthors(authors: string[]): Promise<void>;
|
|
26
24
|
getNarrators(): Promise<string[]>;
|
|
27
25
|
setNarrators(narrators: string[]): Promise<void>;
|
|
28
|
-
getCoverArt(): Promise<
|
|
29
|
-
setCoverArt(picture:
|
|
26
|
+
getCoverArt(): Promise<AttachedPic | null>;
|
|
27
|
+
setCoverArt(picture: AttachedPic): Promise<void>;
|
|
30
28
|
getPublisher(): Promise<string | null>;
|
|
31
29
|
setPublisher(publisher: string): Promise<void>;
|
|
32
30
|
getReleaseDate(): Promise<Date | null>;
|
|
33
31
|
setReleaseDate(date: Date): Promise<void>;
|
|
34
32
|
getDuration(): Promise<number>;
|
|
35
33
|
getResource(): Promise<AudiobookResource>;
|
|
36
|
-
|
|
34
|
+
getChapters(): Promise<AudiobookChapter[]>;
|
|
35
|
+
saveAndClose(): Promise<void>;
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
export { AudiobookEntry, type Uint8ArrayEntry };
|