mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-13 02:14:55 +00:00
feat(gacha): add /api/gacha wish animation rendered as MP4
A meteor coloured by rarity falls across a night sky, lands in a white flash, and the label is revealed with its stars popping in. The caller picks the result and rarity; the route only draws it. Renders as silent H.264 so Telegram plays it as an animation without GIF banding, and shares the render slots with /api/gif.
This commit is contained in:
1 parent
61d0e74709
commit
97d8aeaadf
16 files changed
+1111
-20
No files matched your search
@@ -45,6 +45,26 @@ try {
|
||||
}
|
||||
|
||||
console.log(`api-smoke: ${response.rawPayload.byteLength} bytes`);
|
||||
|
||||
const gacha = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/gacha',
|
||||
headers: {
|
||||
authorization: 'Bearer smoke-token',
|
||||
},
|
||||
payload: {label: 'Pizza', rarity: 5},
|
||||
});
|
||||
|
||||
if (gacha.statusCode !== 200) {
|
||||
throw new Error(`Expected gacha 200, got ${gacha.statusCode}: ${gacha.body}`);
|
||||
}
|
||||
|
||||
const box = gacha.rawPayload.subarray(4, 8).toString();
|
||||
if (box !== 'ftyp') {
|
||||
throw new Error(`Expected MP4 ftyp box, got ${box}`);
|
||||
}
|
||||
|
||||
console.log(`api-smoke gacha: ${gacha.rawPayload.byteLength} bytes`);
|
||||
} finally {
|
||||
await app.close();
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import {mkdir, writeFile} from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import {renderGachaVideo} from '../src/render/render-gacha.js';
|
||||
import {renderWheelGif} from '../src/render/render-gif.js';
|
||||
|
||||
const smoke = process.argv.includes('--smoke');
|
||||
@@ -47,9 +48,27 @@ const fixtures = [
|
||||
|
||||
await mkdir(fixturesDir, {recursive: true});
|
||||
|
||||
for (const fixture of smoke ? fixtures.slice(0, 1) : fixtures) {
|
||||
const result = await renderWheelGif(fixture.request, {timeoutInMilliseconds: 30000});
|
||||
const output = path.join(fixturesDir, `${fixture.name}.gif`);
|
||||
/** @type {{name: string, request: import('../src/schemas/gacha-request.js').GachaRenderRequest}[]} */
|
||||
const gachaFixtures = [
|
||||
{name: 'gacha-5-star', request: {label: 'Pizza', rarity: 5, fps: 24, width: 640}},
|
||||
{name: 'gacha-4-star', request: {label: 'Phở bò tái nạm gầu', rarity: 4, fps: 24, width: 640}},
|
||||
{name: 'gacha-3-star', request: {label: 'Cơm tấm', rarity: 3, fps: 24, width: 854}},
|
||||
];
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {{buffer: Buffer, byteLength: number, durationMs: number}} result
|
||||
*/
|
||||
const save = async (name, result) => {
|
||||
const output = path.join(fixturesDir, name);
|
||||
await writeFile(output, result.buffer);
|
||||
console.log(`${fixture.name}: ${output} ${result.byteLength} bytes ${result.durationMs}ms`);
|
||||
console.log(`${name}: ${output} ${result.byteLength} bytes ${result.durationMs}ms`);
|
||||
};
|
||||
|
||||
for (const fixture of smoke ? fixtures.slice(0, 1) : fixtures) {
|
||||
await save(`${fixture.name}.gif`, await renderWheelGif(fixture.request, {timeoutInMilliseconds: 30000}));
|
||||
}
|
||||
|
||||
for (const fixture of smoke ? gachaFixtures.slice(0, 1) : gachaFixtures) {
|
||||
await save(`${fixture.name}.mp4`, await renderGachaVideo(fixture.request, {timeoutInMilliseconds: 30000}));
|
||||
}
|
||||
Reference in new issue
Block a user