pinokiod 7.2.5 → 7.2.7

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.
@@ -73,13 +73,19 @@ class Ffmpeg {
73
73
  if (this.kernel.platform !== "darwin") {
74
74
  return
75
75
  }
76
- if (!(await this.hasInstalledBinaryPaths())) {
77
- await this.removeBaseActivationHooks()
78
- return
76
+ try {
77
+ if (!(await this.hasInstalledBinaryPaths())) {
78
+ await this.removeRuntimeExposure()
79
+ return
80
+ }
81
+ await this.selfTest()
82
+ await this.ensureBaseActivationHooks()
83
+ await this.syncMacUvLibraryShims()
84
+ await this.startMacUvLibraryWatcher()
85
+ } catch (error) {
86
+ await this.removeRuntimeExposure()
87
+ console.log("conda ffmpeg start check failed", error && error.message ? error.message : error)
79
88
  }
80
- await this.ensureBaseActivationHooks()
81
- await this.syncMacUvLibraryShims()
82
- await this.startMacUvLibraryWatcher()
83
89
  }
84
90
 
85
91
  async install(req, ondata) {
@@ -231,28 +237,33 @@ class Ffmpeg {
231
237
  }
232
238
  }
233
239
 
240
+ async removeRuntimeExposure(ondata) {
241
+ await this.stopMacUvLibraryWatcher()
242
+ await this.removeMacUvLibraryShims(ondata)
243
+ await this.removeBaseActivationHooks()
244
+ }
245
+
234
246
  async installed() {
235
247
  try {
236
248
  if (!(await this.hasInstalledBinaryPaths())) {
237
- await this.removeBaseActivationHooks()
249
+ await this.removeRuntimeExposure()
238
250
  return false
239
251
  }
240
252
 
253
+ await this.selfTest()
241
254
  await this.ensureBaseActivationHooks()
242
255
  await this.syncMacUvLibraryShims()
243
256
  await this.startMacUvLibraryWatcher()
244
- await this.selfTest()
245
257
  return true
246
258
  } catch (error) {
259
+ await this.removeRuntimeExposure()
247
260
  console.log("conda ffmpeg installed check failed", error && error.message ? error.message : error)
248
261
  return false
249
262
  }
250
263
  }
251
264
 
252
265
  async uninstall(req, ondata) {
253
- await this.stopMacUvLibraryWatcher()
254
- await this.removeMacUvLibraryShims(ondata)
255
- await this.removeBaseActivationHooks()
266
+ await this.removeRuntimeExposure(ondata)
256
267
  const prefix = this.ffmpegPrefix()
257
268
  const exists = await fs.promises.access(prefix).then(() => true).catch(() => false)
258
269
  if (exists) {
package/kernel/shell.js CHANGED
@@ -67,6 +67,18 @@ function stripInheritedCondaActivationState(env) {
67
67
  }
68
68
  }
69
69
 
70
+ function setDefaultEnvValue(env, key, value) {
71
+ const existingKey = Object.keys(env).find((envKey) => envKey.toLowerCase() === key.toLowerCase())
72
+ if (!existingKey) {
73
+ env[key] = value
74
+ return
75
+ }
76
+ const existingValue = env[existingKey]
77
+ if (typeof existingValue !== "string" || !existingValue.trim()) {
78
+ env[existingKey] = value
79
+ }
80
+ }
81
+
70
82
  // xterm.js currently ignores DECSYNCTERM (CSI ? 2026 h/l) and renders it as text on Windows.
71
83
  // filterDecsync() removes these sequences so they do not pollute the terminal output.
72
84
  class Shell {
@@ -281,6 +293,13 @@ class Shell {
281
293
  }
282
294
  }
283
295
 
296
+ if (this.platform === "win32") {
297
+ // Hugging Face file symlinks regularly fail on non-admin Windows setups.
298
+ // Default to no-symlink cache mode unless the user/app explicitly overrides it.
299
+ setDefaultEnvValue(this.env, "HF_HUB_DISABLE_SYMLINKS", "1")
300
+ setDefaultEnvValue(this.env, "HF_HUB_DISABLE_SYMLINKS_WARNING", "1")
301
+ }
302
+
284
303
  stripInheritedCondaActivationState(this.env)
285
304
  this.env[PATH_KEY] = stripBluefairyShimPaths(this.env[PATH_KEY], this.platform)
286
305
 
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "7.2.5",
3
+ "version": "7.2.7",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "download_readme": "wget -O kernel/proto/PINOKIO.md https://raw.githubusercontent.com/pinokiocomputer/home/refs/heads/main/docs/README.md",
8
- "start": "node script/index"
8
+ "start": "node script/index",
9
+ "verify:ffmpeg": "node script/verify-ffmpeg.js"
9
10
  },
10
11
  "author": "",
11
12
  "license": "MIT",
@@ -0,0 +1,459 @@
1
+ #!/usr/bin/env node
2
+
3
+ const crypto = require("crypto")
4
+ const fs = require("fs")
5
+ const os = require("os")
6
+ const path = require("path")
7
+ const { spawn } = require("child_process")
8
+ const Kernel = require("../kernel")
9
+
10
+ function parseArgs(argv) {
11
+ const options = {
12
+ home: process.env.PINOKIO_HOME || path.resolve(process.cwd(), ".pinokio"),
13
+ reinstall: false,
14
+ skipInstall: false,
15
+ }
16
+
17
+ for (let i = 0; i < argv.length; i += 1) {
18
+ const arg = argv[i]
19
+ if (arg === "--home" && argv[i + 1]) {
20
+ options.home = path.resolve(argv[i + 1])
21
+ i += 1
22
+ } else if (arg === "--reinstall") {
23
+ options.reinstall = true
24
+ } else if (arg === "--skip-install") {
25
+ options.skipInstall = true
26
+ } else if (arg === "--help" || arg === "-h") {
27
+ options.help = true
28
+ } else {
29
+ throw new Error(`Unknown argument: ${arg}`)
30
+ }
31
+ }
32
+
33
+ return options
34
+ }
35
+
36
+ function usage() {
37
+ return [
38
+ "Usage: node script/verify-ffmpeg.js [--home <PINOKIO_HOME>] [--reinstall] [--skip-install]",
39
+ "",
40
+ "--reinstall remove and reinstall FFmpeg before verification",
41
+ "--skip-install only verify the current install state",
42
+ ].join("\n")
43
+ }
44
+
45
+ function logOnData(event) {
46
+ if (!event) {
47
+ return
48
+ }
49
+ if (typeof event.raw === "string") {
50
+ process.stdout.write(event.raw)
51
+ return
52
+ }
53
+ if (typeof event.html === "string") {
54
+ process.stdout.write(`${event.html.replace(/<[^>]+>/g, "")}\n`)
55
+ }
56
+ }
57
+
58
+ function mergeEnv(baseEnv, overlay) {
59
+ const env = { ...baseEnv }
60
+ for (const [key, value] of Object.entries(overlay || {})) {
61
+ if (Array.isArray(value)) {
62
+ const prefix = value.filter(Boolean).join(path.delimiter)
63
+ if (prefix.length === 0) {
64
+ continue
65
+ }
66
+ env[key] = env[key] ? `${prefix}${path.delimiter}${env[key]}` : prefix
67
+ } else if (value === undefined || value === null) {
68
+ delete env[key]
69
+ } else {
70
+ env[key] = String(value)
71
+ }
72
+ }
73
+ return env
74
+ }
75
+
76
+ function normalizePathForCompare(value) {
77
+ return String(value || "")
78
+ .replace(/\\/g, "/")
79
+ .replace(/\/+$/, "")
80
+ .toLowerCase()
81
+ }
82
+
83
+ function assert(condition, message) {
84
+ if (!condition) {
85
+ throw new Error(message)
86
+ }
87
+ }
88
+
89
+ async function exists(target) {
90
+ try {
91
+ await fs.promises.access(target)
92
+ return true
93
+ } catch (error) {
94
+ return false
95
+ }
96
+ }
97
+
98
+ async function runCommand(command, args, options = {}) {
99
+ return await new Promise((resolve, reject) => {
100
+ const child = spawn(command, args, {
101
+ cwd: options.cwd,
102
+ env: options.env,
103
+ windowsHide: true,
104
+ shell: false,
105
+ })
106
+
107
+ let stdout = ""
108
+ let stderr = ""
109
+ child.stdout.on("data", (chunk) => {
110
+ const text = chunk.toString()
111
+ stdout += text
112
+ if (options.stream) {
113
+ process.stdout.write(text)
114
+ }
115
+ })
116
+ child.stderr.on("data", (chunk) => {
117
+ const text = chunk.toString()
118
+ stderr += text
119
+ if (options.stream) {
120
+ process.stderr.write(text)
121
+ }
122
+ })
123
+ child.on("error", reject)
124
+ child.on("close", (code) => {
125
+ if (code === 0) {
126
+ resolve({ stdout, stderr, code })
127
+ } else {
128
+ reject(new Error(`Command failed (${code}): ${command} ${args.join(" ")}\n${stdout}${stderr}`))
129
+ }
130
+ })
131
+ })
132
+ }
133
+
134
+ function prefixedValue(output, prefix) {
135
+ const line = String(output || "").split(/\r?\n/).find((entry) => entry.startsWith(prefix))
136
+ if (!line) {
137
+ return ""
138
+ }
139
+ return line.slice(prefix.length)
140
+ }
141
+
142
+ function sectionValues(output, beginMarker, endMarker) {
143
+ const lines = String(output || "").split(/\r?\n/)
144
+ const begin = lines.findIndex((line) => line.trim() === beginMarker)
145
+ const end = lines.findIndex((line, index) => index > begin && line.trim() === endMarker)
146
+ if (begin === -1 || end === -1 || end <= begin) {
147
+ return []
148
+ }
149
+ return lines.slice(begin + 1, end).map((line) => line.trim()).filter(Boolean)
150
+ }
151
+
152
+ async function verifyHookFiles(ffmpeg) {
153
+ const hookFiles = ffmpeg.activationHookFiles()
154
+ for (const file of hookFiles) {
155
+ assert(await exists(file.path), `Missing activation hook: ${file.path}`)
156
+ }
157
+ }
158
+
159
+ async function verifyWindowsPatchedCache(ffmpeg) {
160
+ if (ffmpeg.kernel.platform !== "win32") {
161
+ return
162
+ }
163
+
164
+ const pkgsDir = ffmpeg.ffmpegPkgsDir()
165
+ const entries = await fs.promises.readdir(pkgsDir, { withFileTypes: true })
166
+ const packageDirs = entries
167
+ .filter((entry) => entry.isDirectory() && /^gdk-pixbuf-/.test(entry.name))
168
+ .map((entry) => path.resolve(pkgsDir, entry.name))
169
+
170
+ assert(packageDirs.length > 0, `No gdk-pixbuf package found under ${pkgsDir}`)
171
+
172
+ for (const packageDir of packageDirs) {
173
+ const scriptPath = path.resolve(packageDir, "Scripts", ".gdk-pixbuf-post-link.bat")
174
+ assert(await exists(scriptPath), `Missing patched gdk-pixbuf script: ${scriptPath}`)
175
+
176
+ const contents = await fs.promises.readFile(scriptPath)
177
+ assert(
178
+ contents.toString("utf8").includes("Pinokio intentionally skips gdk-pixbuf loader cache generation"),
179
+ `Unexpected gdk-pixbuf post-link contents in ${scriptPath}`
180
+ )
181
+
182
+ const pathsJsonPath = path.resolve(packageDir, "info", "paths.json")
183
+ const pathsJson = JSON.parse(await fs.promises.readFile(pathsJsonPath, "utf8"))
184
+ const entry = Array.isArray(pathsJson.paths)
185
+ ? pathsJson.paths.find((item) => item && item._path === "Scripts/.gdk-pixbuf-post-link.bat")
186
+ : null
187
+
188
+ assert(entry, `Missing paths.json entry for patched gdk-pixbuf script in ${pathsJsonPath}`)
189
+ assert(entry.size_in_bytes === contents.length, `paths.json size mismatch for ${scriptPath}`)
190
+
191
+ const sha256 = crypto.createHash("sha256").update(contents).digest("hex")
192
+ assert(entry.sha256 === sha256, `paths.json sha256 mismatch for ${scriptPath}`)
193
+ }
194
+ }
195
+
196
+ async function verifyPosixRuntime(ffmpeg, condaEnv) {
197
+ const shell = "/bin/bash"
198
+ const env = mergeEnv(process.env, condaEnv)
199
+ const expectedFfmpeg = ffmpeg.binaryPath("ffmpeg")
200
+ const expectedFfprobe = ffmpeg.binaryPath("ffprobe")
201
+ const expectedBinDir = path.dirname(expectedFfmpeg)
202
+ const expectedLibDir = ffmpeg.libraryDir()
203
+
204
+ const command = [
205
+ "set -e",
206
+ 'eval "$(conda shell.bash hook)"',
207
+ "conda deactivate || true",
208
+ "conda deactivate || true",
209
+ "conda deactivate || true",
210
+ "conda activate base",
211
+ 'printf "__FFMPEG__%s\\n" "$(command -v ffmpeg)"',
212
+ 'printf "__FFPROBE__%s\\n" "$(command -v ffprobe)"',
213
+ 'printf "__FFMPEG_PATH__%s\\n" "${FFMPEG_PATH-}"',
214
+ 'printf "__FFPROBE_PATH__%s\\n" "${FFPROBE_PATH-}"',
215
+ 'printf "__PATH__%s\\n" "$PATH"',
216
+ ffmpeg.kernel.platform === "linux"
217
+ ? 'printf "__LD_LIBRARY_PATH__%s\\n" "${LD_LIBRARY_PATH-}"'
218
+ : 'printf "__LD_LIBRARY_PATH__%s\\n" "${LD_LIBRARY_PATH-}"',
219
+ "ffmpeg -hide_banner -version | head -n 1",
220
+ "ffprobe -hide_banner -version | head -n 1",
221
+ "ffmpeg -hide_banner -encoders | grep -q libmp3lame",
222
+ ].join(" && ")
223
+
224
+ const { stdout } = await runCommand(shell, ["-lc", command], { env, stream: true })
225
+ const ffmpegResolved = prefixedValue(stdout, "__FFMPEG__")
226
+ const ffprobeResolved = prefixedValue(stdout, "__FFPROBE__")
227
+ const ffmpegPathEnv = prefixedValue(stdout, "__FFMPEG_PATH__")
228
+ const ffprobePathEnv = prefixedValue(stdout, "__FFPROBE_PATH__")
229
+ const shellPath = prefixedValue(stdout, "__PATH__")
230
+ const ldLibraryPath = prefixedValue(stdout, "__LD_LIBRARY_PATH__")
231
+
232
+ assert(
233
+ normalizePathForCompare(ffmpegResolved) === normalizePathForCompare(expectedFfmpeg),
234
+ `bash resolved ffmpeg to ${ffmpegResolved}, expected ${expectedFfmpeg}`
235
+ )
236
+ assert(
237
+ normalizePathForCompare(ffprobeResolved) === normalizePathForCompare(expectedFfprobe),
238
+ `bash resolved ffprobe to ${ffprobeResolved}, expected ${expectedFfprobe}`
239
+ )
240
+ assert(
241
+ normalizePathForCompare(ffmpegPathEnv) === normalizePathForCompare(expectedFfmpeg),
242
+ `FFMPEG_PATH was ${ffmpegPathEnv}, expected ${expectedFfmpeg}`
243
+ )
244
+ assert(
245
+ normalizePathForCompare(ffprobePathEnv) === normalizePathForCompare(expectedFfprobe),
246
+ `FFPROBE_PATH was ${ffprobePathEnv}, expected ${expectedFfprobe}`
247
+ )
248
+ assert(
249
+ shellPath.split(":").map((entry) => normalizePathForCompare(entry))[0] === normalizePathForCompare(expectedBinDir),
250
+ `PATH does not start with FFmpeg bin dir: ${expectedBinDir}`
251
+ )
252
+ if (ffmpeg.kernel.platform === "linux") {
253
+ assert(
254
+ ldLibraryPath.split(":").map((entry) => normalizePathForCompare(entry))[0] === normalizePathForCompare(expectedLibDir),
255
+ `LD_LIBRARY_PATH does not start with FFmpeg lib dir: ${expectedLibDir}`
256
+ )
257
+ }
258
+ }
259
+
260
+ async function verifyWindowsCmdRuntime(ffmpeg, condaEnv) {
261
+ const env = mergeEnv(process.env, condaEnv)
262
+ const expectedFfmpeg = ffmpeg.binaryPath("ffmpeg")
263
+ const expectedFfprobe = ffmpeg.binaryPath("ffprobe")
264
+ const expectedRuntimeDir = ffmpeg.libraryDir()
265
+
266
+ const command = [
267
+ "conda_hook",
268
+ "conda deactivate",
269
+ "conda deactivate",
270
+ "conda deactivate",
271
+ [
272
+ "conda activate base",
273
+ "echo __FFMPEG_PATH__%FFMPEG_PATH%",
274
+ "echo __FFPROBE_PATH__%FFPROBE_PATH%",
275
+ "echo __PATH__%PATH%",
276
+ "echo __FFMPEG_BEGIN__",
277
+ "where ffmpeg",
278
+ "echo __FFMPEG_END__",
279
+ "echo __FFPROBE_BEGIN__",
280
+ "where ffprobe",
281
+ "echo __FFPROBE_END__",
282
+ "ffmpeg -hide_banner -version",
283
+ "ffprobe -hide_banner -version",
284
+ 'ffmpeg -hide_banner -encoders | findstr /C:"libmp3lame"',
285
+ ].join(" && "),
286
+ ].join(" & ")
287
+
288
+ const shell = process.env.ComSpec || "cmd.exe"
289
+ const { stdout } = await runCommand(shell, ["/d", "/s", "/c", command], { env, stream: true })
290
+
291
+ const ffmpegPathEnv = prefixedValue(stdout, "__FFMPEG_PATH__")
292
+ const ffprobePathEnv = prefixedValue(stdout, "__FFPROBE_PATH__")
293
+ const shellPath = prefixedValue(stdout, "__PATH__")
294
+ const ffmpegResolved = sectionValues(stdout, "__FFMPEG_BEGIN__", "__FFMPEG_END__")[0]
295
+ const ffprobeResolved = sectionValues(stdout, "__FFPROBE_BEGIN__", "__FFPROBE_END__")[0]
296
+
297
+ assert(
298
+ normalizePathForCompare(ffmpegResolved) === normalizePathForCompare(expectedFfmpeg),
299
+ `cmd resolved ffmpeg to ${ffmpegResolved}, expected ${expectedFfmpeg}`
300
+ )
301
+ assert(
302
+ normalizePathForCompare(ffprobeResolved) === normalizePathForCompare(expectedFfprobe),
303
+ `cmd resolved ffprobe to ${ffprobeResolved}, expected ${expectedFfprobe}`
304
+ )
305
+ assert(
306
+ normalizePathForCompare(ffmpegPathEnv) === normalizePathForCompare(expectedFfmpeg),
307
+ `FFMPEG_PATH was ${ffmpegPathEnv}, expected ${expectedFfmpeg}`
308
+ )
309
+ assert(
310
+ normalizePathForCompare(ffprobePathEnv) === normalizePathForCompare(expectedFfprobe),
311
+ `FFPROBE_PATH was ${ffprobePathEnv}, expected ${expectedFfprobe}`
312
+ )
313
+ assert(
314
+ shellPath.split(";").map((entry) => normalizePathForCompare(entry))[0] === normalizePathForCompare(expectedRuntimeDir),
315
+ `PATH does not start with FFmpeg runtime dir: ${expectedRuntimeDir}`
316
+ )
317
+ }
318
+
319
+ async function verifyWindowsPowerShellRuntime(ffmpeg, condaEnv) {
320
+ const env = mergeEnv(process.env, condaEnv)
321
+ const expectedFfmpeg = ffmpeg.binaryPath("ffmpeg")
322
+ const expectedFfprobe = ffmpeg.binaryPath("ffprobe")
323
+ const expectedRuntimeDir = ffmpeg.libraryDir()
324
+
325
+ const script = [
326
+ "$ErrorActionPreference = 'Stop'",
327
+ "conda_hook",
328
+ "conda deactivate",
329
+ "conda deactivate",
330
+ "conda deactivate",
331
+ "conda activate base",
332
+ 'Write-Output ("__FFMPEG_PATH__" + $Env:FFMPEG_PATH)',
333
+ 'Write-Output ("__FFPROBE_PATH__" + $Env:FFPROBE_PATH)',
334
+ 'Write-Output ("__PATH__" + $Env:Path)',
335
+ 'Write-Output ("__FFMPEG__" + (Get-Command ffmpeg).Source)',
336
+ 'Write-Output ("__FFPROBE__" + (Get-Command ffprobe).Source)',
337
+ "ffmpeg -hide_banner -version | Select-Object -First 1",
338
+ "ffprobe -hide_banner -version | Select-Object -First 1",
339
+ "if (-not (ffmpeg -hide_banner -encoders | Select-String -SimpleMatch 'libmp3lame')) { exit 1 }",
340
+ ].join("; ")
341
+
342
+ const shell = process.env.SystemRoot
343
+ ? path.resolve(process.env.SystemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
344
+ : "powershell.exe"
345
+ const { stdout } = await runCommand(shell, ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", script], { env, stream: true })
346
+
347
+ const ffmpegResolved = prefixedValue(stdout, "__FFMPEG__")
348
+ const ffprobeResolved = prefixedValue(stdout, "__FFPROBE__")
349
+ const ffmpegPathEnv = prefixedValue(stdout, "__FFMPEG_PATH__")
350
+ const ffprobePathEnv = prefixedValue(stdout, "__FFPROBE_PATH__")
351
+ const shellPath = prefixedValue(stdout, "__PATH__")
352
+
353
+ assert(
354
+ normalizePathForCompare(ffmpegResolved) === normalizePathForCompare(expectedFfmpeg),
355
+ `PowerShell resolved ffmpeg to ${ffmpegResolved}, expected ${expectedFfmpeg}`
356
+ )
357
+ assert(
358
+ normalizePathForCompare(ffprobeResolved) === normalizePathForCompare(expectedFfprobe),
359
+ `PowerShell resolved ffprobe to ${ffprobeResolved}, expected ${expectedFfprobe}`
360
+ )
361
+ assert(
362
+ normalizePathForCompare(ffmpegPathEnv) === normalizePathForCompare(expectedFfmpeg),
363
+ `PowerShell FFMPEG_PATH was ${ffmpegPathEnv}, expected ${expectedFfmpeg}`
364
+ )
365
+ assert(
366
+ normalizePathForCompare(ffprobePathEnv) === normalizePathForCompare(expectedFfprobe),
367
+ `PowerShell FFPROBE_PATH was ${ffprobePathEnv}, expected ${expectedFfprobe}`
368
+ )
369
+ assert(
370
+ shellPath.split(";").map((entry) => normalizePathForCompare(entry))[0] === normalizePathForCompare(expectedRuntimeDir),
371
+ `PowerShell PATH does not start with FFmpeg runtime dir: ${expectedRuntimeDir}`
372
+ )
373
+ }
374
+
375
+ async function main() {
376
+ const options = parseArgs(process.argv.slice(2))
377
+ if (options.help) {
378
+ console.log(usage())
379
+ return
380
+ }
381
+
382
+ process.env.PINOKIO_HOME = options.home
383
+ console.log(`[verify-ffmpeg] home=${options.home}`)
384
+ console.log(`[verify-ffmpeg] platform=${os.platform()} arch=${os.arch()}`)
385
+
386
+ const kernel = new Kernel({ store: {} })
387
+ await kernel.init({})
388
+ await kernel.shell.init()
389
+ await kernel.bin.init()
390
+ await kernel.bin.refreshInstalled()
391
+
392
+ if (kernel.refresh_interval) {
393
+ clearInterval(kernel.refresh_interval)
394
+ }
395
+ kernel.server_running = true
396
+
397
+ const conda = kernel.bin.mod("conda")
398
+ const ffmpeg = kernel.bin.mod("ffmpeg")
399
+
400
+ assert(conda, "Conda module was not initialized")
401
+ assert(ffmpeg, "FFmpeg module was not initialized")
402
+
403
+ if (!kernel.bin.installed.conda || !(await conda.installed())) {
404
+ console.log("[verify-ffmpeg] installing conda")
405
+ await kernel.bin.install({
406
+ params: [
407
+ {
408
+ name: "conda",
409
+ dependencies: [],
410
+ }
411
+ ]
412
+ }, logOnData)
413
+ await kernel.bin.refreshInstalled()
414
+ }
415
+
416
+ if (!options.skipInstall) {
417
+ const ffmpegInstalled = await ffmpeg.installed()
418
+ if (options.reinstall && ffmpegInstalled) {
419
+ console.log("[verify-ffmpeg] reinstall requested, removing existing ffmpeg")
420
+ await ffmpeg.uninstall({}, logOnData)
421
+ await kernel.bin.refreshInstalled()
422
+ }
423
+ if (options.reinstall || !(await ffmpeg.installed())) {
424
+ console.log("[verify-ffmpeg] installing ffmpeg")
425
+ await kernel.bin.install({
426
+ params: [
427
+ {
428
+ name: "ffmpeg",
429
+ }
430
+ ]
431
+ }, logOnData)
432
+ await kernel.bin.refreshInstalled()
433
+ }
434
+ }
435
+
436
+ assert(await ffmpeg.installed(), "FFmpeg module did not report installed after setup")
437
+ await ffmpeg.selfTest(logOnData)
438
+ await verifyHookFiles(ffmpeg)
439
+ await verifyWindowsPatchedCache(ffmpeg)
440
+
441
+ const condaEnv = conda.env()
442
+ if (kernel.platform === "win32") {
443
+ console.log("[verify-ffmpeg] verifying cmd.exe runtime")
444
+ await verifyWindowsCmdRuntime(ffmpeg, condaEnv)
445
+ console.log("[verify-ffmpeg] verifying PowerShell runtime")
446
+ await verifyWindowsPowerShellRuntime(ffmpeg, condaEnv)
447
+ } else {
448
+ console.log("[verify-ffmpeg] verifying bash runtime")
449
+ await verifyPosixRuntime(ffmpeg, condaEnv)
450
+ }
451
+
452
+ console.log("[verify-ffmpeg] all checks passed")
453
+ }
454
+
455
+ main().catch((error) => {
456
+ console.error("[verify-ffmpeg] failed")
457
+ console.error(error && error.stack ? error.stack : error)
458
+ process.exit(1)
459
+ })