motionrender 0.2.4 → 0.2.5
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/cli.js +71 -14
- package/dist/types/packages/ai/src/providers.d.ts +6 -0
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -2951,25 +2951,23 @@ function inferChatTask(messages2, options3) {
|
|
|
2951
2951
|
return "compose";
|
|
2952
2952
|
}
|
|
2953
2953
|
function createProvider(config = {}) {
|
|
2954
|
-
const id2 = (config.provider || process.env.OVE_AI_PROVIDER || (process.env.FREELLMAPI_BASE_URL ? "freellmapi" : "") || (process.env.NVIDIA_API_KEY ? "nvidia" : process.env.GROQ_API_KEY ? "groq" : process.env.ANTHROPIC_API_KEY ? "anthropic" : "")).toLowerCase();
|
|
2954
|
+
const id2 = (config.provider || process.env.OVE_AI_PROVIDER || (process.env.FREELLMAPI_BASE_URL || process.env.FREELLMAPI_API_KEY ? "freellmapi" : "") || (process.env.NVIDIA_API_KEY ? "nvidia" : process.env.GROQ_API_KEY ? "groq" : process.env.ANTHROPIC_API_KEY ? "anthropic" : "") || "freellmapi").toLowerCase();
|
|
2955
2955
|
switch (id2) {
|
|
2956
|
+
case "mock":
|
|
2957
|
+
return new MockProvider();
|
|
2956
2958
|
case "freellmapi":
|
|
2957
2959
|
case "openai":
|
|
2958
|
-
return
|
|
2960
|
+
return new FreeLlmApiProvider(config);
|
|
2961
|
+
case "groq":
|
|
2962
|
+
return new GroqProvider(config);
|
|
2959
2963
|
case "nvidia":
|
|
2960
2964
|
case "nim":
|
|
2961
2965
|
return attachGroqAudio(new NvidiaProvider(config), config);
|
|
2962
2966
|
case "anthropic":
|
|
2963
2967
|
case "claude":
|
|
2964
2968
|
return attachGroqAudio(new AnthropicProvider(config), config);
|
|
2965
|
-
case "groq":
|
|
2966
|
-
return new GroqProvider(config);
|
|
2967
|
-
case "mock":
|
|
2968
|
-
return new MockProvider();
|
|
2969
|
-
case "":
|
|
2970
|
-
throw new Error("No AI provider chosen: pass --provider freellmapi|nvidia|groq|anthropic|mock, or set FREELLMAPI_BASE_URL, NVIDIA_API_KEY, GROQ_API_KEY or ANTHROPIC_API_KEY");
|
|
2971
2969
|
default:
|
|
2972
|
-
|
|
2970
|
+
return new FreeLlmApiProvider(config);
|
|
2973
2971
|
}
|
|
2974
2972
|
}
|
|
2975
2973
|
function describeProvider(provider) {
|
|
@@ -3259,6 +3257,65 @@ var init_providers = __esm({
|
|
|
3259
3257
|
if (!text) throw new Error("FreeLLMAPI chat returned no text. Check active models and upstream keys in your FreeLLMAPI dashboard.");
|
|
3260
3258
|
return text;
|
|
3261
3259
|
}
|
|
3260
|
+
async speak(text, options3 = {}) {
|
|
3261
|
+
const response = await request(`${this.baseUrl}/audio/speech`, {
|
|
3262
|
+
method: "POST",
|
|
3263
|
+
signal: timeoutSignal(options3.signal),
|
|
3264
|
+
headers: jsonHeaders(this.headers()),
|
|
3265
|
+
body: JSON.stringify({
|
|
3266
|
+
model: "auto",
|
|
3267
|
+
input: text,
|
|
3268
|
+
voice: options3.voice ?? "alloy"
|
|
3269
|
+
})
|
|
3270
|
+
}, "FreeLLMAPI speech");
|
|
3271
|
+
return { data: new Uint8Array(await response.arrayBuffer()), extension: "mp3" };
|
|
3272
|
+
}
|
|
3273
|
+
async transcribe(audio, filename, options3 = {}) {
|
|
3274
|
+
const form = new FormData();
|
|
3275
|
+
form.append("file", new Blob([audio]), filename || "audio.mp3");
|
|
3276
|
+
form.append("model", "auto");
|
|
3277
|
+
form.append("response_format", "verbose_json");
|
|
3278
|
+
if (options3.language) form.append("language", options3.language);
|
|
3279
|
+
const response = await request(`${this.baseUrl}/audio/transcriptions`, {
|
|
3280
|
+
method: "POST",
|
|
3281
|
+
signal: timeoutSignal(options3.signal),
|
|
3282
|
+
headers: this.headers(),
|
|
3283
|
+
body: form
|
|
3284
|
+
}, "FreeLLMAPI transcription");
|
|
3285
|
+
const data = await response.json();
|
|
3286
|
+
return {
|
|
3287
|
+
text: String(data?.text ?? ""),
|
|
3288
|
+
words: Array.isArray(data?.words) ? data.words.map((w) => ({
|
|
3289
|
+
text: String(w.word ?? w.text ?? ""),
|
|
3290
|
+
start: Number(w.start) || 0,
|
|
3291
|
+
end: Number(w.end) || 0
|
|
3292
|
+
})) : [],
|
|
3293
|
+
cues: Array.isArray(data?.segments) ? data.segments.map((s) => ({
|
|
3294
|
+
text: String(s.text ?? ""),
|
|
3295
|
+
start: Number(s.start) || 0,
|
|
3296
|
+
end: Number(s.end) || 0
|
|
3297
|
+
})) : []
|
|
3298
|
+
};
|
|
3299
|
+
}
|
|
3300
|
+
async image(prompt, options3 = {}) {
|
|
3301
|
+
const size = options3.size ?? "1024x1024";
|
|
3302
|
+
const response = await request(`${this.baseUrl}/images/generations`, {
|
|
3303
|
+
method: "POST",
|
|
3304
|
+
signal: timeoutSignal(options3.signal),
|
|
3305
|
+
headers: jsonHeaders(this.headers()),
|
|
3306
|
+
body: JSON.stringify({
|
|
3307
|
+
model: "auto",
|
|
3308
|
+
prompt,
|
|
3309
|
+
n: 1,
|
|
3310
|
+
size,
|
|
3311
|
+
response_format: "b64_json"
|
|
3312
|
+
})
|
|
3313
|
+
}, "FreeLLMAPI image");
|
|
3314
|
+
const data = await response.json();
|
|
3315
|
+
const b64 = data?.data?.[0]?.b64_json;
|
|
3316
|
+
if (!b64) throw new Error("FreeLLMAPI did not return image data");
|
|
3317
|
+
return { data: Buffer.from(b64, "base64"), extension: "png" };
|
|
3318
|
+
}
|
|
3262
3319
|
};
|
|
3263
3320
|
attachGroqAudio = (provider, config) => {
|
|
3264
3321
|
if (provider.speak || provider.transcribe || !process.env.GROQ_API_KEY) return provider;
|
|
@@ -4521,7 +4578,7 @@ function narrationScene(composition, options3) {
|
|
|
4521
4578
|
return next;
|
|
4522
4579
|
}
|
|
4523
4580
|
async function narrate(provider, options3) {
|
|
4524
|
-
if (!provider.speak) throw new Error(`The ${provider.id} provider cannot make speech
|
|
4581
|
+
if (!provider.speak) throw new Error(`The ${provider.id} provider cannot make speech (or add a speak() adapter)`);
|
|
4525
4582
|
const brief = options3.brief?.trim();
|
|
4526
4583
|
let text = options3.text?.trim() ?? "";
|
|
4527
4584
|
if (!text && brief) {
|
|
@@ -4568,7 +4625,7 @@ async function narrate(provider, options3) {
|
|
|
4568
4625
|
return { audio: audioFile, captions: captionsFile, durationSeconds, words: transcript.words.length, composition, text };
|
|
4569
4626
|
}
|
|
4570
4627
|
async function captionAudio(provider, options3) {
|
|
4571
|
-
if (!provider.transcribe) throw new Error(`The ${provider.id} provider cannot transcribe
|
|
4628
|
+
if (!provider.transcribe) throw new Error(`The ${provider.id} provider cannot transcribe (or add a transcribe() adapter)`);
|
|
4572
4629
|
const audioFile = resolve6(options3.audio);
|
|
4573
4630
|
const data = await readFile8(audioFile);
|
|
4574
4631
|
options3.onProgress?.("Transcribing\u2026");
|
|
@@ -4819,7 +4876,7 @@ function editComposition(options3) {
|
|
|
4819
4876
|
return composition;
|
|
4820
4877
|
}
|
|
4821
4878
|
async function editVideo(provider, options3) {
|
|
4822
|
-
if (!provider.transcribe) throw new Error(`The ${provider.id} provider cannot transcribe
|
|
4879
|
+
if (!provider.transcribe) throw new Error(`The ${provider.id} provider cannot transcribe (or add a transcribe() adapter)`);
|
|
4823
4880
|
const clip2 = resolve7(options3.clip);
|
|
4824
4881
|
const outDir = resolve7(options3.outDir);
|
|
4825
4882
|
const width = options3.width ?? 1080, height = options3.height ?? 1920, fps = options3.fps ?? 30;
|
|
@@ -4927,7 +4984,7 @@ function shortsCandidatePlan(candidate, cut, maxSilence, keepFillers) {
|
|
|
4927
4984
|
return cut ? planCuts(slice, { maxSilence, keepFillers, padding: 0.2 }) : planCuts(slice, { maxSilence: Number.MAX_SAFE_INTEGER, keepFillers: true, padding: 0.2 });
|
|
4928
4985
|
}
|
|
4929
4986
|
async function shortsFrom(provider, options3) {
|
|
4930
|
-
if (!provider.transcribe) throw new Error(`The ${provider.id} provider cannot transcribe
|
|
4987
|
+
if (!provider.transcribe) throw new Error(`The ${provider.id} provider cannot transcribe (or add a transcribe() adapter)`);
|
|
4931
4988
|
const clip2 = resolve8(options3.clip);
|
|
4932
4989
|
const outDir = resolve8(options3.outDir);
|
|
4933
4990
|
const width = options3.width ?? 1080, height = options3.height ?? 1920, fps = options3.fps ?? 30;
|
|
@@ -5055,7 +5112,7 @@ function imageSize(size) {
|
|
|
5055
5112
|
return sizes[size.toLowerCase()] ?? size;
|
|
5056
5113
|
}
|
|
5057
5114
|
async function generateImage(provider, options3) {
|
|
5058
|
-
if (!provider.image) throw new Error(`The ${provider.id} provider cannot generate images
|
|
5115
|
+
if (!provider.image) throw new Error(`The ${provider.id} provider cannot generate images (or add an image() adapter)`);
|
|
5059
5116
|
const generated = await provider.image(options3.prompt, { size: imageSize(options3.size), signal: options3.signal });
|
|
5060
5117
|
const file2 = resolve9(/\.(png|jpe?g|webp)$/i.test(options3.out) ? options3.out : `${options3.out}.${generated.extension}`);
|
|
5061
5118
|
await mkdir12(dirname9(file2), { recursive: true });
|
|
@@ -130,6 +130,12 @@ export declare class FreeLlmApiProvider implements AiProvider {
|
|
|
130
130
|
private headers;
|
|
131
131
|
resolveModel(task: ChatTask, explicitModel?: string, signal?: AbortSignal): Promise<string>;
|
|
132
132
|
chat(messages: ChatMessage[], options?: ChatOptions): Promise<string>;
|
|
133
|
+
speak(text: string, options?: SpeakOptions): Promise<AudioResult>;
|
|
134
|
+
transcribe(audio: Uint8Array, filename: string, options?: {
|
|
135
|
+
language?: string;
|
|
136
|
+
signal?: AbortSignal;
|
|
137
|
+
}): Promise<Transcript>;
|
|
138
|
+
image(prompt: string, options?: ImageOptions): Promise<ImageResult>;
|
|
133
139
|
}
|
|
134
140
|
export declare class MockProvider implements AiProvider {
|
|
135
141
|
id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "motionrender",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "JSON-first, frame-deterministic motion graphics video engine: render compositions to MP4, WebM, ProRes, GIF or PNG frames from Node or the command line.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -77,4 +77,4 @@
|
|
|
77
77
|
"optional": true
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
-
}
|
|
80
|
+
}
|