31 lines
1.4 KiB
TypeScript
31 lines
1.4 KiB
TypeScript
import type { UploadFile } from './common';
|
||
import { audioExt } from './files';
|
||
|
||
type SummaryFile = Pick<UploadFile, 'format' | 'original_name' | 'bitrate' | 'sample_rate' | 'bit_depth'>;
|
||
|
||
function range(values: (number | null)[], divisor: number, decimals: number, unit: string): string | null {
|
||
const known = values.filter((value): value is number => value !== null && Number.isFinite(value) && value > 0);
|
||
if (!known.length) return null;
|
||
const format = (value: number) => String(Number((value / divisor).toFixed(decimals)));
|
||
const min = format(Math.min(...known));
|
||
const max = format(Math.max(...known));
|
||
return `${min === max ? min : `${min}–${max}`} ${unit}`;
|
||
}
|
||
|
||
/** Only measured positive values contribute to quality ranges; absent metadata is not zero. */
|
||
export function batchSummary(files: SummaryFile[]) {
|
||
const counts = new Map<string, number>();
|
||
for (const file of files) {
|
||
const format = (file.format?.trim() || audioExt(file.original_name)).toUpperCase();
|
||
counts.set(format, (counts.get(format) ?? 0) + 1);
|
||
}
|
||
return {
|
||
formats: [...counts].sort(([a, ac], [b, bc]) => bc - ac || a.localeCompare(b)),
|
||
quality: [
|
||
range(files.map((file) => file.bitrate), 1000, 0, 'kbps'),
|
||
range(files.map((file) => file.sample_rate), 1000, 3, 'kHz'),
|
||
range(files.map((file) => file.bit_depth), 1, 0, 'bit'),
|
||
].filter(Boolean).join(' · '),
|
||
};
|
||
}
|