dashcam 1.3.27 → 1.3.29

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.
@@ -217,7 +217,7 @@ async function runBackgroundRecording() {
217
217
  process.on('SIGINT', () => handleShutdown('SIGINT'));
218
218
  process.on('SIGTERM', () => handleShutdown('SIGTERM'));
219
219
 
220
- // Keep the process alive - wait indefinitely for signals
220
+ // Keep the process alive - wait indefinitely for SIGKILL from stop command
221
221
  logger.info('Background recording is now running. Waiting for stop signal...');
222
222
  console.log('[Background] Waiting for stop signal...');
223
223
 
@@ -235,7 +235,7 @@ async function runBackgroundRecording() {
235
235
  process.exit(1);
236
236
  }
237
237
 
238
- // Infinite loop - process will only exit via signal handlers
238
+ // Infinite loop - process will only exit via signal handlers or stop file
239
239
  await new Promise(() => {});
240
240
  }
241
241
 
package/bin/dashcam.js CHANGED
@@ -469,36 +469,63 @@ program
469
469
  console.log('Recording stopped successfully');
470
470
  logger.debug('Stop result:', result);
471
471
 
472
- // Wait for background process to write recording result
473
- logger.debug('Waiting for recording result from background process...');
474
- console.log('Waiting for recording result...');
472
+ // Reconstruct recording data from status and fix video with FFmpeg
473
+ console.log('Processing recording...');
474
+ logger.debug('Reconstructing recording data from status file');
475
475
 
476
- // Wait up to 30 seconds for recording result to appear
477
- const maxWaitForResult = 30000;
478
- const startWaitForResult = Date.now();
479
- let recordingResult = null;
480
- let checkCount = 0;
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');
481
479
 
