storebound/cli/shots/jpeg.ts

37 lines
2 KiB
TypeScript

// JPEG copies of the Play renders (play, tab7, tab10, feature): about 4x smaller, so `play images` uploads much faster.
// The App Store screenshots stay PNG.
// storebound shots jpeg [--q 92] [--lang en,tr] [--variant b | --variants]
import { existsSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
import { spawnSync } from 'node:child_process';
import type { Ctx } from '../lib/ctx';
import { done, log } from '../lib/log';
import { variantRoot } from './lib';
/** ffmpeg's mjpeg -q:v (2 best .. 31 worst) for a 0-100 quality. */
export const ffmpegQ = (q: number): number => Math.max(2, Math.min(31, Math.round(2 + (100 - q) * 0.29)));
export async function run(ctx: Ctx): Promise<void> {
const { config, resolve } = ctx.loaded;
const base = resolve(ctx.args.get('src') ?? config.renders ?? config.shots?.out ?? 'store/renders');
const roots = ctx.args.has('variants') ? [base, ...Object.keys(config.shots?.variants ?? {}).map(v => variantRoot(base, v, config.shots?.variants))]
: [variantRoot(base, ctx.args.get('variant'), config.shots?.variants)];
const q = ctx.args.num('q', 92);
const langs = ctx.args.list('lang').length ? ctx.args.list('lang') : config.languages.map(l => l.id);
const sips = spawnSync('sh', ['-c', 'command -v sips']).status === 0;
let n = 0;
for (const src of roots) for (const lang of langs) for (const sub of ['play', 'tab7', 'tab10', 'feature']) {
const dir = join(src, lang, sub);
if (!existsSync(dir)) continue;
for (const f of readdirSync(dir).filter(f => f.endsWith('.png'))) {
const inp = join(dir, f), out = inp.replace(/\.png$/, '.jpg');
const r = sips
? spawnSync('sips', ['-s', 'format', 'jpeg', '-s', 'formatOptions', String(q), inp, '--out', out])
: spawnSync('ffmpeg', ['-v', 'error', '-y', '-i', inp, '-q:v', String(ffmpegQ(q)), out]);
if (r.status !== 0) throw new Error(`jpeg failed for ${inp}`);
n++;
}
log('shots', `${src === base ? '' : src.slice(base.length + 1) + '/'}${lang}/${sub}: jpeg q${q}`);
}
done('shots', `${n} JPEG copies`);
}