@wovin/tranz 0.1.8 → 0.1.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/dist/audio.min.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/utils/audio/split.ts
2
- import ffmpeg from "fluent-ffmpeg";
2
+ import { execa } from "execa";
3
3
  import * as fs from "fs";
4
4
  import path from "path";
5
5
  import { spawn } from "child_process";
@@ -11,21 +11,54 @@ var DEFAULT_SPLIT_CONFIG = {
11
11
  preferLongerSilence: true,
12
12
  silenceBuffer: 0.2
13
13
  };
14
+ async function execFFprobe(audioPath) {
15
+ try {
16
+ const { stdout } = await execa("ffprobe", [
17
+ "-v",
18
+ "quiet",
19
+ "-print_format",
20
+ "json",
21
+ "-show_format",
22
+ audioPath
23
+ ]);
24
+ return JSON.parse(stdout);
25
+ } catch (err) {
26
+ throw new Error(`Failed to probe audio: ${err instanceof Error ? err.message : String(err)}`);
27
+ }
28
+ }
29
+ async function extractAudioSegment(inputPath, outputPath, startSec, durationSec) {
30
+ try {
31
+ await execa("ffmpeg", [
32
+ "-ss",
33
+ startSec.toString(),
34
+ "-t",
35
+ durationSec.toString(),
36
+ "-i",
37
+ inputPath,
38
+ "-ar",
39
+ "16000",
40
+ // 16kHz sample rate (Whisper-compatible)
41
+ "-ac",
42
+ "1",
43
+ // mono
44
+ "-c:a",
45
+ "pcm_s16le",
46
+ // 16-bit PCM codec
47
+ "-y",
48
+ // overwrite output
49
+ outputPath
50
+ ]);
51
+ } catch (err) {
52
+ throw new Error(`Failed to extract segment: ${err instanceof Error ? err.message : String(err)}`);
53
+ }
54
+ }
14
55
  async function getAudioDuration(audioPath) {
15
- return new Promise((resolve, reject) => {
16
- ffmpeg.ffprobe(audioPath, (err, metadata) => {
17
- if (err) {
18
- reject(new Error(`Failed to probe audio: ${err.message}`));
19
- return;
20
- }
21
- const duration = metadata.format.duration;
22
- if (typeof duration !== "number") {
23
- reject(new Error("Could not determine audio duration"));
24
- return;
25
- }
26
- resolve(duration);
27
- });
28
- });
56
+ const metadata = await execFFprobe(audioPath);
57
+ const duration = metadata.format.duration;
58
+ if (typeof duration !== "number") {
59
+ throw new Error("Could not determine audio duration");
60
+ }
61
+ return duration;
29
62
  }
