feat(gacha): add /api/gachabeta toon-shaded wish style

The beta wish renders an 8-second astrology-themed night sky in toon
shading through a perspective action camera: it dollies toward a hero
cloud, a comet lights the cloud's rim from behind and bursts through it,
the camera chases the comet as its flare builds to a starburst, and the
label appears with an S, SS, or SSS rank. It shares the /api/gacha request
contract and render slots.
This commit is contained in:
tiennm99 committed 2026-10-01 15:07:56 +07:00
1 parent dccd524f9d
commit d2f09ecb33
11 files changed
+934 -12

No files matched your search

+15
View File
@@ -65,6 +65,21 @@ try {
}
console.log(`api-smoke gacha: ${gacha.rawPayload.byteLength} bytes`);
const beta = await app.inject({
method: 'POST',
url: '/api/gachabeta',
headers: {
authorization: 'Bearer smoke-token',
},
payload: {label: 'Bún bò', rarity: 5},
});
if (beta.statusCode !== 200 || beta.rawPayload.subarray(4, 8).toString() !== 'ftyp') {
throw new Error(`Expected gachabeta MP4, got ${beta.statusCode}: ${beta.body.slice(0, 200)}`);
}
console.log(`api-smoke gachabeta: ${beta.rawPayload.byteLength} bytes`);
} finally {
await app.close();
}
+10 -1
View File
@@ -1,6 +1,6 @@
import {mkdir, writeFile} from 'node:fs/promises';
import path from 'node:path';
import {renderGachaVideo} from '../src/render/render-gacha.js';
import {renderGachaBetaVideo, renderGachaVideo} from '../src/render/render-gacha.js';
import {renderWheelGif} from '../src/render/render-gif.js';
const smoke = process.argv.includes('--smoke');
@@ -72,3 +72,12 @@ for (const fixture of smoke ? fixtures.slice(0, 1) : fixtures) {
for (const fixture of smoke ? gachaFixtures.slice(0, 1) : gachaFixtures) {
await save(`${fixture.name}.mp4`, await renderGachaVideo(fixture.request, {timeoutInMilliseconds: 30000}));
}
const betaFixture = {
label: 'Bún bò',
rarity: /** @type {const} */ (5),
fps: /** @type {const} */ (24),
width: /** @type {const} */ (640),
seed: 7,
};
await save('gachabeta-5-star.mp4', await renderGachaBetaVideo(betaFixture, {timeoutInMilliseconds: 30000}));