utilitas 2000.3.25 → 2000.3.27
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/README.md +4 -12
- package/dist/utilitas.lite.mjs +1 -1
- package/dist/utilitas.lite.mjs.map +1 -1
- package/index.mjs +2 -3
- package/lib/alan.mjs +180 -32
- package/lib/manifest.mjs +1 -1
- package/lib/speech.mjs +9 -37
- package/package.json +1 -1
- package/lib/gen.mjs +0 -209
package/lib/gen.mjs
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ensureArray, ensureString, log as _log, need, throwError,
|
|
3
|
-
tryUntil, timeout,
|
|
4
|
-
} from './utilitas.mjs';
|
|
5
|
-
|
|
6
|
-
import { convert, MIME_PNG, MIME_MP4, getTempPath } from './storage.mjs';
|
|
7
|
-
import { createReadStream } from 'fs';
|
|
8
|
-
|
|
9
|
-
const _NEED = ['OpenAI', '@google/genai'];
|
|
10
|
-
const log = (cnt, opt) => _log(cnt, import.meta.url, { time: 1, ...opt || {} });
|
|
11
|
-
const [
|
|
12
|
-
clients, OPENAI, GOOGLE, BASE64, FILE, BUFFER, ERROR_GENERATING,
|
|
13
|
-
IMAGEN_MODEL, OPENAI_MODEL, VEO_MODEL, IMAGEN_UPSCALE_MODEL,
|
|
14
|
-
] = [
|
|
15
|
-
{}, 'OPENAI', 'GOOGLE', 'BASE64', 'FILE', 'BUFFER',
|
|
16
|
-
'Error generating media.', 'imagen-4.0-ultra-generate-001',
|
|
17
|
-
'gpt-image-1', 'veo-3.1-generate-preview', 'imagen-4.0-upscale-preview',
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
const init = async (options) => {
|
|
21
|
-
assert(options?.apiKey, 'API key is required.');
|
|
22
|
-
const provider = ensureString(options?.provider, { case: 'UP' });
|
|
23
|
-
switch (provider) {
|
|
24
|
-
case OPENAI:
|
|
25
|
-
const OpenAI = await need('openai');
|
|
26
|
-
var client = new OpenAI(options);
|
|
27
|
-
clients[provider] = {
|
|
28
|
-
image: client.images,
|
|
29
|
-
toFile: OpenAI.toFile,
|
|
30
|
-
};
|
|
31
|
-
break;
|
|
32
|
-
case GOOGLE:
|
|
33
|
-
const { GoogleGenAI } = await need('@google/genai');
|
|
34
|
-
var client = new GoogleGenAI({ vertexai: false, ...options });
|
|
35
|
-
clients[provider] = {
|
|
36
|
-
gen: client,
|
|
37
|
-
};
|
|
38
|
-
break;
|
|
39
|
-
default:
|
|
40
|
-
throw new Error('Invalid provider.');
|
|
41
|
-
}
|
|
42
|
-
return clients;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const extractImage = async (data, options) => await convert(
|
|
46
|
-
data, { input: BASE64, suffix: 'png', ...options || {} }
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
const extractVideo = async (data, options) => await convert(
|
|
50
|
-
data, { input: FILE, suffix: 'mp4', ...options || {} }
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
const prepareImage = async (files, repack, options) => {
|
|
54
|
-
if (!files) { return }
|
|
55
|
-
const multiple = Array.isArray(files);
|
|
56
|
-
files = ensureArray(files);
|
|
57
|
-
const resp = await Promise.all(files.map(async x => await repack(
|
|
58
|
-
createReadStream(await convert(
|
|
59
|
-
x, { expected: 'FILE', ...options || {} }
|
|
60
|
-
)), null, { type: MIME_PNG } // don't need to be right MIME type
|
|
61
|
-
)));
|
|
62
|
-
return multiple ? resp : resp[0];
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const image = async (prompt, options) => {
|
|
67
|
-
let provider = ensureString(options?.provider, { case: 'UP' });
|
|
68
|
-
if (!provider && clients?.[GOOGLE]) { provider = GOOGLE; }
|
|
69
|
-
else if (!provider && clients?.[OPENAI]) { provider = OPENAI; }
|
|
70
|
-
const client = clients?.[provider];
|
|
71
|
-
const n = options?.n || 4;
|
|
72
|
-
assert(client, 'No available image generation provider.');
|
|
73
|
-
prompt = ensureString(prompt);
|
|
74
|
-
assert(prompt.length <= 4000,
|
|
75
|
-
'Prompt must be less than 4000 characters.', 400);
|
|
76
|
-
options = {
|
|
77
|
-
...options || {},
|
|
78
|
-
expected: ensureString(options?.expected || BUFFER, { case: 'LOW' }),
|
|
79
|
-
};
|
|
80
|
-
switch (provider) {
|
|
81
|
-
case OPENAI:
|
|
82
|
-
let [func, extraOptions] = ['generate', {}];
|
|
83
|
-
if (options?.reference || options?.mask) {
|
|
84
|
-
func = 'edit';
|
|
85
|
-
extraOptions = {
|
|
86
|
-
image: await prepareImage(options?.reference, client.toFile, options),
|
|
87
|
-
mask: await prepareImage(options?.mask, client.toFile, options),
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
try { // https://platform.openai.com/docs/guides/image-generation?image-generation-model=gpt-image-1
|
|
91
|
-
var resp = await client.image[func]({
|
|
92
|
-
prompt, model: OPENAI_MODEL, n, quality: 'high',
|
|
93
|
-
size: '1536x1024', moderation: 'low',
|
|
94
|
-
// 1024x1024 (square), 1536x1024 (landscape), 1024x1536 (portrait), auto (default)
|
|
95
|
-
// background: 'transparent',
|
|
96
|
-
...extraOptions, ...options?.params || {},
|
|
97
|
-
});
|
|
98
|
-
} catch (err) { throwError(err?.message || ERROR_GENERATING); }
|
|
99
|
-
if (!options?.raw) {
|
|
100
|
-
resp.data = await Promise.all(resp.data.map(async x => ({
|
|
101
|
-
caption: `🎨 by ${OPENAI_MODEL}`,
|
|
102
|
-
data: await extractImage(x.b64_json, {
|
|
103
|
-
...options || {}, input: BASE64,
|
|
104
|
-
}),
|
|
105
|
-
mimeType: MIME_PNG,
|
|
106
|
-
})));
|
|
107
|
-
}
|
|
108
|
-
return resp?.data;
|
|
109
|
-
case GOOGLE:
|
|
110
|
-
var resp = await client.gen.models.generateImages({
|
|
111
|
-
model: IMAGEN_MODEL, prompt, config: {
|
|
112
|
-
numberOfImages: n, sampleImageSize: '2K',
|
|
113
|
-
includeRaiReason: true,
|
|
114
|
-
// "1:1" (default), "3:4", "4:3", "9:16", and "16:9"
|
|
115
|
-
aspectRatio: '16:9', personGeneration: 'allow_adult',
|
|
116
|
-
...options?.config || {},
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
const generated = resp?.generatedImages;
|
|
120
|
-
assert(!resp?.error && generated?.filter(
|
|
121
|
-
x => !x.raiFilteredReason
|
|
122
|
-
).length, resp?.error?.message || generated?.find(
|
|
123
|
-
x => x.raiFilteredReason
|
|
124
|
-
)?.raiFilteredReason || ERROR_GENERATING);
|
|
125
|
-
if (!options?.raw) {
|
|
126
|
-
resp = await Promise.all((resp?.generatedImages || []).map(
|
|
127
|
-
async x => ({
|
|
128
|
-
caption: `🎨 by ${IMAGEN_MODEL}`,
|
|
129
|
-
data: await extractImage(x.image.imageBytes, options),
|
|
130
|
-
mimeType: x.mimeType,
|
|
131
|
-
})
|
|
132
|
-
));
|
|
133
|
-
}
|
|
134
|
-
return resp;
|
|
135
|
-
default:
|
|
136
|
-
throw new Error('Invalid provider.');
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const video = async (prompt, options) => {
|
|
141
|
-
let provider = ensureString(options?.provider, { case: 'UP' });
|
|
142
|
-
if (!provider && clients?.[GOOGLE]) { provider = GOOGLE; }
|
|
143
|
-
const client = clients?.[provider];
|
|
144
|
-
assert(client, 'No available video generation provider.');
|
|
145
|
-
prompt = ensureString(prompt);
|
|
146
|
-
assert(prompt.length <= 4000,
|
|
147
|
-
'Prompt must be less than 4000 characters.', 400);
|
|
148
|
-
options = {
|
|
149
|
-
...options || {},
|
|
150
|
-
expected: ensureString(options?.expected || BUFFER, { case: 'LOW' }),
|
|
151
|
-
};
|
|
152
|
-
switch (provider) {
|
|
153
|
-
case GOOGLE:
|
|
154
|
-
var resp = await client.gen.models.generateVideos({
|
|
155
|
-
model: VEO_MODEL, prompt, config: {
|
|
156
|
-
aspectRatio: '16:9', numberOfVideos: 1,
|
|
157
|
-
// personGeneration: 'allow_adult',
|
|
158
|
-
enablePromptRewriting: true, addWatermark: false,
|
|
159
|
-
includeRaiReason: true, ...options?.config || {},
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
assert(!resp?.error, resp?.error?.message || ERROR_GENERATING);
|
|
163
|
-
if (options?.generateRaw) { return resp; }
|
|
164
|
-
await tryUntil(async () => {
|
|
165
|
-
resp = await client.gen.operations.getVideosOperation({
|
|
166
|
-
operation: resp,
|
|
167
|
-
});
|
|
168
|
-
assert(
|
|
169
|
-
resp?.done,
|
|
170
|
-
`Waiting for Google video generation: ${resp.name}`,
|
|
171
|
-
);
|
|
172
|
-
}, { maxTry: 60 * 10, log });
|
|
173
|
-
let generated = resp?.response?.generatedVideos;
|
|
174
|
-
assert(!resp?.error && generated?.filter(
|
|
175
|
-
x => !x.raiFilteredReason
|
|
176
|
-
).length, resp?.error?.message || generated?.find(
|
|
177
|
-
x => x.raiFilteredReason
|
|
178
|
-
)?.raiFilteredReason || ERROR_GENERATING);
|
|
179
|
-
if (!options?.videoRaw) {
|
|
180
|
-
generated = await Promise.all(generated?.filter(
|
|
181
|
-
x => x?.video?.uri
|
|
182
|
-
).map(async (x, i) => {
|
|
183
|
-
const downloadPath = `${getTempPath({
|
|
184
|
-
seed: x?.video?.uri
|
|
185
|
-
})}.mp4`;
|
|
186
|
-
// @todo: fix this
|
|
187
|
-
// https://github.com/googleapis/js-genai/compare/main...Leask:js-genai:main
|
|
188
|
-
await client.gen.files.download({ file: x, downloadPath });
|
|
189
|
-
await timeout(1000 * 10); // hack to wait for file to be downloaded
|
|
190
|
-
return {
|
|
191
|
-
caption: `🎥 by ${VEO_MODEL}`,
|
|
192
|
-
data: await extractVideo(downloadPath, options),
|
|
193
|
-
mimeType: MIME_MP4, jobId: resp.name,
|
|
194
|
-
};
|
|
195
|
-
}));
|
|
196
|
-
}
|
|
197
|
-
return generated;
|
|
198
|
-
default:
|
|
199
|
-
throw new Error('Invalid provider.');
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
export default init;
|
|
204
|
-
export {
|
|
205
|
-
_NEED,
|
|
206
|
-
image,
|
|
207
|
-
init,
|
|
208
|
-
video,
|
|
209
|
-
};
|