mirror of
https://github.com/hanzoai/frames.git
synced 2026-09-24 00:08:03 +00:00
Voice is POST /v1/audio/speech and word timings come from POST /v1/audio/transcriptions over the rendered audio. Music, sound effects, images, and video generate through /v1/audio/music, /v1/audio/foley, /v1/images/generations, and /v1/videos/generations. The shared catalog is a listing under media/<type>/ in our own object store, browsed through /v1/s3 — an empty prefix reports itself as empty rather than reading as a bad query. One client (scripts/lib/api.mjs) holds every route and the one credential: a Hanzo IAM token in $HANZO_API_KEY, read from Hanzo KMS. No credential file, no per-repo .env, no per-provider CLI to install or keep current. $HANZO_BASE_URL points the same code at a local Hanzo Engine. Word timings are passed through, never interpolated: a caption cut on invented boundaries reads as correct and drifts against the voice. When the service returns text without them, the word array is empty and the caller is told. Deletes the provider cascade this replaces, its model ladders, and the account linking in telemetry — the install id stands alone.
48 lines
1.8 KiB
JavaScript
48 lines
1.8 KiB
JavaScript
import { strict as assert } from "node:assert";
|
|
import { test } from "node:test";
|
|
import { mkdtempSync, rmSync, existsSync } from "node:fs";
|
|
import { join, dirname } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
import { fileURLToPath } from "node:url";
|
|
import { resolveSfx } from "./lib/sfx.mjs";
|
|
|
|
// Proves the relocated engine (skills/media-use/audio/) still resolves its
|
|
// bundled SFX library from the moved location — the path most likely to break
|
|
// on a subtree move. No credential is set, so no network rung is reached.
|
|
|
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
const sfxLibDir = join(HERE, "..", "assets", "sfx"); // same offset the engine uses
|
|
|
|
test("bundled SFX library resolves from the relocated path", async () => {
|
|
assert.ok(existsSync(join(sfxLibDir, "manifest.json")), "moved manifest is present");
|
|
const dir = mkdtempSync(join(tmpdir(), "mu-audio-"));
|
|
try {
|
|
const { sfx, anomalies } = await resolveSfx({
|
|
cues: [{ id: "1", name: "whoosh" }],
|
|
framesDir: dir,
|
|
sfxLibDir,
|
|
});
|
|
assert.equal(sfx.length, 1, `expected 1 resolved cue, got anomalies: ${anomalies.join("; ")}`);
|
|
assert.equal(sfx[0].source, "library");
|
|
assert.match(sfx[0].file, /assets\/sfx\//);
|
|
assert.ok(existsSync(join(dir, sfx[0].file)), "matched SFX copied into the project");
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("an unknown cue is reported, not fatal", async () => {
|
|
const dir = mkdtempSync(join(tmpdir(), "mu-audio-"));
|
|
try {
|
|
const { sfx, anomalies } = await resolveSfx({
|
|
cues: [{ id: "1", name: "definitely-not-a-real-sfx" }],
|
|
framesDir: dir,
|
|
sfxLibDir,
|
|
});
|
|
assert.equal(sfx.length, 0);
|
|
assert.ok(anomalies.some((a) => /none could be made/.test(a)));
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|