62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
export const MIN_AUDIO_PLAYBACK_RATE = 0.1;
|
|
export const MAX_AUDIO_PLAYBACK_RATE = 4;
|
|
export const AUDIO_PLAYBACK_RATE_STEP = 0.1;
|
|
|
|
export type AudioToolRequest =
|
|
| { kind: "trim"; startSeconds: number; endSeconds: number }
|
|
| { kind: "speed"; playbackRate: number };
|
|
|
|
export function normalizeAudioPlaybackRate(value: unknown, fallback = 1) {
|
|
const parsed = Number.parseFloat(String(value ?? "").replace(/x$/i, ""));
|
|
const safe = Number.isFinite(parsed) ? parsed : fallback;
|
|
return Math.round(
|
|
Math.min(MAX_AUDIO_PLAYBACK_RATE, Math.max(MIN_AUDIO_PLAYBACK_RATE, safe)) * 100,
|
|
) / 100;
|
|
}
|
|
|
|
export function stepAudioPlaybackRate(value: unknown, direction: 1 | -1) {
|
|
return normalizeAudioPlaybackRate(
|
|
normalizeAudioPlaybackRate(value) + direction * AUDIO_PLAYBACK_RATE_STEP,
|
|
);
|
|
}
|
|
|
|
export function formatAudioPlaybackRate(value: unknown) {
|
|
return `${normalizeAudioPlaybackRate(value).toFixed(2)}x`;
|
|
}
|
|
|
|
export function formatAudioPlaybackRateSuffix(value: unknown) {
|
|
const rate = normalizeAudioPlaybackRate(value);
|
|
return Number.isInteger(rate) ? `${rate}x` : `${rate.toFixed(2).replace(/0+$/, "")}x`;
|
|
}
|
|
|
|
export function getDefaultAudioTrimRange(durationSeconds: unknown) {
|
|
const duration = Math.max(0.1, Number(durationSeconds) || 0.1);
|
|
return {
|
|
startSeconds: 0,
|
|
endSeconds: Math.min(duration, Math.max(0.1, duration / 3)),
|
|
};
|
|
}
|
|
|
|
export function normalizeAudioTrimRange(
|
|
durationSeconds: unknown,
|
|
startSeconds: unknown,
|
|
endSeconds: unknown,
|
|
) {
|
|
const duration = Math.max(0.1, Number(durationSeconds) || 0.1);
|
|
const start = Math.min(duration - 0.05, Math.max(0, Number(startSeconds) || 0));
|
|
const end = Math.min(duration, Math.max(start + 0.05, Number(endSeconds) || duration));
|
|
return { startSeconds: start, endSeconds: end };
|
|
}
|
|
|
|
export function getProcessedAudioTitle(sourceTitle: string, request: AudioToolRequest) {
|
|
const base = String(sourceTitle || "音频").trim() || "音频";
|
|
return request.kind === "trim"
|
|
? `${base}_截取`
|
|
: `${base}_${formatAudioPlaybackRateSuffix(request.playbackRate)}`;
|
|
}
|
|
|
|
export function getAudioDownloadExtension(source: unknown) {
|
|
const pathname = String(source || "").split(/[?#]/, 1)[0];
|
|
return pathname.match(/\.(wav|mp3|m4a|aac|ogg|webm)$/i)?.[1]?.toLowerCase() || "mp3";
|
|
}
|