hyperframes 0.8.148 → 0.8.149
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/{add-JAHZJYB7.js → add-MG53577L.js} +12 -12
- package/dist/api.d.ts +209 -0
- package/dist/api.js +75 -0
- package/dist/{asset-SJA7DT6Q.js → asset-3GIBXLLL.js} +3 -3
- package/dist/{auth-RR3OIXLH.js → auth-XQMT727H.js} +4 -4
- package/dist/{autoUpdate-KLDV2XWV.js → autoUpdate-CREZJGMU.js} +2 -2
- package/dist/{backgroundChecks-OVL3E2RK.js → backgroundChecks-K3S5QKR3.js} +3 -3
- package/dist/backgroundChecksWorker.js +3 -3
- package/dist/{batchRender-2SAJGOHU.js → batchRender-42AKNX73.js} +4 -4
- package/dist/{beats-HTYS42CC.js → beats-Y7IKETUS.js} +15 -15
- package/dist/{benchmark-CAHP4GLB.js → benchmark-22SAXSO5.js} +15 -15
- package/dist/{browser-M7I67IGX.js → browser-ABNISCC3.js} +14 -13
- package/dist/{capture-P5SNZ6HL.js → capture-DBNHO4WJ.js} +2 -2
- package/dist/{capture-YZQZ5LKM.js → capture-HQG5W42I.js} +11 -11
- package/dist/{catalog-LREZPRJS.js → catalog-KICZFIDX.js} +28 -28
- package/dist/{catch-up-2MLRYAYP.js → catch-up-ZCQUCI45.js} +13 -13
- package/dist/{check-BH6NUR22.js → check-TGXIICEF.js} +34 -34
- package/dist/{checkBrowser-BM6JBFST.js → checkBrowser-3N23I56J.js} +22 -22
- package/dist/{chunk-A6S35NYA.js → chunk-7IEGPJ4P.js} +1 -1
- package/dist/{chunk-A4Q7W4LV.js → chunk-B3XLIBFL.js} +4 -2
- package/dist/{chunk-VHJPGKUW.js → chunk-BNYRD7PQ.js} +1 -1
- package/dist/{chunk-JN4EK6MC.js → chunk-CNPJHUOX.js} +12 -12
- package/dist/{chunk-54TV77W5.js → chunk-CT6ZQRLD.js} +6 -8
- package/dist/chunk-CYFFYK2F.js +56 -0
- package/dist/{chunk-KVGDFUVO.js → chunk-CZQLCBWY.js} +26 -13
- package/dist/{chunk-6IIGT7BX.js → chunk-DNZMBQTH.js} +1 -1
- package/dist/{chunk-SYUGVPYH.js → chunk-DUUFDLC4.js} +1 -1
- package/dist/{chunk-ASEJ2FBO.js → chunk-GESJSXFH.js} +1 -1
- package/dist/chunk-HU2SPFNG.js +103 -0
- package/dist/{chunk-4OA4LDTU.js → chunk-IYLHJV34.js} +1 -1
- package/dist/{chunk-KBB4RG6F.js → chunk-JZIEZCQM.js} +9 -2
- package/dist/{chunk-BB3HJLHD.js → chunk-K44HCHZN.js} +1 -1
- package/dist/chunk-KGPLIH7B.js +127 -0
- package/dist/{chunk-B4P5VDFQ.js → chunk-KMAAOHLO.js} +1 -1
- package/dist/{chunk-RKBES4XP.js → chunk-KUTT3JXL.js} +88 -28
- package/dist/{chunk-OLENCLFE.js → chunk-L274XRWA.js} +79 -6
- package/dist/{chunk-QX26JK43.js → chunk-LACFOFWX.js} +10 -10
- package/dist/chunk-LCILS4AF.js +329 -0
- package/dist/{chunk-ELACLQPC.js → chunk-LTJDUBSQ.js} +1 -1
- package/dist/{chunk-66SAATRI.js → chunk-M5B42RL5.js} +9 -9
- package/dist/{chunk-YQK445YQ.js → chunk-MI6U3OIN.js} +2 -2
- package/dist/{chunk-S7E2I3HT.js → chunk-MXB6CWVH.js} +1 -1
- package/dist/{chunk-KQESKXAC.js → chunk-OMBSUO4T.js} +2 -2
- package/dist/{chunk-UTBQSOEC.js → chunk-P7NTODQE.js} +2 -2
- package/dist/{chunk-BHVFTYSI.js → chunk-PO2SDVQA.js} +4 -1
- package/dist/{chunk-NT7EK6ET.js → chunk-RMIFSBRV.js} +1 -1
- package/dist/{chunk-URYAKNQ2.js → chunk-SFUBSJFP.js} +1 -1
- package/dist/{chunk-74JDPWQ3.js → chunk-TPIG7ZBX.js} +4 -4
- package/dist/{chunk-24GKVAEE.js → chunk-U7SASZC5.js} +10 -10
- package/dist/{chunk-TLGJRK6Q.js → chunk-VGCEMOQA.js} +5 -5
- package/dist/{normalize-U3SL5VG3.js → chunk-VHZ6DL3M.js} +3 -3
- package/dist/chunk-VX4AL2FQ.js +26 -0
- package/dist/{chunk-6VKQ5JT3.js → chunk-WX7VCRM7.js} +2 -2
- package/dist/{chunk-BYSBRF24.js → chunk-XPQSL5VS.js} +5 -120
- package/dist/{chunk-X2G54Y2V.js → chunk-Y475GD4L.js} +4 -4
- package/dist/{chunk-XIL7KT5Q.js → chunk-YDRX42P3.js} +6 -6
- package/dist/{chunk-4SFGME7K.js → chunk-YJDB4FLT.js} +1 -1
- package/dist/{chunk-QATWIE4K.js → chunk-YU2QRNWN.js} +2 -2
- package/dist/{chunk-CNEYCO24.js → chunk-ZKDKFJCK.js} +13 -13
- package/dist/{clean-K7GYTLQE.js → clean-6QP7VAV4.js} +25 -24
- package/dist/cli.js +55 -55
- package/dist/{cloud-I3J5HTN7.js → cloud-5TME5ROM.js} +4 -4
- package/dist/{cloudrun-MJQ363PB.js → cloudrun-F5VVCVF5.js} +4 -4
- package/dist/{compare-LHW6NEFR.js → compare-XPY2EXX6.js} +21 -21
- package/dist/{component-LTPK2D3K.js → component-OPVL3PUX.js} +4 -4
- package/dist/{compositions-QGEHXGIL.js → compositions-WSEOI454.js} +15 -15
- package/dist/{delete-ATNRBUDJ.js → delete-SLMH57VH.js} +11 -11
- package/dist/{doctor-6B76R5BJ.js → doctor-QZW3EKIH.js} +16 -15
- package/dist/{events-33GOPHSS.js → events-6C3ZG7LS.js} +8 -8
- package/dist/{events-BLABPRD5.js → events-FIFWFRGC.js} +6 -6
- package/dist/{feedback-HLXEG7RT.js → feedback-VKXM7YJ5.js} +22 -22
- package/dist/{ffmpeg-5V4FP3R6.js → ffmpeg-TZB5WAYE.js} +3 -2
- package/dist/{figma-T6W7H23L.js → figma-3UYNADNA.js} +3 -3
- package/dist/fontLocalizeCli.js +4 -4
- package/dist/{get-UDMLOTKJ.js → get-VH7VMRVX.js} +11 -11
- package/dist/{grade-compare-P4CHFVBR.js → grade-compare-OSC2YQWN.js} +26 -25
- package/dist/{help-4MW6L6YB.js → help-DCBFEZPT.js} +3 -3
- package/dist/{history-336VM6SH.js → history-XYJMQE26.js} +15 -15
- package/dist/hyperframes-player.global.js +1 -1
- package/dist/{info-FPMIDMD5.js → info-YEHGENAH.js} +15 -15
- package/dist/{init-IWM4PWLO.js → init-64SML7PY.js} +44 -43
- package/dist/{inspect-IIG7756C.js → inspect-GFOQKRJI.js} +19 -19
- package/dist/{keyframes-TWO4BXBA.js → keyframes-ORYFWKBZ.js} +16 -16
- package/dist/{lambda-2JB2QUK2.js → lambda-DRMOJGTC.js} +6 -6
- package/dist/{layout-TPKEKFQQ.js → layout-ZEQBE6UQ.js} +19 -19
- package/dist/{lint-H3KL7KSX.js → lint-67KGFY63.js} +19 -19
- package/dist/{list-LYPO4KRE.js → list-T6OU5ARJ.js} +11 -11
- package/dist/{login-SQQWKWTD.js → login-2PXIGDP7.js} +9 -9
- package/dist/{logout-B4KS4A7S.js → logout-DKJANASY.js} +3 -3
- package/dist/{manager-5ORDVWJB.js → manager-ES2UFT4X.js} +6 -4
- package/dist/{manager-BPSR6D3V.js → manager-GWU5J6RJ.js} +3 -2
- package/dist/{media-treatment-KSRINVUA.js → media-treatment-NAAHID6M.js} +24 -23
- package/dist/{models-WUBF6GDB.js → models-P6XB6RWK.js} +15 -13
- package/dist/{motionShot-STKG4KYQ.js → motionShot-7MHRIV6V.js} +4 -4
- package/dist/{manager-RFZNG5YT.js → normalize-4UDISLPL.js} +14 -20
- package/dist/{normalize-audio-CA47XZ4I.js → normalize-audio-LWNFYR2F.js} +15 -15
- package/dist/{open-B5WYEM3Z.js → open-DAP5C7UD.js} +13 -13
- package/dist/{parakeetRunner-JBK2JPEH.js → parakeetRunner-3ZVFPOD4.js} +13 -23
- package/dist/{pipeline-FEAAD2RJ.js → pipeline-V4YJCPUX.js} +5 -5
- package/dist/{play-2LC5XRM6.js → play-UDCESJO3.js} +26 -26
- package/dist/{preflight-ONF5AJNO.js → preflight-JOD4OXGC.js} +5 -4
- package/dist/{present-XKYF3VGC.js → present-DXTHBH3F.js} +23 -23
- package/dist/{preview-WDPZRHE5.js → preview-YHXKRXKB.js} +29 -27
- package/dist/{publish-3OYXNY44.js → publish-UEFBFGV3.js} +15 -15
- package/dist/{refresh-PVHBEABE.js → refresh-MGCVWX56.js} +3 -3
- package/dist/{remove-background-F6QTJIPZ.js → remove-background-FMV6IDOH.js} +34 -30
- package/dist/{render-JKB6GZDB.js → render-N7QGX6RJ.js} +28 -28
- package/dist/{render-SC77I7FT.js → render-SYC4RPGT.js} +4 -4
- package/dist/{render-QQ7NUREG.js → render-ZTXNPRGF.js} +51 -50
- package/dist/{render-batch-4F44JFAB.js → render-batch-SZRPCRUJ.js} +4 -4
- package/dist/renderSetupWorker.js +4 -3
- package/dist/{sherpa-FOXB4XBN.js → sherpa-M4Z2Q5Y2.js} +11 -10
- package/dist/sherpaWorker.js +3 -1
- package/dist/{skills-GG756RCG.js → skills-NEHNSHZK.js} +15 -15
- package/dist/{skillsUpdateCheck-N2LDCNAS.js → skillsUpdateCheck-O77QR72A.js} +3 -3
- package/dist/{snapshot-2LDOY65W.js → snapshot-GDVXFBVY.js} +40 -39
- package/dist/{staticProjectServer-QBB6WUAY.js → staticProjectServer-3D2NXQ6W.js} +5 -5
- package/dist/{status-PTKNQD2E.js → status-NBRMGL7D.js} +5 -5
- package/dist/studio/assets/{hyperframes-player-BBBg-uvu.js → hyperframes-player-C-2YwYre.js} +1 -1
- package/dist/studio/assets/{index-BJIpZeuk.js → index-ByJU5J6n.js} +4 -4
- package/dist/studio/assets/{index-BXJLeCqB.js → index-BybGk67U.js} +1 -1
- package/dist/studio/assets/{index-DARhiE_i.js → index-Cfs2r3fz.js} +1 -1
- package/dist/studio/index.html +1 -1
- package/dist/{studio-api-VPTZF2AW.js → studio-api-XIBDLRHB.js} +2 -2
- package/dist/{studioServer-VZKX2MG7.js → studioServer-QIQK47UN.js} +45 -44
- package/dist/{synthesize-UCI4X5O7.js → synthesize-22B7L5GX.js} +6 -6
- package/dist/{telemetry-76XND6XK.js → telemetry-565KDZUW.js} +8 -8
- package/dist/{timeline-UJLTA4AX.js → timeline-E6XB7I6W.js} +18 -18
- package/dist/{tokens-VMWANYJY.js → tokens-3ZAJENSE.js} +3 -3
- package/dist/transcribe-WODP3T77.js +332 -0
- package/dist/{transcribe-JNOG667L.js → transcribe-XWQQCCBG.js} +9 -8
- package/dist/{tts-B6AHFQEO.js → tts-QSAQZVEZ.js} +3 -3
- package/dist/{updateCheck-WI3HYM72.js → updateCheck-QPYU4GRL.js} +2 -2
- package/dist/{upgrade-52RIOKFX.js → upgrade-2FJ5ZEN6.js} +5 -5
- package/dist/{validate-MJVNR7YY.js → validate-SP2VGNEI.js} +16 -16
- package/package.json +8 -1
- package/dist/chunk-6IHWCZ3W.js +0 -54
- package/dist/chunk-SQLK7SJL.js +0 -88
- package/dist/renderCancellation-7OEBNE2L.js +0 -43
- package/dist/transcribe-FD7A2SH3.js +0 -466
- package/dist/{bundleWithLocalizedFonts-EKRXJBXU.js → bundleWithLocalizedFonts-OE5ZI4JE.js} +3 -3
- package/dist/{chunk-DKSDVDXG.js → chunk-NAMGMP3R.js} +3 -3
- package/dist/{chunk-C24LU5XD.js → chunk-NKM53WMI.js} +5 -5
- package/dist/{chunk-O3EALI4M.js → chunk-XHBX7QN6.js} +3 -3
- package/dist/{policies-4FEXMXPK.js → policies-DCSIM4AB.js} +3 -3
- package/dist/{screenshotCapture-3JXXUZND.js → screenshotCapture-TEUIWXWN.js} +3 -3
- package/dist/{telemetry-W5AKPI4R.js → telemetry-CQYHCCPL.js} +3 -3
- package/dist/{video-72VNEQEI.js → video-RVNPFEA6.js} +3 -3
|
@@ -6,10 +6,13 @@ var __filename = __hf_fileURLToPath(import.meta.url);
|
|
|
6
6
|
var __dirname = __hf_dirname(__filename);
|
|
7
7
|
import {
|
|
8
8
|
downloadFile
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PO2SDVQA.js";
|
|
10
10
|
import {
|
|
11
11
|
findFFmpeg
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-DUUFDLC4.js";
|
|
13
|
+
import {
|
|
14
|
+
stoppableExecFile
|
|
15
|
+
} from "./chunk-HU2SPFNG.js";
|
|
13
16
|
|
|
14
17
|
// src/whisper/manager.ts
|
|
15
18
|
import { execFileSync } from "child_process";
|
|
@@ -74,7 +77,7 @@ function findBuiltBinary() {
|
|
|
74
77
|
}
|
|
75
78
|
return void 0;
|
|
76
79
|
}
|
|
77
|
-
function buildFromSource(onProgress) {
|
|
80
|
+
async function buildFromSource(onProgress, signal) {
|
|
78
81
|
if (existsSync(BUILD_DIR) && !findBuiltBinary()) {
|
|
79
82
|
rmSync(BUILD_DIR, { recursive: true, force: true });
|
|
80
83
|
}
|
|
@@ -83,23 +86,26 @@ function buildFromSource(onProgress) {
|
|
|
83
86
|
mkdirSync(join(homedir(), ".cache", "hyperframes", "whisper"), {
|
|
84
87
|
recursive: true
|
|
85
88
|
});
|
|
86
|
-
|
|
89
|
+
await stoppableExecFile("git", ["clone", "--depth", "1", WHISPER_REPO, BUILD_DIR], {
|
|
87
90
|
stdio: "ignore",
|
|
88
91
|
timeout: 6e4,
|
|
89
|
-
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
92
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
|
|
93
|
+
signal
|
|
90
94
|
});
|
|
91
95
|
}
|
|
92
96
|
onProgress?.("Building whisper.cpp (this may take a minute)...");
|
|
93
97
|
try {
|
|
94
|
-
|
|
98
|
+
await stoppableExecFile("cmake", ["-B", "build"], {
|
|
95
99
|
cwd: BUILD_DIR,
|
|
96
100
|
stdio: ["pipe", "pipe", "pipe"],
|
|
97
|
-
timeout: 12e4
|
|
101
|
+
timeout: 12e4,
|
|
102
|
+
signal
|
|
98
103
|
});
|
|
99
|
-
|
|
104
|
+
await stoppableExecFile("cmake", ["--build", "build", "--config", "Release", "-j"], {
|
|
100
105
|
cwd: BUILD_DIR,
|
|
101
106
|
stdio: ["pipe", "pipe", "pipe"],
|
|
102
|
-
timeout: 3e5
|
|
107
|
+
timeout: 3e5,
|
|
108
|
+
signal
|
|
103
109
|
});
|
|
104
110
|
} catch (err) {
|
|
105
111
|
let detail = "";
|
|
@@ -150,6 +156,7 @@ function hasCmake() {
|
|
|
150
156
|
return whichBinary("cmake") !== void 0;
|
|
151
157
|
}
|
|
152
158
|
async function ensureWhisper(options) {
|
|
159
|
+
const signal = options?.signal;
|
|
153
160
|
const existing = findWhisper();
|
|
154
161
|
if (existing) return existing;
|
|
155
162
|
if (options?.installRuntime === false) {
|
|
@@ -160,20 +167,23 @@ async function ensureWhisper(options) {
|
|
|
160
167
|
if (platform() === "darwin" && hasBrew()) {
|
|
161
168
|
options?.onProgress?.("Installing whisper-cpp via Homebrew...");
|
|
162
169
|
try {
|
|
163
|
-
|
|
170
|
+
await stoppableExecFile("brew", ["install", "whisper-cpp"], {
|
|
164
171
|
stdio: "ignore",
|
|
165
|
-
timeout: 3e5
|
|
172
|
+
timeout: 3e5,
|
|
173
|
+
signal
|
|
166
174
|
});
|
|
167
175
|
const installed = findFromSystem();
|
|
168
176
|
if (installed) return { ...installed, source: "brew" };
|
|
169
177
|
} catch {
|
|
170
178
|
}
|
|
179
|
+
signal?.throwIfAborted();
|
|
171
180
|
}
|
|
172
181
|
if (hasGit() && hasCmake()) {
|
|
173
182
|
try {
|
|
174
|
-
return buildFromSource(options?.onProgress);
|
|
183
|
+
return await buildFromSource(options?.onProgress, signal);
|
|
175
184
|
} catch {
|
|
176
185
|
}
|
|
186
|
+
signal?.throwIfAborted();
|
|
177
187
|
}
|
|
178
188
|
throw new WhisperUnavailableError(`whisper-cpp not found. Install: ${getInstallInstructions()}`);
|
|
179
189
|
}
|
|
@@ -182,7 +192,10 @@ async function ensureModel(model = DEFAULT_MODEL, options) {
|
|
|
182
192
|
if (existsSync(modelPath)) return modelPath;
|
|
183
193
|
mkdirSync(MODELS_DIR, { recursive: true });
|
|
184
194
|
options?.onProgress?.(`Downloading model ${model}...`);
|
|
185
|
-
await downloadFile(getModelUrl(model), modelPath, {
|
|
195
|
+
await downloadFile(getModelUrl(model), modelPath, {
|
|
196
|
+
signal: options?.signal,
|
|
197
|
+
onProgress: options?.onDownloadProgress
|
|
198
|
+
});
|
|
186
199
|
if (!existsSync(modelPath)) {
|
|
187
200
|
throw new Error(`Model download failed: ${model}`);
|
|
188
201
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { createRequire as __hf_createRequire } from "node:module";
|
|
2
|
+
import { fileURLToPath as __hf_fileURLToPath } from "node:url";
|
|
3
|
+
import { dirname as __hf_dirname } from "node:path";
|
|
4
|
+
var require = __hf_createRequire(import.meta.url);
|
|
5
|
+
var __filename = __hf_fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = __hf_dirname(__filename);
|
|
7
|
+
import {
|
|
8
|
+
terminateProcessTree
|
|
9
|
+
} from "./chunk-KGPLIH7B.js";
|
|
10
|
+
|
|
11
|
+
// src/utils/stoppableExecFile.ts
|
|
12
|
+
import { execFileSync, spawn } from "child_process";
|
|
13
|
+
import * as util from "util";
|
|
14
|
+
function syscallError(code, file, args) {
|
|
15
|
+
const known = util.getSystemErrorMap?.() ?? /* @__PURE__ */ new Map();
|
|
16
|
+
const errno = [...known].find(([, [name]]) => name === code)?.[0];
|
|
17
|
+
return Object.assign(new Error(`spawnSync ${file} ${code}`), {
|
|
18
|
+
errno,
|
|
19
|
+
code,
|
|
20
|
+
syscall: `spawnSync ${file}`,
|
|
21
|
+
path: file,
|
|
22
|
+
spawnargs: args
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
async function stoppableExecFile(file, args, options) {
|
|
26
|
+
const { signal, ...syncOptions } = options;
|
|
27
|
+
if (!signal) {
|
|
28
|
+
execFileSync(file, args, syncOptions);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
signal.throwIfAborted();
|
|
32
|
+
const maxBuffer = options.maxBuffer ?? 1024 * 1024;
|
|
33
|
+
await new Promise((resolve, reject) => {
|
|
34
|
+
const child = spawn(file, args, { cwd: options.cwd, env: options.env, stdio: options.stdio });
|
|
35
|
+
let failure;
|
|
36
|
+
const stopWith = (code) => {
|
|
37
|
+
failure ??= code;
|
|
38
|
+
child.kill("SIGTERM");
|
|
39
|
+
};
|
|
40
|
+
const collect = (stream) => {
|
|
41
|
+
if (!stream) return null;
|
|
42
|
+
const chunks = [];
|
|
43
|
+
let size = 0;
|
|
44
|
+
stream.on("data", (chunk) => {
|
|
45
|
+
chunks.push(chunk);
|
|
46
|
+
size += chunk.length;
|
|
47
|
+
if (size > maxBuffer) stopWith("ENOBUFS");
|
|
48
|
+
});
|
|
49
|
+
return chunks;
|
|
50
|
+
};
|
|
51
|
+
const stdout = collect(child.stdout);
|
|
52
|
+
const stderr = collect(child.stderr);
|
|
53
|
+
child.stdin?.end();
|
|
54
|
+
const timer = setTimeout(() => stopWith("ETIMEDOUT"), options.timeout);
|
|
55
|
+
let stopping;
|
|
56
|
+
const onAbort = () => {
|
|
57
|
+
if (child.pid === void 0) return;
|
|
58
|
+
stopping ??= terminateProcessTree(child.pid, { child }).catch(() => void 0);
|
|
59
|
+
};
|
|
60
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
61
|
+
const settle = () => {
|
|
62
|
+
clearTimeout(timer);
|
|
63
|
+
signal.removeEventListener("abort", onAbort);
|
|
64
|
+
};
|
|
65
|
+
child.on("error", (err) => {
|
|
66
|
+
if (child.pid !== void 0) return;
|
|
67
|
+
settle();
|
|
68
|
+
const spawnError = syscallError(err.code ?? "UNKNOWN", file, args);
|
|
69
|
+
const result = { status: null, signal: null, output: null, pid: 0 };
|
|
70
|
+
reject(Object.assign(spawnError, { error: spawnError }, result));
|
|
71
|
+
});
|
|
72
|
+
child.on("close", (status, exitSignal) => {
|
|
73
|
+
settle();
|
|
74
|
+
if (signal.aborted) {
|
|
75
|
+
void Promise.resolve(stopping).then(() => reject(signal.reason));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const out = stdout && Buffer.concat(stdout);
|
|
79
|
+
const errText = stderr && Buffer.concat(stderr);
|
|
80
|
+
const result = {
|
|
81
|
+
status,
|
|
82
|
+
signal: exitSignal,
|
|
83
|
+
output: [null, out, errText],
|
|
84
|
+
pid: child.pid,
|
|
85
|
+
stdout: out,
|
|
86
|
+
stderr: errText
|
|
87
|
+
};
|
|
88
|
+
if (failure) {
|
|
89
|
+
const err = syscallError(failure, file, args);
|
|
90
|
+
return reject(Object.assign(err, { error: err }, result));
|
|
91
|
+
}
|
|
92
|
+
if (status === 0) return resolve();
|
|
93
|
+
const command = `Command failed: ${[file, ...args].join(" ")}`;
|
|
94
|
+
const message = errText?.length ? `${command}
|
|
95
|
+
${errText.toString()}` : command;
|
|
96
|
+
reject(Object.assign(new Error(message), result));
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
stoppableExecFile
|
|
103
|
+
};
|
|
@@ -7,6 +7,9 @@ var __dirname = __hf_dirname(__filename);
|
|
|
7
7
|
import {
|
|
8
8
|
TRANSCRIPT_FILE
|
|
9
9
|
} from "./chunk-IR35BCLK.js";
|
|
10
|
+
import {
|
|
11
|
+
stoppableExecFile
|
|
12
|
+
} from "./chunk-HU2SPFNG.js";
|
|
10
13
|
|
|
11
14
|
// src/whisper/parakeet.ts
|
|
12
15
|
import { execFileSync } from "child_process";
|
|
@@ -163,7 +166,7 @@ function silenceCuts(samples, sampleRate, windowSeconds = 60) {
|
|
|
163
166
|
if (samples.length > 0) cuts.push(samples.length);
|
|
164
167
|
return cuts;
|
|
165
168
|
}
|
|
166
|
-
function transcribeWithParakeet(inputPath, dir, options) {
|
|
169
|
+
async function transcribeWithParakeet(inputPath, dir, options) {
|
|
167
170
|
const runner = findParakeet();
|
|
168
171
|
if (!runner) {
|
|
169
172
|
throw new Error(
|
|
@@ -188,7 +191,11 @@ function transcribeWithParakeet(inputPath, dir, options) {
|
|
|
188
191
|
model: PARAKEET_MODEL_LABEL,
|
|
189
192
|
status: "started"
|
|
190
193
|
});
|
|
191
|
-
|
|
194
|
+
await stoppableExecFile(runner, argv, {
|
|
195
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
196
|
+
timeout: 18e5,
|
|
197
|
+
signal: options?.signal
|
|
198
|
+
});
|
|
192
199
|
const produced = join(workDir, `${basename(inputPath, extname(inputPath))}.json`);
|
|
193
200
|
if (!existsSync(produced)) throw new Error("Parakeet did not produce output.");
|
|
194
201
|
const result = writeParakeetTranscript(
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { createRequire as __hf_createRequire } from "node:module";
|
|
2
|
+
import { fileURLToPath as __hf_fileURLToPath } from "node:url";
|
|
3
|
+
import { dirname as __hf_dirname } from "node:path";
|
|
4
|
+
var require = __hf_createRequire(import.meta.url);
|
|
5
|
+
var __filename = __hf_fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = __hf_dirname(__filename);
|
|
7
|
+
|
|
8
|
+
// src/utils/processTree.ts
|
|
9
|
+
import { execFileSync, spawn } from "child_process";
|
|
10
|
+
import { readdirSync, readFileSync } from "fs";
|
|
11
|
+
function processIsAlive(pid) {
|
|
12
|
+
try {
|
|
13
|
+
process.kill(pid, 0);
|
|
14
|
+
return true;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
return error?.code !== "ESRCH";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function processGroupIsAlive(pid) {
|
|
20
|
+
if (process.platform === "linux") {
|
|
21
|
+
try {
|
|
22
|
+
return readdirSync("/proc").some((entry) => {
|
|
23
|
+
if (!/^\d+$/.test(entry)) return false;
|
|
24
|
+
try {
|
|
25
|
+
const stat = readFileSync(`/proc/${entry}/stat`, "utf8");
|
|
26
|
+
const fields = stat.slice(stat.lastIndexOf(") ") + 2).split(/\s+/);
|
|
27
|
+
return fields[2] === String(pid) && fields[0] !== "Z" && fields[0] !== "X";
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
} catch {
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return processIsAlive(-pid);
|
|
36
|
+
}
|
|
37
|
+
function waitForDelay(delayMs) {
|
|
38
|
+
return new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
39
|
+
}
|
|
40
|
+
async function waitForProcessGroupExit(pid) {
|
|
41
|
+
while (processGroupIsAlive(pid)) await waitForDelay(20);
|
|
42
|
+
}
|
|
43
|
+
function windowsProcessTreeKillArgs(pid) {
|
|
44
|
+
return ["/PID", String(pid), "/T", "/F"];
|
|
45
|
+
}
|
|
46
|
+
function terminateWindowsProcessTree(pid, spawnProcess = (command, args, options) => spawn(command, [...args], options)) {
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
const killer = spawnProcess("taskkill", windowsProcessTreeKillArgs(pid), {
|
|
49
|
+
stdio: "ignore",
|
|
50
|
+
windowsHide: true
|
|
51
|
+
});
|
|
52
|
+
killer.once("error", reject);
|
|
53
|
+
killer.once("close", (status) => {
|
|
54
|
+
if (status === 0) resolve();
|
|
55
|
+
else reject(new Error(`taskkill exited with status ${status ?? "unknown"}`));
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function signalProcessGroup(pid, signal) {
|
|
60
|
+
try {
|
|
61
|
+
process.kill(-pid, signal);
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function getDescendants(pid) {
|
|
66
|
+
let children;
|
|
67
|
+
try {
|
|
68
|
+
const raw = execFileSync("pgrep", ["-P", String(pid)], {
|
|
69
|
+
encoding: "utf8",
|
|
70
|
+
timeout: 2e3
|
|
71
|
+
}).trim();
|
|
72
|
+
children = raw.split(/\r?\n/).map(Number).filter((childPid) => Number.isInteger(childPid) && childPid > 0);
|
|
73
|
+
} catch {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
return children.flatMap((childPid) => [childPid, ...getDescendants(childPid)]);
|
|
77
|
+
}
|
|
78
|
+
function signalProcesses(pids, signal) {
|
|
79
|
+
for (const pid of pids) {
|
|
80
|
+
try {
|
|
81
|
+
process.kill(pid, signal);
|
|
82
|
+
} catch {
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function terminatePidTree(pid, signal) {
|
|
87
|
+
const pids = [...getDescendants(pid).reverse(), pid];
|
|
88
|
+
signalProcesses(pids, signal);
|
|
89
|
+
if (signal === "SIGKILL") return "SIGKILL";
|
|
90
|
+
await waitForDelay(500);
|
|
91
|
+
const survivors = pids.filter(processIsAlive);
|
|
92
|
+
signalProcesses(survivors, "SIGKILL");
|
|
93
|
+
return survivors.length > 0 ? "SIGKILL" : "SIGTERM";
|
|
94
|
+
}
|
|
95
|
+
async function terminateProcessGroup(pid, signal) {
|
|
96
|
+
signalProcessGroup(pid, signal);
|
|
97
|
+
if (signal === "SIGKILL") {
|
|
98
|
+
await waitForProcessGroupExit(pid);
|
|
99
|
+
return "SIGKILL";
|
|
100
|
+
}
|
|
101
|
+
await Promise.race([waitForProcessGroupExit(pid), waitForDelay(250)]);
|
|
102
|
+
if (!processGroupIsAlive(pid)) return "SIGTERM";
|
|
103
|
+
signalProcessGroup(pid, "SIGKILL");
|
|
104
|
+
await waitForProcessGroupExit(pid);
|
|
105
|
+
return "SIGKILL";
|
|
106
|
+
}
|
|
107
|
+
async function terminateProcessTree(pid, options = {}) {
|
|
108
|
+
if (process.platform === "win32") {
|
|
109
|
+
try {
|
|
110
|
+
await terminateWindowsProcessTree(pid, options.spawnProcess);
|
|
111
|
+
} catch (error) {
|
|
112
|
+
try {
|
|
113
|
+
options.child?.kill("SIGKILL");
|
|
114
|
+
} catch {
|
|
115
|
+
}
|
|
116
|
+
if (options.child) throw error;
|
|
117
|
+
}
|
|
118
|
+
return "SIGKILL";
|
|
119
|
+
}
|
|
120
|
+
const signal = options.signal ?? "SIGTERM";
|
|
121
|
+
return options.processGroup ? terminateProcessGroup(pid, signal) : terminatePidTree(pid, signal);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export {
|
|
125
|
+
processIsAlive,
|
|
126
|
+
terminateProcessTree
|
|
127
|
+
};
|
|
@@ -4,29 +4,29 @@ import { dirname as __hf_dirname } from "node:path";
|
|
|
4
4
|
var require = __hf_createRequire(import.meta.url);
|
|
5
5
|
var __filename = __hf_fileURLToPath(import.meta.url);
|
|
6
6
|
var __dirname = __hf_dirname(__filename);
|
|
7
|
-
import {
|
|
8
|
-
emitWords
|
|
9
|
-
} from "./chunk-6IHWCZ3W.js";
|
|
10
7
|
import {
|
|
11
8
|
stoppedByCancelSignal
|
|
12
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-P7NTODQE.js";
|
|
13
10
|
import {
|
|
14
11
|
DEFAULT_MODEL,
|
|
15
12
|
ensureModel,
|
|
16
13
|
ensureWhisper,
|
|
17
14
|
hasFFmpeg
|
|
18
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-CZQLCBWY.js";
|
|
19
16
|
import {
|
|
20
17
|
findFFmpeg,
|
|
21
18
|
findFFprobe,
|
|
22
19
|
getFFmpegInstallHint
|
|
23
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-DUUFDLC4.js";
|
|
24
21
|
import {
|
|
25
22
|
findWavChunk
|
|
26
23
|
} from "./chunk-UOFAE5RF.js";
|
|
27
24
|
import {
|
|
28
25
|
TRANSCRIPT_FILE
|
|
29
26
|
} from "./chunk-IR35BCLK.js";
|
|
27
|
+
import {
|
|
28
|
+
stoppableExecFile
|
|
29
|
+
} from "./chunk-HU2SPFNG.js";
|
|
30
30
|
|
|
31
31
|
// src/whisper/transcribe.ts
|
|
32
32
|
import { execFile, execFileSync } from "child_process";
|
|
@@ -36,6 +36,60 @@ import { existsSync, readFileSync, mkdirSync, rmSync, statSync, unlinkSync } fro
|
|
|
36
36
|
import { basename, join, extname } from "path";
|
|
37
37
|
import { tmpdir } from "os";
|
|
38
38
|
import { randomUUID } from "crypto";
|
|
39
|
+
|
|
40
|
+
// src/whisper/modelForLanguage.ts
|
|
41
|
+
function initialModelForLanguage(model, language) {
|
|
42
|
+
const baseLanguage = language?.trim().toLowerCase().split(/[-_]/, 1)[0];
|
|
43
|
+
if (baseLanguage && baseLanguage !== "en" && model.endsWith(".en")) {
|
|
44
|
+
return model.slice(0, -3);
|
|
45
|
+
}
|
|
46
|
+
return model;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/whisper/progress.ts
|
|
50
|
+
var DESKTOP_MAX_LINE_BYTES = 16e3;
|
|
51
|
+
function emitWords(onEvent, model, words, through) {
|
|
52
|
+
const empty = Buffer.byteLength(JSON.stringify({ type: "words", model, words: [], through })) + 1;
|
|
53
|
+
let chunk = [];
|
|
54
|
+
let bytes = empty;
|
|
55
|
+
for (const word of words) {
|
|
56
|
+
const size = Buffer.byteLength(JSON.stringify(word)) + 1;
|
|
57
|
+
if (chunk.length > 0 && bytes + size > DESKTOP_MAX_LINE_BYTES) {
|
|
58
|
+
onEvent({ type: "words", model, words: chunk, through: chunk.at(-1).end });
|
|
59
|
+
chunk = [];
|
|
60
|
+
bytes = empty;
|
|
61
|
+
}
|
|
62
|
+
chunk.push(word);
|
|
63
|
+
bytes += size;
|
|
64
|
+
}
|
|
65
|
+
onEvent({ type: "words", model, words: chunk, through });
|
|
66
|
+
}
|
|
67
|
+
function createProgressWriter(stream) {
|
|
68
|
+
let blocked = false;
|
|
69
|
+
const pending = [];
|
|
70
|
+
const write = (event) => {
|
|
71
|
+
if (blocked) {
|
|
72
|
+
const previous = pending.at(-1);
|
|
73
|
+
if (event.type === "progress" && event.phase === "download" && previous?.type === "progress" && previous.phase === "download" && previous.model === event.model) {
|
|
74
|
+
pending[pending.length - 1] = event;
|
|
75
|
+
} else {
|
|
76
|
+
pending.push(event);
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
blocked = !stream.write(`${JSON.stringify(event)}
|
|
81
|
+
`);
|
|
82
|
+
if (blocked) {
|
|
83
|
+
stream.once("drain", () => {
|
|
84
|
+
blocked = false;
|
|
85
|
+
while (!blocked && pending.length > 0) write(pending.shift());
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
return write;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/whisper/transcribe.ts
|
|
39
93
|
var WHISPER_TIMEOUT_FLOOR_MS = 3e5;
|
|
40
94
|
var WHISPER_TIMEOUT_PER_AUDIO_SECOND_MS = 1e4;
|
|
41
95
|
var WHISPER_TIMEOUT_CAP_MS = 432e5;
|
|
@@ -175,15 +229,17 @@ function isVideoFile(filePath) {
|
|
|
175
229
|
function tempWavPath() {
|
|
176
230
|
return join(tmpdir(), `hyperframes-audio-${process.pid}-${randomUUID()}.wav`);
|
|
177
231
|
}
|
|
178
|
-
function runFfmpeg(ffmpegPath, args, output, timeout) {
|
|
232
|
+
async function runFfmpeg(ffmpegPath, args, output, timeout, signal) {
|
|
179
233
|
try {
|
|
180
|
-
|
|
234
|
+
await stoppableExecFile(ffmpegPath, ["-nostats", "-hide_banner", ...args, "-y", output], {
|
|
181
235
|
stdio: ["ignore", "ignore", "pipe"],
|
|
182
236
|
maxBuffer: 64 * 1024 * 1024,
|
|
183
|
-
timeout
|
|
237
|
+
timeout,
|
|
238
|
+
signal
|
|
184
239
|
});
|
|
185
240
|
} catch (err) {
|
|
186
241
|
rmSync(output, { force: true });
|
|
242
|
+
if (signal?.aborted) throw err;
|
|
187
243
|
const stop = err;
|
|
188
244
|
if (stop.code) throw err;
|
|
189
245
|
const said = String(stop.stderr ?? "").trim();
|
|
@@ -193,7 +249,7 @@ function runFfmpeg(ffmpegPath, args, output, timeout) {
|
|
|
193
249
|
throw Object.assign(failure, { cancelled, stderr: said });
|
|
194
250
|
}
|
|
195
251
|
}
|
|
196
|
-
function extractAudio(videoPath) {
|
|
252
|
+
async function extractAudio(videoPath, signal) {
|
|
197
253
|
const ffmpegPath = findFFmpeg();
|
|
198
254
|
if (!ffmpegPath) {
|
|
199
255
|
throw new Error(
|
|
@@ -201,11 +257,12 @@ function extractAudio(videoPath) {
|
|
|
201
257
|
);
|
|
202
258
|
}
|
|
203
259
|
const wavPath = tempWavPath();
|
|
204
|
-
runFfmpeg(
|
|
260
|
+
await runFfmpeg(
|
|
205
261
|
ffmpegPath,
|
|
206
262
|
["-i", videoPath, "-vn", "-ar", "16000", "-ac", "1", "-f", "wav"],
|
|
207
263
|
wavPath,
|
|
208
|
-
resolveAudioPreparationTimeoutMs(getMediaDurationSeconds(videoPath))
|
|
264
|
+
resolveAudioPreparationTimeoutMs(getMediaDurationSeconds(videoPath)),
|
|
265
|
+
signal
|
|
209
266
|
);
|
|
210
267
|
return wavPath;
|
|
211
268
|
}
|
|
@@ -227,7 +284,7 @@ function isWav16kMono(filePath) {
|
|
|
227
284
|
return false;
|
|
228
285
|
}
|
|
229
286
|
}
|
|
230
|
-
function prepareAudio(audioPath) {
|
|
287
|
+
async function prepareAudio(audioPath, signal) {
|
|
231
288
|
if (extname(audioPath).toLowerCase() === ".wav" && isWav16kMono(audioPath)) {
|
|
232
289
|
return audioPath;
|
|
233
290
|
}
|
|
@@ -236,28 +293,22 @@ function prepareAudio(audioPath) {
|
|
|
236
293
|
throw new Error(`ffmpeg is required to prepare audio. Install: ${getFFmpegInstallHint()}`);
|
|
237
294
|
}
|
|
238
295
|
const wavPath = tempWavPath();
|
|
239
|
-
runFfmpeg(
|
|
296
|
+
await runFfmpeg(
|
|
240
297
|
ffmpegPath,
|
|
241
298
|
["-i", audioPath, "-ar", "16000", "-ac", "1", "-f", "wav"],
|
|
242
299
|
wavPath,
|
|
243
|
-
resolveAudioPreparationTimeoutMs(getMediaDurationSeconds(audioPath))
|
|
300
|
+
resolveAudioPreparationTimeoutMs(getMediaDurationSeconds(audioPath)),
|
|
301
|
+
signal
|
|
244
302
|
);
|
|
245
303
|
return wavPath;
|
|
246
304
|
}
|
|
247
305
|
function dtwPresetForModel(model) {
|
|
248
306
|
return model.replace(/-/g, ".");
|
|
249
307
|
}
|
|
250
|
-
function
|
|
251
|
-
const baseLanguage = language?.trim().toLowerCase().split(/[-_]/, 1)[0];
|
|
252
|
-
if (baseLanguage && baseLanguage !== "en" && model.endsWith(".en")) {
|
|
253
|
-
return model.slice(0, -3);
|
|
254
|
-
}
|
|
255
|
-
return model;
|
|
256
|
-
}
|
|
257
|
-
function prepareWav(inputPath, onProgress) {
|
|
308
|
+
async function prepareWav(inputPath, onProgress, signal) {
|
|
258
309
|
if (isAudioFile(inputPath)) {
|
|
259
310
|
onProgress?.("Preparing audio...");
|
|
260
|
-
return prepareAudio(inputPath);
|
|
311
|
+
return prepareAudio(inputPath, signal);
|
|
261
312
|
}
|
|
262
313
|
if (isVideoFile(inputPath)) {
|
|
263
314
|
if (!hasFFmpeg()) {
|
|
@@ -266,19 +317,24 @@ function prepareWav(inputPath, onProgress) {
|
|
|
266
317
|
);
|
|
267
318
|
}
|
|
268
319
|
onProgress?.("Extracting audio from video...");
|
|
269
|
-
return extractAudio(inputPath);
|
|
320
|
+
return extractAudio(inputPath, signal);
|
|
270
321
|
}
|
|
271
322
|
throw new Error(`Unsupported file type: ${extname(inputPath).toLowerCase()}`);
|
|
272
323
|
}
|
|
273
324
|
async function transcribe(inputPath, outputDir, options) {
|
|
274
325
|
const model = initialModelForLanguage(options?.model ?? DEFAULT_MODEL, options?.language);
|
|
326
|
+
const signal = options?.signal;
|
|
327
|
+
signal?.throwIfAborted();
|
|
275
328
|
options?.onProgress?.("Checking whisper...");
|
|
276
329
|
const whisper = await ensureWhisper({
|
|
277
330
|
onProgress: options?.onProgress,
|
|
278
|
-
installRuntime: options?.installRuntime
|
|
331
|
+
installRuntime: options?.installRuntime,
|
|
332
|
+
signal
|
|
279
333
|
});
|
|
334
|
+
signal?.throwIfAborted();
|
|
280
335
|
options?.onProgress?.("Checking model...");
|
|
281
336
|
const modelPath = await ensureModel(model, {
|
|
337
|
+
signal,
|
|
282
338
|
onProgress: options?.onProgress,
|
|
283
339
|
onDownloadProgress: options?.onEvent ? (receivedBytes, totalBytes) => options.onEvent?.({
|
|
284
340
|
type: "progress",
|
|
@@ -288,7 +344,9 @@ async function transcribe(inputPath, outputDir, options) {
|
|
|
288
344
|
totalBytes
|
|
289
345
|
}) : void 0
|
|
290
346
|
});
|
|
291
|
-
|
|
347
|
+
signal?.throwIfAborted();
|
|
348
|
+
const wavPath = await prepareWav(inputPath, options?.onProgress, signal);
|
|
349
|
+
signal?.throwIfAborted();
|
|
292
350
|
const automaticLanguage = options?.language === void 0 && !model.endsWith(".en");
|
|
293
351
|
const language = options?.language ?? (automaticLanguage ? "auto" : "en");
|
|
294
352
|
options?.onProgress?.("Transcribing...");
|
|
@@ -436,6 +494,9 @@ function wrapWhisperTimeoutError(err, options) {
|
|
|
436
494
|
}
|
|
437
495
|
|
|
438
496
|
export {
|
|
497
|
+
initialModelForLanguage,
|
|
498
|
+
emitWords,
|
|
499
|
+
createProgressWriter,
|
|
439
500
|
whisperModelSlowdownFactor,
|
|
440
501
|
resolveWhisperTimeoutMs,
|
|
441
502
|
resolveAudioPreparationTimeoutMs,
|
|
@@ -444,7 +505,6 @@ export {
|
|
|
444
505
|
detectSpeechOnset,
|
|
445
506
|
isPcm16kMono,
|
|
446
507
|
dtwPresetForModel,
|
|
447
|
-
initialModelForLanguage,
|
|
448
508
|
prepareWav,
|
|
449
509
|
transcribe,
|
|
450
510
|
isWhisperTimeoutError,
|