comfyclips 1.1.0 → 1.2.0

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/README.md CHANGED
@@ -5,11 +5,12 @@ Interactive CLI to download video or audio from social media links (YouTube, Ins
5
5
  ## Requirements
6
6
 
7
7
  - Node.js >= 18
8
- - [ffmpeg](https://ffmpeg.org/) on your PATH — required to merge separate video/audio streams and to extract/convert audio formats. Without it, downloads may fail or fall back to lower quality.
9
- - Debian/Ubuntu: `sudo apt-get install ffmpeg`
10
- - macOS: `brew install ffmpeg`
11
- - Windows: `choco install ffmpeg` (or download from ffmpeg.org and add it to PATH)
12
- - `yt-dlp`not required ahead of time. If it isn't found on your PATH, ComfyClips downloads a copy automatically on first run into `~/.comfyclips/bin`.
8
+
9
+ That's it everything else is provisioned automatically:
10
+
11
+ - **ffmpeg** used to merge separate video/audio streams and to extract/convert audio formats. If it's not on your PATH, `npm install` fetches a static build for your platform (via `ffmpeg-static`).
12
+ - **yt-dlp**if it isn't found on your PATH, ComfyClips downloads a copy on first run into `~/.comfyclips/bin`.
13
+ - **Deno** — YouTube requires a JS runtime to solve its signature challenge. If it isn't found on your PATH, ComfyClips downloads it on first run into `~/.comfyclips/bin`.
13
14
 
14
15
  ## Install
15
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "comfyclips",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Interactive CLI to download video or audio from social media platforms (YouTube, Instagram, TikTok, Facebook, X/Twitter) via yt-dlp.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -35,6 +35,7 @@
35
35
  "chalk": "^5.3.0",
36
36
  "cli-progress": "^3.12.0",
37
37
  "cli-table3": "^0.6.5",
38
+ "ffmpeg-static": "^5.3.0",
38
39
  "figlet": "^1.11.4",
39
40
  "inquirer": "^14.1.0",
40
41
  "ora": "^8.1.0",
package/src/binaries.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import AdmZip from 'adm-zip';
2
+ import ffmpegStaticPath from 'ffmpeg-static';
2
3
  import { spawnSync } from 'node:child_process';
3
4
  import { chmodSync, existsSync, mkdirSync, rmSync } from 'node:fs';
4
5
  import os from 'node:os';
@@ -19,9 +20,18 @@ function commandExists(cmd, versionFlag = '--version') {
19
20
  return !result.error && result.status === 0;
20
21
  }
21
22
 
22
- export function isFfmpegAvailable() {
23
+ // Prefer a system ffmpeg if the user already has one on PATH; otherwise fall
24
+ // back to the static binary `ffmpeg-static` already fetched via its own npm
25
+ // postinstall step, so no separate download step is needed here.
26
+ export function resolveFfmpeg() {
23
27
  // ffmpeg uses single-dash flags (-version), unlike most CLIs.
24
- return commandExists('ffmpeg', '-version');
28
+ if (commandExists('ffmpeg', '-version')) {
29
+ return { available: true, locationArgs: [] };
30
+ }
31
+ if (ffmpegStaticPath && existsSync(ffmpegStaticPath)) {
32
+ return { available: true, locationArgs: ['--ffmpeg-location', ffmpegStaticPath] };
33
+ }
34
+ return { available: false, locationArgs: [] };
25
35
  }
26
36
 
27
37
  function denoAssetName() {
package/src/downloader.js CHANGED
@@ -34,9 +34,18 @@ export function buildArgs({
34
34
  outputDir,
35
35
  ffmpegAvailable,
36
36
  jsRuntimeArgs = [],
37
+ ffmpegLocationArgs = [],
37
38
  }) {
38
39
  const outputTemplate = path.join(outputDir, '%(title)s.%(ext)s');
39
- const args = [url, '-o', outputTemplate, '--no-playlist', '--newline', ...jsRuntimeArgs];
40
+ const args = [
41
+ url,
42
+ '-o',
43
+ outputTemplate,
44
+ '--no-playlist',
45
+ '--newline',
46
+ ...jsRuntimeArgs,
47
+ ...ffmpegLocationArgs,
48
+ ];
40
49
  const warnings = [];
41
50
 
42
51
  if (mode === 'audio') {
@@ -70,6 +79,7 @@ export async function downloadMedia({
70
79
  outputDir,
71
80
  ffmpegAvailable,
72
81
  jsRuntimeArgs,
82
+ ffmpegLocationArgs,
73
83
  }) {
74
84
  mkdirSync(outputDir, { recursive: true });
75
85
 
@@ -82,6 +92,7 @@ export async function downloadMedia({
82
92
  outputDir,
83
93
  ffmpegAvailable,
84
94
  jsRuntimeArgs,
95
+ ffmpegLocationArgs,
85
96
  });
86
97
  warnings.forEach(printWarning);
87
98
 
package/src/index.js CHANGED
@@ -3,7 +3,7 @@ import { readFileSync, statSync } from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import chalk from 'chalk';
5
5
  import inquirer from 'inquirer';
6
- import { isFfmpegAvailable, resolveJsRuntimeArgs, resolveYtDlpBinaryPath } from './binaries.js';
6
+ import { resolveFfmpeg, resolveJsRuntimeArgs, resolveYtDlpBinaryPath } from './binaries.js';
7
7
  import { downloadMedia } from './downloader.js';
8
8
  import { PLATFORMS, hostMatchesPlatform } from './platforms.js';
9
9
  import boxedSelect from './prompts/boxedSelect.js';
@@ -137,7 +137,7 @@ async function main() {
137
137
 
138
138
  try {
139
139
  const binaryPath = await resolveYtDlpBinaryPath();
140
- const ffmpegAvailable = isFfmpegAvailable();
140
+ const { available: ffmpegAvailable, locationArgs: ffmpegLocationArgs } = resolveFfmpeg();
141
141
  const jsRuntimeArgs = await resolveJsRuntimeArgs();
142
142
 
143
143
  const { outputFile, elapsedSeconds } = await downloadMedia({
@@ -149,6 +149,7 @@ async function main() {
149
149
  outputDir,
150
150
  ffmpegAvailable,
151
151
  jsRuntimeArgs,
152
+ ffmpegLocationArgs,
152
153
  });
153
154
 
154
155
  let fileSize = 'Unknown';