dashcam 1.4.13-beta.1 → 1.4.13-beta.3

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.
@@ -1,139 +0,0 @@
1
- # Performance Tracking
2
-
3
- The Dashcam CLI now includes comprehensive performance tracking during recordings. This feature monitors CPU and memory usage throughout the recording session and includes the data in the log files.
4
-
5
- ## What's Tracked
6
-
7
- ### 1. Dashcam Process Metrics
8
- - **CPU Usage**: Percentage of CPU used by the Dashcam process
9
- - **Memory Usage**: Memory consumed by the Dashcam process in bytes and MB
10
- - **Process Info**: PID, parent PID, CPU time, elapsed time
11
-
12
- ### 2. System-Wide Metrics
13
- - **Total Memory**: System total and free memory
14
- - **Memory Usage Percentage**: Overall system memory utilization
15
- - **CPU Count**: Number of CPU cores available
16
-
17
- ### 3. Top Processes
18
- - **Top 10 by CPU**: The most CPU-intensive processes running on the system
19
- - **Top 10 by Memory**: The most memory-intensive processes running on the system
20
- - **Process Details**: For each top process, tracks:
21
- - Process name
22
- - PID
23
- - CPU usage percentage
24
- - Memory usage in bytes
25
- - Parent process ID
26
- - CPU time and elapsed time
27
-
28
- ## Sampling Frequency
29
-
30
- Performance metrics are sampled every **1 second** (1000ms) during the recording session.
31
-
32
- ## Output Format
33
-
34
- Performance data is included in the recording result with the following structure:
35
-
36
- ```javascript
37
- {
38
- performance: {
39
- samples: [
40
- {
41
- timestamp: 1700000000000,
42
- elapsedMs: 1000,
43
- system: {
44
- totalMemory: 17179869184,
45
- freeMemory: 8589934592,
46
- usedMemory: 8589934592,
47
- memoryUsagePercent: 50.0,
48
- cpuCount: 8
49
- },
50
- process: {
51
- cpu: 15.5,
52
- memory: 134217728,
53
- pid: 12345,
54
- ppid: 1,
55
- ctime: 5000,
56
- elapsed: 10000
57
- },
58
- topProcesses: [
59
- {
60
- pid: 54321,
61
- name: "ffmpeg",
62
- cpu: 85.2,
63
- memory: 268435456,
64
- ppid: 12345,
65
- ctime: 8500,
66
- elapsed: 10000
67
- },
68
- // ... up to 10 processes
69
- ],
70
- totalProcesses: 342
71
- }
72
- // ... one sample per second
73
- ],
74
- summary: {
75
- durationMs: 10000,
76
- sampleCount: 10,
77
- monitorInterval: 1000,
78
- avgProcessCPU: 12.3,
79
- maxProcessCPU: 18.7,
80
- avgProcessMemoryBytes: 134217728,
81
- avgProcessMemoryMB: 128.0,
82
- maxProcessMemoryBytes: 201326592,
83
- maxProcessMemoryMB: 192.0,
84
- avgSystemMemoryUsagePercent: 52.5,
85
- maxSystemMemoryUsagePercent: 55.3,
86
- totalSystemMemoryBytes: 17179869184,
87
- totalSystemMemoryGB: 16.0
88
- }
89
- }
90
- }
91
- ```
92
-
93
- ## Summary Statistics
94
-
95
- The performance tracker calculates summary statistics including:
96
- - **Average and Max Process CPU**: How much CPU the Dashcam process used
97
- - **Average and Max Process Memory**: Memory consumed by the Dashcam process
98
- - **Average and Max System Memory Usage**: Overall system memory pressure
99
- - **Total Duration**: How long the tracking ran
100
- - **Sample Count**: Number of samples collected
101
-
102
- ## Logging
103
-
104
- Performance data is logged to the standard Dashcam log files:
105
- - `~/.dashcam/logs/combined.log` - All log levels including performance samples
106
- - `~/.dashcam/logs/debug.log` - Debug-level information
107
- - Console output when running with `--verbose` flag
108
-
109
- ## Testing
110
-
111
- Run the performance tracking test:
112
-
113
- ```bash
114
- node test-performance-tracking.js
115
- ```
116
-
117
- This will:
118
- 1. Start a 10-second recording
119
- 2. Collect performance samples every second
120
- 3. Display detailed performance statistics
121
- 4. Show the top 10 processes at the end of the recording
122
-
123
- ## Use Cases
124
-
125
- Performance tracking helps with:
126
- - **Debugging Performance Issues**: Identify when recordings are resource-intensive
127
- - **Optimization**: Track the impact of code changes on resource usage
128
- - **System Monitoring**: Understand what other processes are running during recordings
129
- - **Troubleshooting**: Correlate performance issues with specific applications or system states
130
- - **Capacity Planning**: Understand resource requirements for different recording scenarios
131
-
132
- ## Implementation Details
133
-
134
- The performance tracker uses:
135
- - `pidusage` - For detailed per-process CPU and memory statistics
136
- - `ps-list` - For listing all system processes
137
- - `os` module - For system-wide memory and CPU information
138
-
139
- The tracker runs in parallel with the recording and has minimal overhead (~1% CPU on average).
@@ -1,129 +0,0 @@
1
- # Single-Frame Video & Frame Drop Issues - Root Cause & Fix
2
-
3
- ## Problem Description
4
-
5
- Videos produced by dashcam-cli had two related issues:
6
- 1. **Single-frame appearance**: Videos appearing as single-frame, even though they contained multiple frames
7
- 2. **Frame drops**: Videos showing significantly shorter duration than actual recording time (e.g., 12 seconds shown vs 68 seconds actual)
8
-
9
- ## Root Causes
10
-
11
- ### Issue 1: Incomplete WebM Container Metadata
12
- When ffmpeg's VP9 encoder is terminated before it can properly finalize the stream:
13
-
14
- 1. **Missing duration metadata** - The WebM container doesn't have duration information
15
- 2. **Premature file ending** - FFprobe reports "File ended prematurely"
16
- 3. **Playback issues** - Some players show only the first frame because they can't seek without duration metadata
17
-
18
- ### Issue 2: Frame Dropping During Capture
19
- Frames were being dropped during the recording process due to:
20
-
21
- 1. **Conflicting frame rate settings** - Platform config had hardcoded `-r 30` while fps parameter was set to 10
22
- 2. **Insufficient buffer sizes** - Default thread queue size caused frame drops when encoder couldn't keep up
23
- 3. **Premature stream termination** - The `-shortest` flag caused encoding to stop before all buffered frames were processed
24
- 4. **Missing vsync enforcement** - Frames could be skipped instead of encoded
25
-
26
- ### Example from Real Recording
27
-
28
- ```bash
29
- # File: 691cb2b4c2fc02f59ae66e21.mp4
30
- Frame count: 512 frames
31
- Actual duration: 17.06 seconds (when decoded)
32
- Container duration: N/A (missing metadata)
33
- Warning: "File ended prematurely"
34
- ```
35
-
36
- The video has 512 frames spanning 17 seconds, but players that rely on container metadata see it as a single frame.
37
-
38
- ## Platform Specificity
39
-
40
- This issue can occur on all platforms but may be more prevalent on Linux due to:
41
- - Different screen capture performance characteristics
42
- - Variations in how X11grab delivers frames vs AVFoundation (macOS) or gdigrab (Windows)
43
- - System load affecting encoder buffer flush timing
44
-
45
- ## Fix Applied
46
-
47
- ### 1. Minimum Recording Duration (recorder.js)
48
- ```javascript
49
- const MIN_RECORDING_DURATION = 2000; // 2 seconds minimum
50
- if (recordingDuration < MIN_RECORDING_DURATION) {
51
- const waitTime = MIN_RECORDING_DURATION - recordingDuration;
52
- await new Promise(resolve => setTimeout(resolve, waitTime));
53
- }
54
- ```
55
-
56
- ### 2. Improved FFmpeg Encoding Parameters
57
-
58
- **Removed conflicting settings:**
59
- ```javascript
60
- // REMOVED from platform config:
61
- '-r', '30' // This conflicted with fps parameter
62
-
63
- // REMOVED from output args:
64
- '-shortest' // This caused premature termination
65
- ```
66
-
67
- **Added buffer and sync enforcement:**
68
- ```javascript
69
- // Input buffering (before -i):
70
- '-thread_queue_size', '512', // Large input buffer prevents drops
71
- '-probesize', '50M', // Better stream detection
72
-
73
- // Output sync enforcement:
74
- '-vsync', '1', // Constant frame rate - encode every frame
75
- '-max_muxing_queue_size', '9999' // Large muxing queue prevents drops
76
-
77
- // Existing improvements:
78
- '-quality', 'good', // Changed from 'realtime' for better finalization
79
- '-cpu-used', '4', // Balanced encoding speed
80
- '-deadline', 'good', // Good quality mode
81
- '-g', fps.toString(), // Keyframe every second (was 2 seconds)
82
- '-force_key_frames', `expr:gte(t,n_forced*1)`, // Force keyframes every 1s
83
- '-fflags', '+genpts', // Generate presentation timestamps
84
- '-avoid_negative_ts', 'make_zero' // Prevent timestamp issues
85
- ```
86
-
87
- ### 3. Extended Graceful Shutdown Timing
88
- ```javascript
89
- // Graceful quit: 5s -> 8s (VP9 needs time to finalize)
90
- // SIGTERM timeout: 10s -> 15s
91
- // Post-exit wait: 3s (for filesystem sync)
92
-
93
- currentRecording.stdin.write('q');
94
- currentRecording.stdin.end(); // Properly close stdin
95
- ```
96
-
97
- ## Testing
98
-
99
- Use the provided test script to verify recordings:
100
-
101
- ```bash
102
- # Analyze existing video
103
- node test-short-recording.js analyze <video-file>
104
-
105
- # Run automated tests with various durations
106
- node test-short-recording.js
107
- ```
108
-
109
- The test checks for:
110
- - ✅ Frame count > 1
111
- - ✅ No "File ended prematurely" warnings
112
- - ✅ Container metadata is complete (duration present)
113
- - ✅ All platforms (macOS/Linux/Windows)
114
-
115
- ## Prevention
116
-
117
- The fix ensures proper container finalization by:
118
- 1. Enforcing minimum recording time for multiple frames
119
- 2. Using encoding parameters that prioritize stream finalization
120
- 3. Allowing sufficient time for VP9 encoder to flush buffers
121
- 4. Properly closing stdin before waiting for process exit
122
- 5. Adding safety timeouts before force-killing the encoder
123
-
124
- ## Impact
125
-
126
- - Short recordings (< 2s) now wait to ensure at least 2 seconds of footage
127
- - All recordings get properly finalized WebM container metadata
128
- - Videos play correctly in all players, including web browsers
129
- - No more "single frame" issues on any platform
@@ -1,150 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Example: Execute JavaScript on a webpage through the Chrome extension
5
- *
6
- * This demonstrates how to:
7
- * 1. Connect to the Chrome extension via WebSocket
8
- * 2. Send JavaScript code to execute on the active tab
9
- * 3. Receive the execution results back
10
- */
11
-
12
- import { server } from '../lib/websocket/server.js';
13
- import { WebTrackerManager } from '../lib/extension-logs/manager.js';
14
- import { logger } from '../lib/logger.js';
15
-
16
- async function main() {
17
- console.log('================================================================');
18
- console.log(' Chrome Extension Script Execution Example');
19
- console.log('================================================================\n');
20
- console.log('Prerequisites:');
21
- console.log(' 1. Chrome extension must be installed and loaded');
22
- console.log(' 2. Have a regular webpage open (NOT chrome:// or chrome-extension://)');
23
- console.log(' 3. For best results, navigate to a simple page like example.com\n');
24
-
25
- console.log('Starting WebSocket server...');
26
-
27
- // Start the WebSocket server
28
- await server.start();
29
- console.log('WebSocket server started on port:', server.port); // Create the WebTrackerManager
30
- const manager = new WebTrackerManager(server);
31
-
32
- // Wait for the Chrome extension to connect
33
- console.log('\nWaiting for Chrome extension to connect...');
34
- const connected = await new Promise((resolve) => {
35
- const timeout = setTimeout(() => {
36
- console.log('Timeout waiting for connection');
37
- resolve(false);
38
- }, 10000);
39
-
40
- const cleanup = server.on('connection', (client) => {
41
- console.log('Chrome extension connected!');
42
- clearTimeout(timeout);
43
- cleanup();
44
- resolve(true);
45
- });
46
- });
47
-
48
- if (!connected) {
49
- console.error('\nChrome extension did not connect.');
50
- console.error(' Make sure the extension is installed and running.');
51
- console.error(' Check chrome://extensions to verify it\'s loaded.');
52
- process.exit(1);
53
- }
54
-
55
- // Give it a moment to fully initialize
56
- await new Promise(resolve => setTimeout(resolve, 500));
57
-
58
- console.log('\n--- Example 1: Get page title ---');
59
- try {
60
- const result = await manager.executeScript({
61
- code: 'return document.title;'
62
- });
63
- console.log('Page title:', result);
64
- } catch (error) {
65
- console.error('Error:', error.message);
66
- }
67
-
68
- console.log('\n--- Example 2: Get current URL ---');
69
- try {
70
- const result = await manager.executeScript({
71
- code: 'return window.location.href;'
72
- });
73
- console.log('Current URL:', result);
74
- } catch (error) {
75
- console.error('Error:', error.message);
76
- }
77
-
78
- console.log('\n--- Example 3: Change page background color ---');
79
- try {
80
- const result = await manager.executeScript({
81
- code: `
82
- document.body.style.backgroundColor = '#ffcccc';
83
- return 'Background color changed!';
84
- `
85
- });
86
- console.log('Result:', result);
87
- } catch (error) {
88
- console.error('Error:', error.message);
89
- }
90
-
91
- console.log('\n--- Example 4: Insert a message on the page ---');
92
- try {
93
- const result = await manager.executeScript({
94
- code: `
95
- const div = document.createElement('div');
96
- div.style.cssText = 'position: fixed; top: 20px; right: 20px; background: #4CAF50; color: white; padding: 20px; border-radius: 8px; font-family: Arial; z-index: 10000; box-shadow: 0 4px 6px rgba(0,0,0,0.1);';
97
- div.textContent = 'Hello from CLI!';
98
- document.body.appendChild(div);
99
-
100
- // Remove after 5 seconds
101
- setTimeout(() => div.remove(), 5000);
102
-
103
- return 'Message inserted successfully!';
104
- `
105
- });
106
- console.log('Result:', result);
107
- } catch (error) {
108
- console.error('Error:', error.message);
109
- }
110
-
111
- console.log('\n--- Example 5: Get all links on the page ---');
112
- try {
113
- const result = await manager.executeScript({
114
- code: `
115
- const links = Array.from(document.querySelectorAll('a'))
116
- .map(a => ({ text: a.textContent.trim().substring(0, 50), href: a.href }))
117
- .slice(0, 5);
118
- return links;
119
- `
120
- });
121
- console.log('First 5 links:', JSON.stringify(result, null, 2));
122
- } catch (error) {
123
- console.error('Error:', error.message);
124
- }
125
-
126
- console.log('\n--- Example 6: Execute with error handling ---');
127
- try {
128
- const result = await manager.executeScript({
129
- code: `
130
- // This will cause an error
131
- nonExistentVariable.doSomething();
132
- return 'This will not be returned';
133
- `
134
- });
135
- console.log('Result:', result);
136
- } catch (error) {
137
- console.error('Expected error caught:', error.message);
138
- }
139
-
140
- console.log('\n--- All examples completed! ---');
141
-
142
- // Clean up
143
- await server.stop();
144
- process.exit(0);
145
- }
146
-
147
- main().catch(error => {
148
- console.error('Fatal error:', error);
149
- process.exit(1);
150
- });
@@ -1,37 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { server } from '../lib/websocket/server.js';
4
- import { WebTrackerManager } from '../lib/extension-logs/manager.js';
5
-
6
- async function main() {
7
- console.log('Simple test - make sure you have example.com or any webpage open\n');
8
-
9
- await server.start();
10
- console.log('Server started on port:', server.port);
11
-
12
- const manager = new WebTrackerManager(server);
13
-
14
- console.log('Waiting for extension...');
15
- await new Promise((resolve) => {
16
- const cleanup = server.on('connection', () => {
17
- console.log('Connected!\n');
18
- cleanup();
19
- resolve();
20
- });
21
- });
22
-
23
- await new Promise(resolve => setTimeout(resolve, 500));
24
-
25
- console.log('Test: Get page DOM');
26
- const result = await manager.getPageDOM();
27
- console.log('Title:', result.title);
28
- console.log('URL:', result.url);
29
- console.log('HTML length:', result.html.length, 'characters\n');
30
-
31
- console.log(result.html)
32
-
33
- await server.stop();
34
- process.exit(0);
35
- }
36
-
37
- main().catch(console.error);