@makefully/dutifully 1.13.0 → 1.13.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.13.1
4
+
5
+ - Harden `say` / ElevenLabs export when the result zip has no MP3 (clearer error, no unhandled ENOENT from ID3 metadata).
6
+
3
7
  ## 1.13.0
4
8
 
5
9
  - Add `packfully` service client for packing images into texture atlases.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makefully/dutifully",
3
- "version": "1.13.0",
3
+ "version": "1.13.1",
4
4
  "description": "Client tools for Cheerfully service.",
5
5
  "main": "./src/index.js",
6
6
  "bin": {
@@ -82,8 +82,12 @@ const
82
82
  await ensureDir(output);
83
83
  }
84
84
 
85
- Object.keys(captions).forEach(async (id) => {
85
+ const
86
+ ids = Object.keys(captions);
87
+
88
+ for (let i = 0; i < ids.length; i++) {
86
89
  const
90
+ id = ids[i],
87
91
  text = captionText(captions[id]),
88
92
  tags = {
89
93
  album,
@@ -95,13 +99,13 @@ const
95
99
  };
96
100
 
97
101
  await id3.update(tags, `${output}${id}.mp3`);
98
-
102
+
99
103
  if (generated) {
100
104
  console.log(`Voice generated for "${id}".`);
101
105
  } else {
102
106
  console.log(`Voice meta data updated for "${id}".`);
103
107
  }
104
- });
108
+ }
105
109
  },
106
110
  mapReduction = (map, list) => list.reduce((obj, file) => {
107
111
  const
@@ -167,7 +171,7 @@ const
167
171
  }
168
172
 
169
173
  if (updateAllMetaData && present.length) {
170
- appendMP3Meta({
174
+ await appendMP3Meta({
171
175
  album,
172
176
  captions: mapReduction(files, present),
173
177
  language,
@@ -186,9 +190,39 @@ const
186
190
  const
187
191
  {album, encodedBy, config, transcripts, updateList} = this,
188
192
  {files, output, language, voice} = config,
189
- list = updateList ?? Object.keys(files).map((id) => `${id}.mp3`);
193
+ list = updateList ?? Object.keys(files).map((id) => `${id}.mp3`),
194
+ missing = [];
195
+
196
+ for (let i = 0; i < list.length; i++) {
197
+ const
198
+ filename = list[i],
199
+ fullPath = `${output}${filename}`;
200
+
201
+ try {
202
+ await fs.access(fullPath);
203
+ } catch (e) {
204
+ missing.push(filename);
205
+ }
206
+ }
207
+
208
+ if (missing.length) {
209
+ let detail = '';
210
+
211
+ try {
212
+ const
213
+ log = JSON.parse(await fs.readFile(`${output}log.json`, 'utf8'));
214
+
215
+ if (log?.errors?.length) {
216
+ detail = ` Server errors: ${log.errors.join('; ')}`;
217
+ }
218
+ } catch (e) { /* no log.json */ }
219
+
220
+ throw new Error(
221
+ `Voice export missing ${missing.length === 1 ? `"${missing[0]}"` : `${missing.length} files (${missing.join(', ')})`}.${detail}`
222
+ );
223
+ }
190
224
 
191
- appendMP3Meta({
225
+ await appendMP3Meta({
192
226
  album,
193
227
  captions: files,
194
228
  generated: true,
package/src/say.js CHANGED
@@ -59,17 +59,20 @@ const
59
59
  },
60
60
  path: '',
61
61
  voice,
62
- output
62
+ output,
63
+ extract: true
63
64
  },
64
65
  handler = new ElevenLabs({
65
66
  config,
66
67
  contents: {
67
68
  ...contents,
68
- service: 'elevenlabs'
69
+ service: 'elevenlabs',
70
+ extract: true
69
71
  }
70
72
  });
71
73
 
72
74
  delete config.script;
75
+ delete config.src;
73
76
 
74
77
  await handler.prepare({
75
78
  difference: false,
@@ -79,7 +82,30 @@ const
79
82
  instanceId: `${contents.id}-say`
80
83
  });
81
84
 
82
- return path.join(CACHE_DIR, `${key}.mp3`);
85
+ const
86
+ mp3File = path.join(CACHE_DIR, `${key}.mp3`);
87
+
88
+ try {
89
+ await fsp.access(mp3File);
90
+ } catch (e) {
91
+ let detail = '';
92
+
93
+ try {
94
+ const
95
+ log = JSON.parse(await fsp.readFile(path.join(CACHE_DIR, 'log.json'), 'utf8'));
96
+
97
+ if (log?.errors?.length) {
98
+ detail = ` ${log.errors.join('; ')}`;
99
+ }
100
+ } catch (err) { /* ignore */ }
101
+
102
+ throw new Error(
103
+ `Speech generation finished but "${mp3File}" was not created.${detail} ` +
104
+ 'Check that the Cheerfully worker is running and picking up elevenlabs chores.'
105
+ );
106
+ }
107
+
108
+ return mp3File;
83
109
  };
84
110
 
85
111
  module.exports = async (textOrArgs = {}) => {