482
- while (!recordingResult && (Date.now() - startWaitForResult) < maxWaitForResult) {
483
- recordingResult = processManager.readRecordingResult();
484
- checkCount++;
485
-
486
- if (!recordingResult) {
487
- if (checkCount % 5 === 0) {
488
- const elapsed = Math.round((Date.now() - startWaitForResult) / 1000);
489
- console.log(`Waiting for recording result... (${elapsed}s)`);
490
- }
491
- await new Promise(resolve => setTimeout(resolve, 1000));
480
+ // Get temp file path
481
+ const tempFileInfoPath = path.join(os.tmpdir(), 'dashcam', 'temp-file.json');
482
+ let tempFileInfo = null;
483
+ try {
484
+ tempFileInfo = JSON.parse(fs.readFileSync(tempFileInfoPath, 'utf8'));
485
+ } catch (error) {
486
+ logger.error('Failed to read temp file info', { error });
487
+ }
488
+
489
+ const tempFile = tempFileInfo?.tempFile || result.outputPath.replace('.webm', '-temp.webm');
490
+ const outputPath = result.outputPath;
491
+
492
+ // Fix the video with FFmpeg (handle incomplete recordings)
493
+ logger.info('Fixing video with FFmpeg', { tempFile, outputPath });
494
+ if (fs.existsSync(tempFile)) {
495
+ try {
496
+ await fixVideoContainer(tempFile, outputPath);
497
+ logger.info('Video fixed successfully');
498
+ } catch (error) {
499
+ logger.warn('FFmpeg fix failed, using temp file as-is', { error: error.message });
500
+ // If fix fails, just copy the temp file
501
+ fs.copyFileSync(tempFile, outputPath);
492
502
  }
503
+ } else {
504
+ logger.warn('Temp file not found, using output path directly', { tempFile });
493
505
  }
494
506
 
507
+ // Collect application and log data
508
+ const apps = await applicationTracker.getApps(activeStatus.startTime);
509
+ const logs = await logsTrackerManager.getLogsForRecording();
510
+
511
+ const recordingResult = {
512
+ outputPath,
513
+ duration: result.duration,
514
+ clientStartDate: activeStatus.startTime,
515
+ apps,
516
+ logs,
517
+ title: activeStatus?.options?.title,
518
+ description: activeStatus?.options?.description,
519
+ project: activeStatus?.options?.project
520
+ };
521
+
495
522
  if (!recordingResult || !recordingResult.outputPath) {
496
- console.error('Failed to get recording result from background process');
497
- logger.error('No recording result received', { recordingResult });
523
+ console.error('Failed to process recording');
524
+ logger.error('No recording result', { recordingResult });
498
525
  process.exit(1);
499
526
  }
500
527
 
501
- console.log('Recording result received, uploading...');
528
+ console.log('Uploading recording...');
502
529
  logger.debug('Recording result:', recordingResult);
503
530
 
504
531
  try {
@@ -11,7 +11,7 @@ const __dirname = path.dirname(__filename);
11
11
  // Use user home directory for cross-session communication
12
12
  const PROCESS_DIR = path.join(os.homedir(), '.dashcam-cli');
13
13
  const STATUS_FILE = path.join(PROCESS_DIR, 'status.json');
14
- const RESULT_FILE = path.join(PROCESS_DIR, 'recording-result.json');
14
+ const RECORDING_RESULT_FILE = path.join(PROCESS_DIR, 'recording-result.json');
15
15
 
16
16
  console.log('[INIT] Process Manager initialized');
17
17
  console.log('[INIT] Process directory:', PROCESS_DIR);
@@ -281,36 +281,33 @@ class ProcessManager {
281
281
  return false;
282
282
  }
283
283
 
284
- logger.info('Sending stop signal to background process', { pid });
284
+ logger.info('Killing background process', { pid });
285
285
 
286
- // Send SIGTERM to the background process to trigger graceful shutdown
286
+ // Kill the process immediately - no graceful shutdown needed
287
+ // Video is already being streamed to disk, we'll fix it with FFmpeg
287
288
  try {
288
- process.kill(pid, 'SIGTERM');
289
- logger.info('Sent SIGTERM to background process');
289
+ process.kill(pid, 'SIGKILL');
290
+ logger.info('Sent SIGKILL to background process');
290
291
  } catch (error) {
291
- logger.error('Failed to send signal to background process', { error });
292
+ logger.error('Failed to kill background process', { error });
292
293
  throw new Error('Failed to stop background recording process');
293
294
  }
294
295
 
295
- // Wait for the background process to finish and write results
296
- logger.debug('Waiting for background process to complete...');
297
- const maxWaitTime = 30000; // 30 seconds
296
+ // Wait briefly for process to die
297
+ logger.debug('Waiting for background process to exit...');
298
+ const maxWaitTime = 5000; // 5 seconds should be plenty for SIGKILL
298
299
  const startWait = Date.now();
299
300
 
300
301
  while (this.isProcessRunning(pid) && (Date.now() - startWait) < maxWaitTime) {
301
- await new Promise(resolve => setTimeout(resolve, 500));
302
+ await new Promise(resolve => setTimeout(resolve, 100));
302
303
  }
303
304
 
304
305
  if (this.isProcessRunning(pid)) {
305
- logger.error('Background process did not exit within timeout, forcing kill');
306
- try {
307
- process.kill(pid, 'SIGKILL');
308
- } catch (error) {
309
- logger.error('Failed to force kill background process', { error });
310
- }
306
+ logger.error('Background process did not exit after SIGKILL');
307
+ throw new Error('Failed to kill background process');
311
308
  }
312
309
 
313
- logger.info('Background process stopped');
310
+ logger.info('Background process killed');
314
311
 
315
312
  // Mark status as completed
316
313
  this.markStatusCompleted({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dashcam",
3
- "version": "1.3.27",
3
+ "version": "1.3.29",
4
4
  "description": "Minimal CLI version of Dashcam desktop app",
5
5
  "main": "bin/dashcam.js",
6
6
  "bin": {