dashcam 1.0.1-beta.2 → 1.0.1-beta.22
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/.github/workflows/publish.yml +26 -20
- package/691cc08dc2fc02f59ae66f08 (1).mp4 +0 -0
- package/NPM_PUBLISH_FIX.md +104 -0
- package/SINGLE_FRAME_VIDEO_FIX.md +129 -0
- package/bin/dashcam-background.js +177 -0
- package/bin/dashcam.js +276 -132
- package/lib/ffmpeg.js +9 -40
- package/lib/logs/index.js +67 -11
- package/lib/processManager.js +121 -73
- package/lib/recorder.js +126 -27
- package/lib/tracking/FileTracker.js +7 -0
- package/lib/tracking/LogsTracker.js +21 -7
- package/lib/tracking/icons/index.js +3 -2
- package/lib/tracking/icons/linux.js +277 -0
- package/lib/uploader.js +10 -3
- package/package.json +4 -1
- package/scripts/sync-version.sh +48 -0
- package/test-short-recording.js +287 -0
- package/test_workflow.sh +99 -25
- package/.github/workflows/build.yml +0 -103
- package/.github/workflows/release.yml +0 -107
|
@@ -1,43 +1,49 @@
|
|
|
1
|
-
name: Publish to npm
|
|
1
|
+
name: Publish Beta to npm
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
|
-
branches:
|
|
6
|
-
|
|
5
|
+
branches: [ "main" ]
|
|
6
|
+
workflow_dispatch:
|
|
7
7
|
|
|
8
8
|
jobs:
|
|
9
|
-
publish:
|
|
9
|
+
publish-beta:
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
|
-
|
|
12
|
-
contents: write
|
|
13
|
-
id-token: write
|
|
11
|
+
|
|
14
12
|
steps:
|
|
15
|
-
-
|
|
16
|
-
uses: actions/checkout@v4
|
|
13
|
+
- uses: actions/checkout@v4
|
|
17
14
|
with:
|
|
18
15
|
fetch-depth: 0
|
|
19
|
-
token: ${{ secrets.GITHUB_TOKEN }}
|
|
20
16
|
|
|
21
17
|
- name: Setup Node.js
|
|
22
18
|
uses: actions/setup-node@v4
|
|
23
19
|
with:
|
|
24
|
-
node-version:
|
|
25
|
-
registry-url:
|
|
20
|
+
node-version: "20"
|
|
21
|
+
registry-url: "https://registry.npmjs.org/"
|
|
26
22
|
|
|
27
23
|
- name: Configure Git
|
|
28
24
|
run: |
|
|
29
|
-
git config user.name "github-actions[bot]"
|
|
30
|
-
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
25
|
+
git config --global user.name "github-actions[bot]"
|
|
26
|
+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: npm install
|
|
31
30
|
|
|
32
|
-
- name:
|
|
31
|
+
- name: Commit dependency changes
|
|
33
32
|
run: |
|
|
34
|
-
|
|
33
|
+
git add package-lock.json
|
|
34
|
+
git diff --staged --quiet || git commit -m "chore: update package-lock.json"
|
|
35
35
|
|
|
36
|
-
- name:
|
|
36
|
+
- name: Bump version (prerelease beta)
|
|
37
37
|
run: |
|
|
38
|
-
|
|
38
|
+
npm version prerelease --preid=beta -m "chore: bump beta version to %s"
|
|
39
|
+
env:
|
|
40
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
39
41
|
|
|
40
|
-
- name: Publish to npm
|
|
41
|
-
run: npm publish --
|
|
42
|
+
- name: Publish to npm under beta tag
|
|
43
|
+
run: npm publish --tag beta
|
|
42
44
|
env:
|
|
43
45
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
46
|
+
|
|
47
|
+
- name: Push version bump commit + tag
|
|
48
|
+
run: |
|
|
49
|
+
git push --follow-tags
|
|
Binary file
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# NPM Publish & Version Sync Issues
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
The npm publish workflow was failing with:
|
|
6
|
+
```
|
|
7
|
+
npm error 404 'dashcam@1.0.1-beta.17' is not in this registry.
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Root Cause
|
|
11
|
+
|
|
12
|
+
**Version drift** between local git tags, package.json, and npm registry:
|
|
13
|
+
|
|
14
|
+
- **NPM registry**: `1.0.1-beta.13` (latest successfully published)
|
|
15
|
+
- **Local package.json**: `1.0.1-beta.16` (from failed publish attempts)
|
|
16
|
+
- **Git tags**: Only up to `v1.0.1-beta.9`
|
|
17
|
+
|
|
18
|
+
This happened because the workflow:
|
|
19
|
+
1. Bumped version in package.json
|
|
20
|
+
2. Created git tag
|
|
21
|
+
3. Tried to publish
|
|
22
|
+
4. **Publish failed** (possibly due to test failures or video encoding issues)
|
|
23
|
+
5. Git changes were not reverted, leaving version incremented
|
|
24
|
+
|
|
25
|
+
## Fixes Applied
|
|
26
|
+
|
|
27
|
+
### 1. Updated Publish Workflow
|
|
28
|
+
|
|
29
|
+
**Before**: Version bump → Push → Publish (wrong order!)
|
|
30
|
+
|
|
31
|
+
**After**:
|
|
32
|
+
1. Sync with npm registry version
|
|
33
|
+
2. Bump version
|
|
34
|
+
3. **Publish first** ✅
|
|
35
|
+
4. Push only if publish succeeded ✅
|
|
36
|
+
|
|
37
|
+
```yaml
|
|
38
|
+
- name: Bump version
|
|
39
|
+
run: |
|
|
40
|
+
# Get current version from npm
|
|
41
|
+
CURRENT_NPM_VERSION=$(npm view dashcam dist-tags.beta)
|
|
42
|
+
|
|
43
|
+
# Sync before bumping
|
|
44
|
+
npm version $CURRENT_NPM_VERSION --no-git-tag-version --allow-same-version
|
|
45
|
+
|
|
46
|
+
# Bump to next
|
|
47
|
+
npm version prerelease --preid=beta
|
|
48
|
+
|
|
49
|
+
- name: Publish to npm
|
|
50
|
+
run: npm publish --access public --tag beta
|
|
51
|
+
|
|
52
|
+
- name: Push changes # Only runs if publish succeeded
|
|
53
|
+
run: git push --follow-tags
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2. Created Version Sync Script
|
|
57
|
+
|
|
58
|
+
`scripts/sync-version.sh` - Helps detect and fix version drift:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
./scripts/sync-version.sh
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This will:
|
|
65
|
+
- Compare local version with npm registry
|
|
66
|
+
- Offer to sync package.json
|
|
67
|
+
- Show unpublished git tags that need cleanup
|
|
68
|
+
|
|
69
|
+
### 3. Synced package.json
|
|
70
|
+
|
|
71
|
+
Reset from `1.0.1-beta.16` → `1.0.1-beta.13` (current npm version)
|
|
72
|
+
|
|
73
|
+
## Video Issue Connection
|
|
74
|
+
|
|
75
|
+
The failed publishes were likely caused by **test failures due to the video encoding bugs** we fixed:
|
|
76
|
+
|
|
77
|
+
- Frame rate conflicts
|
|
78
|
+
- Buffer size issues
|
|
79
|
+
- Frame dropping
|
|
80
|
+
- Incomplete container metadata
|
|
81
|
+
|
|
82
|
+
All of these are now fixed in the recorder.js, so future CI runs should succeed.
|
|
83
|
+
|
|
84
|
+
## Next Steps
|
|
85
|
+
|
|
86
|
+
1. ✅ Package.json is synced
|
|
87
|
+
2. ✅ Workflow is fixed
|
|
88
|
+
3. ⚠️ Need to clean up unpublished git tags manually (optional):
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# List tags
|
|
92
|
+
git tag | grep beta
|
|
93
|
+
|
|
94
|
+
# Delete local tags for unpublished versions (14-16)
|
|
95
|
+
git tag -d v1.0.1-beta.14 v1.0.1-beta.15 v1.0.1-beta.16
|
|
96
|
+
|
|
97
|
+
# If they exist on remote, delete them
|
|
98
|
+
git push origin :refs/tags/v1.0.1-beta.14
|
|
99
|
+
git push origin :refs/tags/v1.0.1-beta.15
|
|
100
|
+
git push origin :refs/tags/v1.0.1-beta.16
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
4. Push the fixes to trigger a new publish
|
|
104
|
+
5. Next version will be `1.0.1-beta.14` ✅
|
|
@@ -0,0 +1,129 @@
|
|
|
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
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Background recording process for dashcam CLI
|
|
4
|
+
* This script runs detached from the parent process to handle long-running recordings
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { startRecording, stopRecording } from '../lib/recorder.js';
|
|
8
|
+
import { upload } from '../lib/uploader.js';
|
|
9
|
+
import { logger, setVerbose } from '../lib/logger.js';
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import os from 'os';
|
|
13
|
+
|
|
14
|
+
// Get process directory for status files
|
|
15
|
+
const PROCESS_DIR = path.join(os.homedir(), '.dashcam-cli');
|
|
16
|
+
const STATUS_FILE = path.join(PROCESS_DIR, 'status.json');
|
|
17
|
+
const RESULT_FILE = path.join(PROCESS_DIR, 'upload-result.json');
|
|
18
|
+
|
|
19
|
+
// Parse options from command line argument
|
|
20
|
+
const optionsJson = process.argv[2];
|
|
21
|
+
if (!optionsJson) {
|
|
22
|
+
console.error('No options provided to background process');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const options = JSON.parse(optionsJson);
|
|
27
|
+
|
|
28
|
+
// Enable verbose logging in background
|
|
29
|
+
setVerbose(true);
|
|
30
|
+
|
|
31
|
+
logger.info('Background recording process started', {
|
|
32
|
+
pid: process.pid,
|
|
33
|
+
options
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Write status file
|
|
37
|
+
function writeStatus(status) {
|
|
38
|
+
try {
|
|
39
|
+
fs.writeFileSync(STATUS_FILE, JSON.stringify({
|
|
40
|
+
...status,
|
|
41
|
+
timestamp: Date.now(),
|
|
42
|
+
pid: process.pid
|
|
43
|
+
}, null, 2));
|
|
44
|
+
} catch (error) {
|
|
45
|
+
logger.error('Failed to write status file', { error });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Write upload result file
|
|
50
|
+
function writeUploadResult(result) {
|
|
51
|
+
try {
|
|
52
|
+
logger.info('Writing upload result to file', { path: RESULT_FILE, shareLink: result.shareLink });
|
|
53
|
+
fs.writeFileSync(RESULT_FILE, JSON.stringify({
|
|
54
|
+
...result,
|
|
55
|
+
timestamp: Date.now()
|
|
56
|
+
}, null, 2));
|
|
57
|
+
logger.info('Successfully wrote upload result to file');
|
|
58
|
+
} catch (error) {
|
|
59
|
+
logger.error('Failed to write upload result file', { error });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Main recording function
|
|
64
|
+
async function runBackgroundRecording() {
|
|
65
|
+
let recordingResult = null;
|
|
66
|
+
let isShuttingDown = false;
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
// Start the recording
|
|
70
|
+
const recordingOptions = {
|
|
71
|
+
fps: parseInt(options.fps) || 10,
|
|
72
|
+
includeAudio: options.audio || false,
|
|
73
|
+
customOutputPath: options.output || null
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
logger.info('Starting recording with options', { recordingOptions });
|
|
77
|
+
|
|
78
|
+
recordingResult = await startRecording(recordingOptions);
|
|
79
|
+
|
|
80
|
+
// Write status to track the recording
|
|
81
|
+
writeStatus({
|
|
82
|
+
isRecording: true,
|
|
83
|
+
startTime: recordingResult.startTime,
|
|
84
|
+
options,
|
|
85
|
+
pid: process.pid,
|
|
86
|
+
outputPath: recordingResult.outputPath
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
logger.info('Recording started successfully', {
|
|
90
|
+
outputPath: recordingResult.outputPath,
|
|
91
|
+
startTime: recordingResult.startTime
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Set up signal handlers for graceful shutdown
|
|
95
|
+
const handleShutdown = async (signal) => {
|
|
96
|
+
if (isShuttingDown) {
|
|
97
|
+
logger.info('Shutdown already in progress...');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
isShuttingDown = true;
|
|
101
|
+
|
|
102
|
+
logger.info(`Received ${signal}, stopping background recording...`);
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
// Stop the recording
|
|
106
|
+
const stopResult = await stopRecording();
|
|
107
|
+
|
|
108
|
+
if (stopResult) {
|
|
109
|
+
logger.info('Recording stopped successfully', {
|
|
110
|
+
outputPath: stopResult.outputPath,
|
|
111
|
+
duration: stopResult.duration
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Upload the recording
|
|
115
|
+
logger.info('Starting upload...');
|
|
116
|
+
const uploadResult = await upload(stopResult.outputPath, {
|
|
117
|
+
title: options.title || 'Dashcam Recording',
|
|
118
|
+
description: options.description || 'Recorded with Dashcam CLI',
|
|
119
|
+
project: options.project || options.k,
|
|
120
|
+
duration: stopResult.duration,
|
|
121
|
+
clientStartDate: stopResult.clientStartDate,
|
|
122
|
+
apps: stopResult.apps,
|
|
123
|
+
logs: stopResult.logs,
|
|
124
|
+
gifPath: stopResult.gifPath,
|
|
125
|
+
snapshotPath: stopResult.snapshotPath
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
logger.info('Upload complete', { shareLink: uploadResult.shareLink });
|
|
129
|
+
|
|
130
|
+
// Write upload result for stop command to read
|
|
131
|
+
writeUploadResult({
|
|
132
|
+
shareLink: uploadResult.shareLink,
|
|
133
|
+
replayId: uploadResult.replay?.id
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Update status to indicate recording stopped
|
|
138
|
+
writeStatus({
|
|
139
|
+
isRecording: false,
|
|
140
|
+
completedTime: Date.now(),
|
|
141
|
+
pid: process.pid
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
logger.info('Background process exiting successfully');
|
|
145
|
+
process.exit(0);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
logger.error('Error during shutdown:', error);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
process.on('SIGINT', () => handleShutdown('SIGINT'));
|
|
153
|
+
process.on('SIGTERM', () => handleShutdown('SIGTERM'));
|
|
154
|
+
|
|
155
|
+
// Keep the process alive
|
|
156
|
+
logger.info('Background recording is now running. Waiting for stop signal...');
|
|
157
|
+
await new Promise(() => {}); // Wait indefinitely for signals
|
|
158
|
+
|
|
159
|
+
} catch (error) {
|
|
160
|
+
logger.error('Background recording failed:', error);
|
|
161
|
+
|
|
162
|
+
// Update status to indicate failure
|
|
163
|
+
writeStatus({
|
|
164
|
+
isRecording: false,
|
|
165
|
+
error: error.message,
|
|
166
|
+
pid: process.pid
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Run the background recording
|
|
174
|
+
runBackgroundRecording().catch(error => {
|
|
175
|
+
logger.error('Fatal error in background process:', error);
|
|
176
|
+
process.exit(1);
|
|
177
|
+
});
|