UNPKG

murmuraba

Version:

Real-time audio noise reduction with advanced chunked processing for web applications

122 lines (121 loc) 4.17 kB
/** * Unified time formatting utilities for consistent duration handling across the application. * All durations are stored internally as milliseconds for precision. */ /** * Convert time between different units */ export const convertTime = { msToSeconds: (ms) => ms / 1000, secondsToMs: (seconds) => seconds * 1000, msToMinutes: (ms) => ms / (1000 * 60), minutesToMs: (minutes) => minutes * 1000 * 60, }; /** * Validate and normalize time values */ export const normalizeTime = (time) => { if (!isFinite(time) || time < 0) return 0; return time; }; /** * Core time formatting function that accepts milliseconds * This is the single source of truth for time formatting */ export const formatDuration = (milliseconds, options = {}) => { const { format = 'mm:ss', showHours = false, precision = 'seconds' } = options; const normalizedMs = normalizeTime(milliseconds); if (normalizedMs === 0) return format === 'compact' ? '0s' : '0:00'; const totalSeconds = precision === 'milliseconds' ? normalizedMs / 1000 : Math.floor(normalizedMs / 1000); const hours = Math.floor(totalSeconds / 3600); const minutes = Math.floor((totalSeconds % 3600) / 60); const seconds = Math.floor(totalSeconds % 60); const ms = Math.floor(normalizedMs % 1000); switch (format) { case 'compact': if (hours > 0) return `${hours}h ${minutes}m`; if (minutes > 0) return `${minutes}m ${seconds}s`; return `${seconds}s`; case 'hh:mm:ss': return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; case 'mm:ss': default: { if (showHours && hours > 0) { return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; } const totalMinutes = Math.floor(totalSeconds / 60); const remainingSeconds = Math.floor(totalSeconds % 60); if (precision === 'milliseconds' && ms > 0) { return `${totalMinutes}:${remainingSeconds.toString().padStart(2, '0')}.${Math.floor(ms / 100)}`; } return `${totalMinutes}:${remainingSeconds.toString().padStart(2, '0')}`; } } }; /** * Legacy compatibility - formats seconds to mm:ss * @deprecated Use formatDuration with convertTime.secondsToMs() instead */ export const formatTime = (seconds) => { return formatDuration(convertTime.secondsToMs(seconds)); }; /** * Format duration with automatic unit detection and user-friendly labels */ export const formatDurationWithLabel = (milliseconds) => { const ms = normalizeTime(milliseconds); if (ms < 1000) return `${ms}ms`; if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`; if (ms < 3600000) return formatDuration(ms, { format: 'mm:ss' }); return formatDuration(ms, { format: 'hh:mm:ss' }); }; /** * Create a time formatter with consistent options */ export const createTimeFormatter = (options = {}) => { return (milliseconds) => formatDuration(milliseconds, options); }; /** * Utility for chunk duration statistics */ export const calculateDurationStats = (durations) => { if (durations.length === 0) { return { total: 0, average: 0, min: 0, max: 0, totalFormatted: '0:00', averageFormatted: '0:00', }; } const total = durations.reduce((sum, duration) => sum + duration, 0); const average = total / durations.length; const min = Math.min(...durations); const max = Math.max(...durations); return { total, average, min, max, totalFormatted: formatDuration(total), averageFormatted: formatDuration(average), minFormatted: formatDuration(min), maxFormatted: formatDuration(max), }; }; /** * Type guard for time values */ export const isValidTime = (value) => { return typeof value === 'number' && isFinite(value) && value >= 0; };