dashcam 1.0.1-beta.7 → 1.0.1-beta.9

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
@@ -29,6 +29,10 @@ program
29
29
  .description('Capture the steps to reproduce every bug.')
30
30
  .version(APP.version)
31
31
  .option('-v, --verbose', 'Enable verbose logging output')
32
+ .option('-t, --title <string>', 'Title of the replay (used with create/default action)')
33
+ .option('-d, --description [text]', 'Replay markdown body (used with create/default action)')
34
+ .option('--md', 'Returns code for a rich markdown image link (used with create/default action)')
35
+ .option('-k, --project <project>', 'Project ID to publish to (used with create/default action)')
32
36
  .hook('preAction', (thisCommand) => {
33
37
  // Enable verbose logging if the flag is set
34
38
  if (thisCommand.opts().verbose) {
@@ -148,6 +152,76 @@ async function recordingAction(options, command) {
148
152
  }
149
153
  }
150
154
 
155
+ // Shared create/clip action
156
+ async function createClipAction(options) {
157
+ try {
158
+ // Check for piped input (description from stdin)
159
+ let description = options.description;
160
+ if (!description && !process.stdin.isTTY) {
161
+ const chunks = [];
162
+ for await (const chunk of process.stdin) {
163
+ chunks.push(chunk);
164
+ }
165
+ description = Buffer.concat(chunks).toString('utf-8');
166
+ }
167
+
168
+ if (!processManager.isRecordingActive()) {
169
+ console.log('No active recording to create clip from');
170
+ console.log('Start a recording first with "dashcam record" or "dashcam start"');
171
+ process.exit(0);
172
+ }
173
+
174
+ const activeStatus = processManager.getActiveStatus();
175
+
176
+ console.log('Creating clip from recording...');
177
+
178
+ const result = await processManager.stopActiveRecording();
179
+
180
+ if (!result) {
181
+ console.log('Failed to stop recording');
182
+ process.exit(1);
183
+ }
184
+
185
+ console.log('Recording stopped successfully');
186
+
187
+ // Upload the recording
188
+ console.log('Uploading clip...');
189
+ try {
190
+ const uploadResult = await upload(result.outputPath, {
191
+ title: options.title || activeStatus?.options?.title || 'Dashcam Recording',
192
+ description: description || activeStatus?.options?.description,
193
+ project: options.project || options.k || activeStatus?.options?.project,
194
+ duration: result.duration,
195
+ clientStartDate: result.clientStartDate,
196
+ apps: result.apps,
197
+ icons: result.icons,
198
+ gifPath: result.gifPath,
199
+ snapshotPath: result.snapshotPath
200
+ });
201
+
202
+ // Output based on format option
203
+ if (options.md) {
204
+ const replayId = uploadResult.replay?.id;
205
+ const shareKey = uploadResult.shareLink.split('share=')[1];
206
+ console.log(`[![Dashcam - ${options.title || 'New Replay'}](https://replayable-api-production.herokuapp.com/replay/${replayId}/gif?shareKey=${shareKey})](${uploadResult.shareLink})`);
207
+ console.log('');
208
+ console.log(`Watch [Dashcam - ${options.title || 'New Replay'}](${uploadResult.shareLink}) on Dashcam`);
209
+ } else {
210
+ console.log(uploadResult.shareLink);
211
+ }
212
+ } catch (uploadError) {
213
+ console.error('Upload failed:', uploadError.message);
214
+ console.log('Recording saved locally:', result.outputPath);
215
+ }
216
+
217
+ process.exit(0);
218
+ } catch (error) {
219
+ logger.error('Error creating clip:', error);
220
+ console.error('Failed to create clip:', error.message);
221
+ process.exit(1);
222
+ }
223
+ }
224
+
151
225
  // 'create' command - creates a clip from current recording (like stop but with more options)
152
226
  program
153
227
  .command('create')
@@ -156,74 +230,7 @@ program
156
230
  .option('-d, --description [text]', 'Replay markdown body. This may also be piped in: `cat README.md | dashcam create`')
157
231
  .option('--md', 'Returns code for a rich markdown image link.')
158
232
  .option('-k, --project <project>', 'Project ID to publish to')
159
- .action(async (options) => {
160
- try {
161
- // Check for piped input (description from stdin)
162
- let description = options.description;
163
- if (!description && !process.stdin.isTTY) {
164
- const chunks = [];
165
- for await (const chunk of process.stdin) {
166
- chunks.push(chunk);
167
- }
168
- description = Buffer.concat(chunks).toString('utf-8');
169
- }
170
-
171
- if (!processManager.isRecordingActive()) {
172
- console.log('No active recording to create clip from');
173
- console.log('Start a recording first with "dashcam record" or "dashcam start"');
174
- process.exit(0);
175
- }
176
-
177
- const activeStatus = processManager.getActiveStatus();
178
-
179
- console.log('Creating clip from recording...');
180
-
181
- const result = await processManager.stopActiveRecording();
182
-
183
- if (!result) {
184
- console.log('Failed to stop recording');
185
- process.exit(1);
186
- }
187
-
188
- console.log('Recording stopped successfully');
189
-
190
- // Upload the recording
191
- console.log('Uploading clip...');
192
- try {
193
- const uploadResult = await upload(result.outputPath, {
194
- title: options.title || activeStatus?.options?.title || 'Dashcam Recording',
195
- description: description || activeStatus?.options?.description,
196
- project: options.project || options.k || activeStatus?.options?.project,
197
- duration: result.duration,
198
- clientStartDate: result.clientStartDate,
199
- apps: result.apps,
200
- icons: result.icons,
201
- gifPath: result.gifPath,
202
- snapshotPath: result.snapshotPath
203
- });
204
-
205
- // Output based on format option
206
- if (options.md) {
207
- const replayId = uploadResult.replay?.id;
208
- const shareKey = uploadResult.shareLink.split('share=')[1];
209
- console.log(`[![Dashcam - ${options.title || 'New Replay'}](https://replayable-api-production.herokuapp.com/replay/${replayId}/gif?shareKey=${shareKey})](${uploadResult.shareLink})`);
210
- console.log('');
211
- console.log(`Watch [Dashcam - ${options.title || 'New Replay'}](${uploadResult.shareLink}) on Dashcam`);
212
- } else {
213
- console.log(uploadResult.shareLink);
214
- }
215
- } catch (uploadError) {
216
- console.error('Upload failed:', uploadError.message);
217
- console.log('Recording saved locally:', result.outputPath);
218
- }
219
-
220
- process.exit(0);
221
- } catch (error) {
222
- logger.error('Error creating clip:', error);
223
- console.error('Failed to create clip:', error.message);
224
- process.exit(1);
225
- }
226
- });
233
+ .action(createClipAction);
227
234
 
228
235
  // 'record' command - the main recording command with all options
229
236
  program
@@ -683,13 +690,7 @@ program
683
690
  }
684
691
  });
