dashcam 1.3.29 → 1.3.31

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.
package/bin/dashcam.js CHANGED
@@ -474,8 +474,6 @@ program
474
474
  logger.debug('Reconstructing recording data from status file');
475
475
 
476
476
  const { fixVideoContainer } = await import('../lib/recorder.js');
477
- const { applicationTracker } = await import('../lib/applicationTracker.js');
478
- const { logsTrackerManager } = await import('../lib/logs/index.js');
479
477
 
480
478
  // Get temp file path
481
479
  const tempFileInfoPath = path.join(os.tmpdir(), 'dashcam', 'temp-file.json');
@@ -504,16 +502,14 @@ program
504
502
  logger.warn('Temp file not found, using output path directly', { tempFile });
505
503
  }
506
504
 
507
- // Collect application and log data
508
- const apps = await applicationTracker.getApps(activeStatus.startTime);
509
- const logs = await logsTrackerManager.getLogsForRecording();
510
-
505
+ // We killed the process, so we don't have apps/logs data
506
+ // The recording is still on disk and can be uploaded without metadata
511
507
  const recordingResult = {
512
508
  outputPath,
513
509
  duration: result.duration,
514
510
  clientStartDate: activeStatus.startTime,
515
- apps,
516
- logs,
511
+ apps: [],
512
+ logs: [],
517
513
  title: activeStatus?.options?.title,
518
514
  description: activeStatus?.options?.description,
519
515
  project: activeStatus?.options?.project
@@ -14,10 +14,10 @@ import { WebTrackerManager } from '../lib/extension-logs/manager.js';
14
14
  import { logger } from '../lib/logger.js';
15
15
 
16
16
  async function main() {
17
- console.log('╔════════════════════════════════════════════════════════════════╗');
18
- console.log(' Chrome Extension Script Execution Example');
19
- console.log('╚════════════════════════════════════════════════════════════════╝\n');
20
- console.log('📋 Prerequisites:');
17
+ console.log('================================================================');
18
+ console.log(' Chrome Extension Script Execution Example');
19
+ console.log('================================================================\n');
20
+ console.log('Prerequisites:');
21
21
  console.log(' 1. Chrome extension must be installed and loaded');
22
22
  console.log(' 2. Have a regular webpage open (NOT chrome:// or chrome-extension://)');
23
23
  console.log(' 3. For best results, navigate to a simple page like example.com\n');
@@ -26,21 +26,19 @@ async function main() {
26
26
 
27
27
  // Start the WebSocket server
28
28
  await server.start();
29
- console.log('WebSocket server started on port:', server.port);
30
-
31
- // Create the WebTrackerManager
29
+ console.log('WebSocket server started on port:', server.port); // Create the WebTrackerManager
32
30
  const manager = new WebTrackerManager(server);
33
31
 
34
32
  // Wait for the Chrome extension to connect
35
33
  console.log('\nWaiting for Chrome extension to connect...');
36
34
  const connected = await new Promise((resolve) => {
37
35
  const timeout = setTimeout(() => {
38
- console.log('⏱️ Timeout waiting for connection');
36
+ console.log('Timeout waiting for connection');
39
37
  resolve(false);
40
38
  }, 10000);
41
39
 
42
40
  const cleanup = server.on('connection', (client) => {
43
- console.log('Chrome extension connected!');
41
+ console.log('Chrome extension connected!');
44
42
  clearTimeout(timeout);
45
43
  cleanup();
46
44
  resolve(true);
@@ -48,7 +46,7 @@ async function main() {
48
46
  });
49
47
 
50
48
  if (!connected) {
51
- console.error('\n❌ Chrome extension did not connect.');
49
+ console.error('\nChrome extension did not connect.');
52
50
  console.error(' Make sure the extension is installed and running.');
53
51
  console.error(' Check chrome://extensions to verify it\'s loaded.');
54
52
  process.exit(1);
@@ -62,9 +60,9 @@ async function main() {
62
60
  const result = await manager.executeScript({
63
61
  code: 'return document.title;'
64
62
  });
65
- console.log('Page title:', result);
63
+ console.log('Page title:', result);
66
64
  } catch (error) {
67
- console.error('Error:', error.message);
65
+ console.error('Error:', error.message);
68
66
  }
69
67
 
70
68
  console.log('\n--- Example 2: Get current URL ---');
@@ -96,7 +94,7 @@ async function main() {
96
94
  code: `
97
95
  const div = document.createElement('div');
98
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);';
99
- div.textContent = 'Hello from CLI! 👋';
97
+ div.textContent = 'Hello from CLI!';
100
98
  document.body.appendChild(div);
101
99
 
102
100
  // Remove after 5 seconds
package/lib/logger.js CHANGED
@@ -109,9 +109,9 @@ logger.trace = (message, meta) => logger.silly(`[TRACE] ${message}`, meta);
109
109
  // Function to log function entry/exit for debugging
110
110
  export function logFunctionCall(functionName, args = {}) {
111
111
  if (isVerbose) {
112
- logger.debug(`→ Entering ${functionName}`, { args });
112
+ logger.debug(`Entering ${functionName}`, { args });
113
113
  return (result) => {
114
- logger.debug(`← Exiting ${functionName}`, { result: typeof result });
114
+ logger.debug(`Exiting ${functionName}`, { result: typeof result });
115
115
  };
116
116
  }
117
117
  return () => {}; // No-op if not verbose
@@ -50,7 +50,7 @@ function showPermissionInstructions() {
50
50
  return;
51
51
  }
52
52
 
53
- console.log('\n⚠️ Screen Recording Permission Required\n');
53
+ console.log('\nScreen Recording Permission Required\n');
54
54
  console.log('Dashcam needs screen recording permission to capture your screen.');
55
55
  console.log('\nTo grant permission:');
56
56
  console.log('1. Open System Settings (or System Preferences)');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dashcam",
3
- "version": "1.3.29",
3
+ "version": "1.3.31",
4
4
  "description": "Minimal CLI version of Dashcam desktop app",
5
5
  "main": "bin/dashcam.js",
6
6
  "bin": {
@@ -30,17 +30,17 @@ import os from 'os';
30
30
  async function analyzeVideo(videoPath) {
31
31
  const ffprobePath = await getFfprobePath();
32
32
 
33
- console.log(`\n📊 Analyzing video: ${videoPath}`);
34
- console.log(''.repeat(80));
33
+ console.log(`\nAnalyzing video: ${videoPath}`);
34
+ console.log('='.repeat(80));
35
35
 
36
36
  // Check if file exists
37
37
  if (!fs.existsSync(videoPath)) {
38
- console.error(`❌ Video file does not exist: ${videoPath}`);
38
+ console.error(`Video file does not exist: ${videoPath}`);
39
39
  return null;
40
40
  }
41
41
 
42
42
  const stats = fs.statSync(videoPath);
43
- console.log(`📁 File size: ${(stats.size / 1024).toFixed(2)} KB`);
43
+ console.log(`File size: ${(stats.size / 1024).toFixed(2)} KB`);
44
44
 
45
45
  try {
46
46
  // Get basic format info
@@ -52,8 +52,8 @@ async function analyzeVideo(videoPath) {
52
52
  ]);
53
53
 
54
54
  const formatData = JSON.parse(formatResult.stdout);
55
- console.log(`⏱️ Duration: ${formatData.format.duration || 'unknown'}s`);
56
- console.log(`📊 Bit rate: ${formatData.format.bit_rate || 'unknown'} bits/s`);
55
+ console.log(`Duration: ${formatData.format.duration || 'unknown'}s`);
56
+ console.log(`Bit rate: ${formatData.format.bit_rate || 'unknown'} bits/s`);
57
57
 
58
58
  // Get stream info
59
59
  const streamResult = await execa(ffprobePath, [
@@ -67,9 +67,9 @@ async function analyzeVideo(videoPath) {
67
67
  const videoStream = streamData.streams.find(s => s.codec_name);
68
68
 
69
69
  if (videoStream) {
70
- console.log(`🎥 Codec: ${videoStream.codec_name}`);
71
- console.log(`📐 Resolution: ${videoStream.width}x${videoStream.height}`);
72
- console.log(`🎞️ Frame rate: ${videoStream.r_frame_rate}`);
70
+ console.log(`Codec: ${videoStream.codec_name}`);
71
+ console.log(`Resolution: ${videoStream.width}x${videoStream.height}`);
72
+ console.log(`Frame rate: ${videoStream.r_frame_rate}`);
73
73
  }
74
74
 
75
75
  // Count actual frames
@@ -83,10 +83,10 @@ async function analyzeVideo(videoPath) {
83
83
  ], { reject: false });
84
84
 
85
85
  const frameCount = parseInt(frameResult.stdout.trim());
86
- console.log(`🖼️ Frame count: ${frameCount || 'unknown'}`);
86
+ console.log(`Frame count: ${frameCount || 'unknown'}`);
87
87
 
88
88
  if (frameResult.stderr) {
89
- console.log(`⚠️ FFprobe warnings: ${frameResult.stderr.trim()}`);
89
+ console.log(`FFprobe warnings: ${frameResult.stderr.trim()}`);
90
90
  }
91
91
 
92
92
  // Check if duration is available in container
@@ -97,10 +97,10 @@ async function analyzeVideo(videoPath) {
97
97
  const hasEncodingIssues = frameResult.stderr.includes('File ended prematurely');
98
98
  const hasMissingMetadata = !hasDuration;
99
99
 
100
- console.log('\n📋 Analysis Result:');
101
- console.log(` Single frame: ${isSingleFrame ? 'YES (BUG!)' : 'NO'}`);
102
- console.log(` Encoding issues: ${hasEncodingIssues ? '⚠️ YES' : 'NO'}`);
103
- console.log(` Missing metadata: ${hasMissingMetadata ? '⚠️ YES (container incomplete)' : 'NO'}`);
100
+ console.log('\nAnalysis Result:');
101
+ console.log(` Single frame: ${isSingleFrame ? 'YES (BUG!)' : 'NO'}`);
102
+ console.log(` Encoding issues: ${hasEncodingIssues ? 'YES' : 'NO'}`);
103
+ console.log(` Missing metadata: ${hasMissingMetadata ? 'YES (container incomplete)' : 'NO'}`);
104
104
  console.log(` Platform: ${os.platform()}`);
105
105
 
106
106
  return {
@@ -117,34 +117,34 @@ async function analyzeVideo(videoPath) {
117
117
  };
118
118
 
119
119
  } catch (error) {
120
- console.error(`❌ Error analyzing video: ${error.message}`);
120
+ console.error(`Error analyzing video: ${error.message}`);
121
121
  return null;
122
122
  }
123
123
  }
124
124
 
125
125
  async function testShortRecording(duration = 3000) {
126
- console.log(`\n🎬 Testing ${duration}ms recording...`);
127
- console.log(''.repeat(80));
126
+ console.log(`\nTesting ${duration}ms recording...`);
127
+ console.log('='.repeat(80));
128
128
 
129
129
  try {
130
130
  // Start recording
131
- console.log('▶️ Starting recording...');
131
+ console.log('Starting recording...');
132
132
  const { outputPath, startTime } = await startRecording({
133
133
  fps: 30,
134
134
  includeAudio: false
135
135
  });
136
136
 
137
- console.log(`✅ Recording started at: ${outputPath}`);
137
+ console.log(`Recording started at: ${outputPath}`);
138
138
 
139
139
  // Wait for specified duration
140
- console.log(`⏳ Recording for ${duration}ms...`);
140
+ console.log(`Recording for ${duration}ms...`);
141
141
  await new Promise(resolve => setTimeout(resolve, duration));
142
142
 
143
143
  // Stop recording
144
- console.log('⏹️ Stopping recording...');
144
+ console.log('Stopping recording...');
145
145
  const result = await stopRecording();
146
146
 
147
- console.log(`✅ Recording stopped`);
147
+ console.log(`Recording stopped`);
148
148
  console.log(` Duration: ${result.duration}ms`);
149
149
  console.log(` File: ${result.outputPath}`);
150
150
 
@@ -154,15 +154,15 @@ async function testShortRecording(duration = 3000) {
154
154
  return result;
155
155
 
156
156
  } catch (error) {
157
- console.error(`❌ Test failed: ${error.message}`);
157
+ console.error(`Test failed: ${error.message}`);
158
158
  console.error(error.stack);
159
159
  throw error;
160
160
  }
161
161
  }
162
162
 
163
163
  async function testExistingVideo(videoPath) {
164
- console.log('\n🔍 Testing existing video...');
165
- console.log(''.repeat(80));
164
+ console.log('\nTesting existing video...');
165
+ console.log('='.repeat(80));
166
166
 
167
167
  return await analyzeVideo(videoPath);
168
168
  }
@@ -171,8 +171,8 @@ async function testExistingVideo(videoPath) {
171
171
  async function main() {
172
172
  const args = process.argv.slice(2);
173
173
 
174
- console.log('\n🧪 Short Recording Test Suite');
175
- console.log(''.repeat(80));
174
+ console.log('\nShort Recording Test Suite');
175
+ console.log('='.repeat(80));
176
176
  console.log(`Platform: ${os.platform()}`);
177
177
  console.log(`Architecture: ${os.arch()}`);
178
178
  console.log(`Node version: ${process.version}`);
@@ -183,13 +183,13 @@ async function main() {
183
183
  const result = await testExistingVideo(videoPath);
184
184
 
185
185
  if (result?.isSingleFrame) {
186
- console.log('\n❌ SINGLE-FRAME VIDEO DETECTED!');
186
+ console.log('\nSINGLE-FRAME VIDEO DETECTED!');
187
187
  process.exit(1);
188
188
  } else if (result?.hasMissingMetadata) {
189
- console.log('\n⚠️ WARNING: Video container metadata is incomplete!');
189
+ console.log('\nWARNING: Video container metadata is incomplete!');
190
190
  console.log(' This can cause playback issues in some players.');
191
191
  console.log(' The video has frames but duration is not in the container.');
192
- console.log('\n💡 Try fixing it with:');
192
+ console.log('\nTry fixing it with:');
193
193
  console.log(` node test-short-recording.js fix ${args[1]} ${args[1].replace(/\.(webm|mp4)$/, '-fixed.$1')}`);
194
194
  process.exit(1);
195
195
  }
@@ -198,38 +198,38 @@ async function main() {
198
198
  const inputPath = path.resolve(args[1]);
199
199
  const outputPath = path.resolve(args[2]);
200
200
 
201
- console.log('\n🔧 Fixing video container...');
202
- console.log(''.repeat(80));
201
+ console.log('\nFixing video container...');
202
+ console.log('='.repeat(80));
203
203
  console.log(`Input: ${inputPath}`);
204
204
  console.log(`Output: ${outputPath}`);
205
205
 
206
206
  if (!fs.existsSync(inputPath)) {
207
- console.error(`❌ Input file does not exist: ${inputPath}`);
207
+ console.error(`Input file does not exist: ${inputPath}`);
208
208
  process.exit(1);
209
209
  }
210
210
 
211
211
  // Analyze before
212
- console.log('\n📊 BEFORE:');
212
+ console.log('\nBEFORE:');
213
213
  const beforeResult = await analyzeVideo(inputPath);
214
214
 
215
215
  // Fix the video
216
216
  const fixSuccess = await fixVideoContainer(inputPath, outputPath);
217
217
 
218
218
  if (!fixSuccess) {
219
- console.error('\n❌ Failed to fix video!');
219
+ console.error('\nFailed to fix video!');
220
220
  process.exit(1);
221
221
  }
222
222
 
223
223
  // Analyze after
224
- console.log('\n📊 AFTER:');
224
+ console.log('\nAFTER:');
225
225
  const afterResult = await analyzeVideo(outputPath);
226
226
 
227
- console.log('\n✅ Video fixed successfully!');
228
- console.log(` Before: ${beforeResult?.hasMissingMetadata ? 'Missing metadata ⚠️' : 'Has metadata'}`);
229
- console.log(` After: ${afterResult?.hasMissingMetadata ? 'Missing metadata ⚠️' : 'Has metadata'}`);
227
+ console.log('\nVideo fixed successfully!');
228
+ console.log(` Before: ${beforeResult?.hasMissingMetadata ? 'Missing metadata' : 'Has metadata'}`);
229
+ console.log(` After: ${afterResult?.hasMissingMetadata ? 'Missing metadata' : 'Has metadata'}`);
230
230
 
231
231
  if (afterResult?.hasMissingMetadata) {
232
- console.log('\n⚠️ Warning: Metadata still missing after fix. The source file may be corrupted.');
232
+ console.log('\nWarning: Metadata still missing after fix. The source file may be corrupted.');
233
233
  process.exit(1);
234
234
  }
235
235
  } else {
@@ -252,7 +252,7 @@ async function main() {
252
252
  fs.unlinkSync(result.snapshotPath);
253
253
  }
254
254
  } catch (cleanupError) {
255
- console.warn(`⚠️ Cleanup warning: ${cleanupError.message}`);
255
+ console.warn(`Cleanup warning: ${cleanupError.message}`);
256
256
  }
257
257
  } catch (error) {
258
258
  results.push({ duration, success: false, error: error.message });
@@ -263,20 +263,20 @@ async function main() {
263
263
  }
264
264
 
265
265
  // Summary
266
- console.log('\n\n📊 TEST SUMMARY');
267
- console.log(''.repeat(80));
266
+ console.log('\n\nTEST SUMMARY');
267
+ console.log('='.repeat(80));
268
268
 
269
269
  for (const result of results) {
270
- const status = result.success ? '' : '';
270
+ const status = result.success ? 'PASS' : 'FAIL';
271
271
  console.log(`${status} ${result.duration}ms recording: ${result.success ? 'PASSED' : result.error}`);
272
272
  }
273
273
 
274
274
  const allPassed = results.every(r => r.success);
275
275
  if (!allPassed) {
276
- console.log('\n❌ Some tests failed!');
276
+ console.log('\nSome tests failed!');
277
277
  process.exit(1);
278
278
  } else {
279
- console.log('\n✅ All tests passed!');
279
+ console.log('\nAll tests passed!');
280
280
  }
281
281
  }
282
282
  }