30
63
  async function detectSilenceRegions(audioPath, config = {}) {
31
64
  const { minSilenceDurSec, silenceThreshold } = { ...DEFAULT_SPLIT_CONFIG, ...config };
@@ -143,8 +176,13 @@ async function splitAudioAtPoints(audioPath, splitPoints, totalDuration, outputD
143
176
  outputPath
144
177
  };
145
178
  segments.push(segment);
146
- const extractPromise = new Promise((resolve, reject) => {
147
- ffmpeg(audioPath).setStartTime(startSec).setDuration(durationSec).audioFrequency(16e3).outputOptions(["-ac 1", "-c:a pcm_s16le"]).output(outputPath).on("error", (err) => reject(new Error(`Failed to extract segment ${i}: ${err.message}`))).on("end", () => resolve()).run();
179
+ const extractPromise = extractAudioSegment(
180
+ audioPath,
181
+ outputPath,
182
+ startSec,
183
+ durationSec
184
+ ).catch((err) => {
185
+ throw new Error(`Failed to extract segment ${i}: ${err instanceof Error ? err.message : String(err)}`);
148
186
  });
149
187
  splitPromises.push(extractPromise);
150
188
  }
package/dist/index.min.js CHANGED
@@ -349,7 +349,7 @@ var GreenPTProvider = class {
349
349
  };
350
350
 
351
351
  // src/utils/audio/split.ts
352
- import ffmpeg from "fluent-ffmpeg";
352
+ import { execa } from "execa";
353
353
  import * as fs2 from "fs";
354
354
  import path2 from "path";
355
355
  import { spawn as spawn2 } from "child_process";
@@ -361,21 +361,54 @@ var DEFAULT_SPLIT_CONFIG = {
361
361
  preferLongerSilence: true,
362
362
  silenceBuffer: 0.2
363
363
  };
364
+ async function execFFprobe(audioPath) {
365
+ try {
366
+ const { stdout } = await execa("ffprobe", [
367
+ "-v",
368
+ "quiet",
369
+ "-print_format",
370
+ "json",
371
+ "-show_format",
372
+ audioPath
373
+ ]);
374
+ return JSON.parse(stdout);
375
+ } catch (err) {
376
+ throw new Error(`Failed to probe audio: ${err instanceof Error ? err.message : String(err)}`);
377
+ }
378
+ }
379
+ async function extractAudioSegment(inputPath, outputPath, startSec, durationSec) {
380
+ try {
381
+ await execa("ffmpeg", [
382
+ "-ss",
383
+ startSec.toString(),
384
+ "-t",
385
+ durationSec.toString(),
386
+ "-i",
387
+ inputPath,
388
+ "-ar",
389
+ "16000",
390
+ // 16kHz sample rate (Whisper-compatible)
391
+ "-ac",
392
+ "1",
393
+ // mono
394
+ "-c:a",
395
+ "pcm_s16le",
396
+ // 16-bit PCM codec
397
+ "-y",
398
+ // overwrite output
399
+ outputPath
400
+ ]);
401
+ } catch (err) {
402
+ throw new Error(`Failed to extract segment: ${err instanceof Error ? err.message : String(err)}`);
403
+ }
404
+ }
364
405
  async function getAudioDuration(audioPath) {
365
- return new Promise((resolve, reject) => {
366
- ffmpeg.ffprobe(audioPath, (err, metadata) => {
367
- if (err) {
368
- reject(new Error(`Failed to probe audio: ${err.message}`));
369
- return;
370
- }
371
- const duration = metadata.format.duration;
372
- if (typeof duration !== "number") {
373
- reject(new Error("Could not determine audio duration"));
374
- return;
375
- }
376
- resolve(duration);
377
- });
378
- });
406
+ const metadata = await execFFprobe(audioPath);
407
+ const duration = metadata.format.duration;
408
+ if (typeof duration !== "number") {
409
+ throw new Error("Could not determine audio duration");
410
+ }
411
+ return duration;
379
412
  }
380
413
  async function detectSilenceRegions(audioPath, config = {}) {
381
414
  const { minSilenceDurSec, silenceThreshold } = { ...DEFAULT_SPLIT_CONFIG, ...config };
@@ -493,8 +526,13 @@ async function splitAudioAtPoints(audioPath, splitPoints, totalDuration, outputD
493
526
  outputPath
494
527
  };
495
528
  segments.push(segment);
496
- const extractPromise = new Promise((resolve, reject) => {
497
- ffmpeg(audioPath).setStartTime(startSec).setDuration(durationSec).audioFrequency(16e3).outputOptions(["-ac 1", "-c:a pcm_s16le"]).output(outputPath).on("error", (err) => reject(new Error(`Failed to extract segment ${i}: ${err.message}`))).on("end", () => resolve()).run();
529
+ const extractPromise = extractAudioSegment(
530
+ audioPath,
531
+ outputPath,
532
+ startSec,
533
+ durationSec
534
+ ).catch((err) => {
535
+ throw new Error(`Failed to extract segment ${i}: ${err instanceof Error ? err.message : String(err)}`);
498
536
  });
499
537
  splitPromises.push(extractPromise);
500
538
  }
@@ -356,7 +356,7 @@ import * as os from "os";
356
356
  import * as path3 from "path";
357
357
 
358
358
  // src/utils/audio/split.ts
359
- import ffmpeg from "fluent-ffmpeg";
359
+ import { execa } from "execa";
360
360
  import * as fs2 from "fs";
361
361
  import path2 from "path";
362
362
  import { spawn as spawn2 } from "child_process";
@@ -368,21 +368,54 @@ var DEFAULT_SPLIT_CONFIG = {
368
368
  preferLongerSilence: true,
369
369
  silenceBuffer: 0.2
370
370
  };
371
+ async function execFFprobe(audioPath) {
372
+ try {
373
+ const { stdout } = await execa("ffprobe", [
374
+ "-v",
375
+ "quiet",
376
+ "-print_format",
377
+ "json",
378
+ "-show_format",
379
+ audioPath
380
+ ]);
381
+ return JSON.parse(stdout);
382
+ } catch (err) {
383
+ throw new Error(`Failed to probe audio: ${err instanceof Error ? err.message : String(err)}`);
384
+ }
385
+ }
386
+ async function extractAudioSegment(inputPath, outputPath, startSec, durationSec) {
387
+ try {
388
+ await execa("ffmpeg", [
389
+ "-ss",
390
+ startSec.toString(),
391
+ "-t",
392
+ durationSec.toString(),
393
+ "-i",
394
+ inputPath,
395
+ "-ar",
396
+ "16000",
397
+ // 16kHz sample rate (Whisper-compatible)
398
+ "-ac",
399
+ "1",
400
+ // mono
401
+ "-c:a",
402
+ "pcm_s16le",
403
+ // 16-bit PCM codec
404
+ "-y",
405
+ // overwrite output
406
+ outputPath
407
+ ]);
408
+ } catch (err) {
409
+ throw new Error(`Failed to extract segment: ${err instanceof Error ? err.message : String(err)}`);
410
+ }
411
+ }
371
412
  async function getAudioDuration(audioPath) {
372
- return new Promise((resolve, reject) => {
373
- ffmpeg.ffprobe(audioPath, (err, metadata) => {
374
- if (err) {
375
- reject(new Error(`Failed to probe audio: ${err.message}`));
376
- return;
377
- }
378
- const duration = metadata.format.duration;
379
- if (typeof duration !== "number") {
380
- reject(new Error("Could not determine audio duration"));
381
- return;
382
- }
383
- resolve(duration);
384
- });
385
- });
413
+ const metadata = await execFFprobe(audioPath);
414
+ const duration = metadata.format.duration;
415
+ if (typeof duration !== "number") {
416
+ throw new Error("Could not determine audio duration");
417
+ }
418
+ return duration;
386
419
  }
387
420
  async function detectSilenceRegions(audioPath, config = {}) {
388
421
  const { minSilenceDurSec, silenceThreshold } = { ...DEFAULT_SPLIT_CONFIG, ...config };
@@ -500,8 +533,13 @@ async function splitAudioAtPoints(audioPath, splitPoints, totalDuration, outputD
500
533
  outputPath
501
534
  };
502
535
  segments.push(segment);
503
- const extractPromise = new Promise((resolve, reject) => {
504
- ffmpeg(audioPath).setStartTime(startSec).setDuration(durationSec).audioFrequency(16e3).outputOptions(["-ac 1", "-c:a pcm_s16le"]).output(outputPath).on("error", (err) => reject(new Error(`Failed to extract segment ${i}: ${err.message}`))).on("end", () => resolve()).run();
536
+ const extractPromise = extractAudioSegment(
537
+ audioPath,
538
+ outputPath,
539
+ startSec,
540
+ durationSec
541
+ ).catch((err) => {
542
+ throw new Error(`Failed to extract segment ${i}: ${err instanceof Error ? err.message : String(err)}`);
505
543
  });
506
544
  splitPromises.push(extractPromise);
507
545
  }
@@ -1 +1 @@
1
- {"version":3,"file":"split.d.ts","sourceRoot":"","sources":["../../../src/utils/audio/split.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,cAAc,EAAE,MAAM,CAAA;IACtB,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,CAAA;IACxB,kDAAkD;IAClD,gBAAgB,EAAE,MAAM,CAAA;IACxB,wDAAwD;IACxD,mBAAmB,EAAE,OAAO,CAAA;IAC5B,uDAAuD;IACvD,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAA;IACf,kDAAkD;IAClD,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAMlC,CAAA;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAezE;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,OAAO,CAAC,aAAa,EAAE,CAAC,CAsD1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,cAAc,EAAE,aAAa,EAAE,EAC/B,aAAa,EAAE,MAAM,EACrB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,UAAU,EAAE,CAwEd;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,UAAU,EAAE,EACzB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,EAAE,CAAC,CA8CzB;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,OAAO,CAAC,YAAY,EAAE,CAAC,CAuCzB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,cAAc,EAAE,aAAa,EAAE,CAAA;IAC/B,UAAU,EAAE,OAAO,CAAA;CACpB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,OAAO,CAAC,aAAa,CAAC,CA0BxB"}
1
+ {"version":3,"file":"split.d.ts","sourceRoot":"","sources":["../../../src/utils/audio/split.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,cAAc,EAAE,MAAM,CAAA;IACtB,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,CAAA;IACxB,kDAAkD;IAClD,gBAAgB,EAAE,MAAM,CAAA;IACxB,wDAAwD;IACxD,mBAAmB,EAAE,OAAO,CAAA;IAC5B,uDAAuD;IACvD,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAA;IACf,kDAAkD;IAClD,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAMlC,CAAA;AA4CD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOzE;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,OAAO,CAAC,aAAa,EAAE,CAAC,CAsD1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,cAAc,EAAE,aAAa,EAAE,EAC/B,aAAa,EAAE,MAAM,EACrB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,UAAU,EAAE,CAwEd;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,UAAU,EAAE,EACzB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,EAAE,CAAC,CA2CzB;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,OAAO,CAAC,YAAY,EAAE,CAAC,CAuCzB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,cAAc,EAAE,aAAa,EAAE,CAAA;IAC/B,UAAU,EAAE,OAAO,CAAA;CACpB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,OAAO,CAAC,aAAa,CAAC,CA0BxB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wovin/tranz",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "type": "module",
5
5
  "description": "Audio transcription library with provider support and auto-splitting",
6
6
  "author": "gotjoshua @gotjoshua",
@@ -41,10 +41,9 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@mistralai/mistralai": "^1.14.0",
44
- "fluent-ffmpeg": "^2.1.2"
44
+ "execa": "^9.6.1"
45
45
  },
46
46
  "devDependencies": {
47
- "@types/fluent-ffmpeg": "^2.1.21",
48
47
  "@types/node": "^24.10.1",
49
48
  "@types/ws": "^8.5.13",
50
49
  "@types/yargs": "^17.0.33",