685
692
 
686
- // If no command specified and there are options like --md, treat as create command
687
- program.action(async (options) => {
688
- // Default to create command when running just "dashcam"
689
- const createCommand = program.commands.find(cmd => cmd.name() === 'create');
690
- if (createCommand && createCommand._actionHandler) {
691
- await createCommand._actionHandler(options);
692
- }
693
- });
693
+ // If no command specified, treat as create command
694
+ program.action(createClipAction);
694
695
 
695
696
  program.parse();
package/lib/ffmpeg.js CHANGED
@@ -18,8 +18,7 @@ export async function createSnapshot(inputVideoPath, outputSnapshotPath, snapsho
18
18
  '-i', inputVideoPath,
19
19
  '-frames:v', '1',
20
20
  '-vf', 'scale=640:-1:force_original_aspect_ratio=decrease:eval=frame',
21
- '-pred', 'mixed',
22
- '-compression_level', '100',
21
+ '-compression_level', '6', // Use default compression (was 100, which is extremely slow)
23
22
  outputSnapshotPath,
24
23
  '-y',
25
24
  '-hide_banner'
package/lib/recorder.js CHANGED
@@ -279,13 +279,13 @@ export async function startRecording({
279
279
  const platformArgs = await getPlatformArgs({ fps, includeAudio });
280
280
  const outputArgs = [
281
281
  '-c:v', 'libvpx-vp9', // Use VP9 codec for better quality and compression
282
- '-quality', 'good', // Use good quality preset for better encoding
283
- '-cpu-used', '2', // Higher quality encoding (0-5, lower = slower but better quality)
284
- '-deadline', 'good', // Good quality encoding mode
285
- '-b:v', '5M', // Higher bitrate for better quality
282
+ '-quality', 'realtime', // Use realtime quality preset for lower CPU usage
283
+ '-cpu-used', '5', // Faster encoding (0-5, higher = faster but lower quality)
284
+ '-deadline', 'realtime', // Realtime encoding mode for lower latency/CPU
285
+ '-b:v', '2M', // Lower bitrate to reduce CPU load (was 5M)
286
286
  // Remove explicit pixel format to let ffmpeg handle conversion automatically
287
287
  '-r', fps.toString(), // Ensure output framerate matches input
288
- '-g', '30', // Keyframe every 30 frames
288
+ '-g', '60', // Keyframe every 60 frames (reduced frequency)
289
289
  // WebM options for more frequent disk writes
290
290
  '-f', 'webm', // Force WebM container format
291
291
  '-flush_packets', '1', // Flush packets immediately to disk
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dashcam",
3
- "version": "1.0.1-beta.7",
3
+ "version": "1.0.1-beta.9",
4
4
  "description": "Minimal CLI version of Dashcam desktop app",
5
5
  "main": "bin/index.js",
6
6
  "bin": {