finchvox 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- finchvox/__init__.py +0 -0
- finchvox/__main__.py +81 -0
- finchvox/audio_recorder.py +278 -0
- finchvox/audio_utils.py +123 -0
- finchvox/cli.py +127 -0
- finchvox/collector/__init__.py +0 -0
- finchvox/collector/__main__.py +22 -0
- finchvox/collector/audio_handler.py +146 -0
- finchvox/collector/collector_routes.py +186 -0
- finchvox/collector/config.py +64 -0
- finchvox/collector/server.py +126 -0
- finchvox/collector/service.py +43 -0
- finchvox/collector/writer.py +86 -0
- finchvox/server.py +201 -0
- finchvox/trace.py +115 -0
- finchvox/ui/css/app.css +774 -0
- finchvox/ui/images/favicon.ico +0 -0
- finchvox/ui/images/finchvox-logo.png +0 -0
- finchvox/ui/js/time-utils.js +97 -0
- finchvox/ui/js/trace_detail.js +1228 -0
- finchvox/ui/js/traces_list.js +26 -0
- finchvox/ui/lib/alpine.min.js +5 -0
- finchvox/ui/lib/wavesurfer.min.js +1 -0
- finchvox/ui/trace_detail.html +313 -0
- finchvox/ui/traces_list.html +63 -0
- finchvox/ui_routes.py +362 -0
- finchvox-0.0.1.dist-info/METADATA +189 -0
- finchvox-0.0.1.dist-info/RECORD +31 -0
- finchvox-0.0.1.dist-info/WHEEL +4 -0
- finchvox-0.0.1.dist-info/entry_points.txt +2 -0
- finchvox-0.0.1.dist-info/licenses/LICENSE +24 -0
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time Utilities for FinchVox UI
|
|
3
|
+
*
|
|
4
|
+
* Provides standardized time duration formatting across the application.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Format a duration in milliseconds to a human-readable string.
|
|
9
|
+
*
|
|
10
|
+
* Formatting rules:
|
|
11
|
+
* - < 1ms: show in ms with 2 decimal places (e.g., "0.05ms")
|
|
12
|
+
* - >= 1ms and < 1s: show in ms with no decimal places (e.g., "250ms")
|
|
13
|
+
* - >= 1s and < 1min: show in seconds with configurable decimals (e.g., "12.3s")
|
|
14
|
+
* - >= 1min and < 1h: show as M:SS + "m" (e.g., "1:02m")
|
|
15
|
+
* - >= 1h and < 24h: show as H:MM:SS + "h" (e.g., "1:02:03h")
|
|
16
|
+
* - >= 24h: show as "Xd H:MM:SS" + "h" (e.g., "1d 1:30:15h")
|
|
17
|
+
*
|
|
18
|
+
* @param {number} milliseconds - Duration in milliseconds
|
|
19
|
+
* @param {number} decimalPlaces - Number of decimal places for seconds display (default: 1)
|
|
20
|
+
* @returns {string} Formatted duration string
|
|
21
|
+
* @throws {Error} If milliseconds is null, undefined, or NaN
|
|
22
|
+
*/
|
|
23
|
+
function formatDuration(milliseconds, decimalPlaces = 1) {
|
|
24
|
+
// Validate input
|
|
25
|
+
if (milliseconds == null || isNaN(milliseconds)) {
|
|
26
|
+
throw new Error(`Invalid duration input: ${milliseconds}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Handle zero
|
|
30
|
+
if (milliseconds === 0) {
|
|
31
|
+
return "0ms";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Handle negative durations
|
|
35
|
+
const isNegative = milliseconds < 0;
|
|
36
|
+
const absMs = Math.abs(milliseconds);
|
|
37
|
+
|
|
38
|
+
let result;
|
|
39
|
+
|
|
40
|
+
// < 1ms: show with 2 decimal places
|
|
41
|
+
if (absMs < 1) {
|
|
42
|
+
result = `${absMs.toFixed(2)}ms`;
|
|
43
|
+
}
|
|
44
|
+
// >= 1ms and < 1s: show in ms with no decimals
|
|
45
|
+
else if (absMs < 1000) {
|
|
46
|
+
result = `${Math.round(absMs)}ms`;
|
|
47
|
+
}
|
|
48
|
+
// >= 1s and < 1min: show in seconds with configurable decimals
|
|
49
|
+
else if (absMs < 60000) {
|
|
50
|
+
const seconds = absMs / 1000;
|
|
51
|
+
result = `${seconds.toFixed(decimalPlaces)}s`;
|
|
52
|
+
}
|
|
53
|
+
// >= 1min and < 1h: show as M:SS + "m"
|
|
54
|
+
else if (absMs < 3600000) {
|
|
55
|
+
const totalSeconds = Math.round(absMs / 1000);
|
|
56
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
57
|
+
const seconds = totalSeconds % 60;
|
|
58
|
+
result = `${minutes}:${String(seconds).padStart(2, '0')}m`;
|
|
59
|
+
}
|
|
60
|
+
// >= 1h and < 24h: show as H:MM:SS + "h"
|
|
61
|
+
else if (absMs < 86400000) {
|
|
62
|
+
const totalSeconds = Math.round(absMs / 1000);
|
|
63
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
64
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
65
|
+
const seconds = totalSeconds % 60;
|
|
66
|
+
result = `${hours}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}h`;
|
|
67
|
+
}
|
|
68
|
+
// >= 24h: show as "Xd H:MM:SS" + "h"
|
|
69
|
+
else {
|
|
70
|
+
const totalSeconds = Math.round(absMs / 1000);
|
|
71
|
+
const days = Math.floor(totalSeconds / 86400);
|
|
72
|
+
const hours = Math.floor((totalSeconds % 86400) / 3600);
|
|
73
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
74
|
+
const seconds = totalSeconds % 60;
|
|
75
|
+
result = `${days}d ${hours}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}h`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Add negative sign if needed
|
|
79
|
+
return isNegative ? `-${result}` : result;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Format a Unix timestamp to a human-readable date string.
|
|
84
|
+
*
|
|
85
|
+
* @param {number} timestamp - Unix timestamp in seconds
|
|
86
|
+
* @returns {string} Formatted date string (e.g., "Jan 2, 05:44 PM")
|
|
87
|
+
*/
|
|
88
|
+
function formatDate(timestamp) {
|
|
89
|
+
if (!timestamp) return '';
|
|
90
|
+
const date = new Date(timestamp * 1000); // Convert seconds to milliseconds
|
|
91
|
+
return date.toLocaleString('en-US', {
|
|
92
|
+
month: 'short',
|
|
93
|
+
day: 'numeric',
|
|
94
|
+
hour: '2-digit',
|
|
95
|
+
minute: '2-digit'
|
|
96
|
+
});
|
|
97
|
+
}
|