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.
68 lines
2.7 KiB
JavaScript
68 lines
2.7 KiB
JavaScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { mkdtempSync, mkdirSync, writeFileSync, existsSync, rmSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
import { resolveSfx } from "./sfx.mjs";
|
|
|
|
// The bundled SFX library may ship manifest.json without the actual mp3s. An
|
|
// entry pushed for a file that was never copied is a dangling reference that
|
|
// drops silently downstream ("not on disk"). These tests lock in the loud
|
|
// behavior: a present file is copied and referenced; a missing one says so.
|
|
// No credential is set here, so the catalog and foley rungs are never reached.
|
|
|
|
async function withDirs(fn) {
|
|
const root = mkdtempSync(join(tmpdir(), "hf-sfx-"));
|
|
const libDir = join(root, "lib");
|
|
const projDir = join(root, "proj");
|
|
mkdirSync(libDir, { recursive: true });
|
|
mkdirSync(projDir, { recursive: true });
|
|
try {
|
|
// `await` is load-bearing: without it the finally cleanup runs before the
|
|
// async test body resolves, deleting the temp dir mid-assertion.
|
|
return await fn({ libDir, projDir });
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
}
|
|
|
|
test("copies and references a present bundled file", async () => {
|
|
await withDirs(async ({ libDir, projDir }) => {
|
|
writeFileSync(
|
|
join(libDir, "manifest.json"),
|
|
JSON.stringify({ whoosh: { file: "whoosh.mp3", duration: 0.8 } }),
|
|
);
|
|
writeFileSync(join(libDir, "whoosh.mp3"), "ID3-fake-bytes");
|
|
const { sfx, anomalies } = await resolveSfx({
|
|
cues: [{ id: "s1", name: "whoosh" }],
|
|
framesDir: projDir,
|
|
sfxLibDir: libDir,
|
|
});
|
|
assert.equal(sfx.length, 1);
|
|
assert.equal(sfx[0].file, "assets/sfx/whoosh.mp3");
|
|
assert.equal(sfx[0].source, "library");
|
|
assert.ok(existsSync(join(projDir, "assets/sfx/whoosh.mp3")), "mp3 copied into project");
|
|
assert.equal(anomalies.length, 0);
|
|
});
|
|
});
|
|
|
|
test("a matched-but-missing bundled file yields an anomaly and NO dangling entry", async () => {
|
|
await withDirs(async ({ libDir, projDir }) => {
|
|
// Manifest names whoosh.mp3, but the mp3 was never shipped (the reported bug).
|
|
writeFileSync(
|
|
join(libDir, "manifest.json"),
|
|
JSON.stringify({ whoosh: { file: "whoosh.mp3", duration: 0.8 } }),
|
|
);
|
|
const { sfx, anomalies } = await resolveSfx({
|
|
cues: [{ id: "s1", name: "whoosh" }],
|
|
framesDir: projDir,
|
|
sfxLibDir: libDir,
|
|
});
|
|
assert.equal(sfx.length, 0, "no dangling entry for a file that was never copied");
|
|
assert.equal(anomalies.length, 2);
|
|
assert.match(anomalies[0], /is missing from/);
|
|
assert.match(anomalies[1], /none could be made/);
|
|
assert.ok(!existsSync(join(projDir, "assets/sfx/whoosh.mp3")), "nothing copied");
|
|
});
|
|
});
|