@acpfx/mic-speaker 0.4.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/bin/mic-aec-darwin-arm64 +0 -0
- package/bin/mic-speaker +36 -0
- package/package.json +25 -0
- package/scripts/postinstall.js +113 -0
|
Binary file
|
package/bin/mic-speaker
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { spawnSync } = require("child_process");
|
|
6
|
+
const { join } = require("path");
|
|
7
|
+
const { existsSync } = require("fs");
|
|
8
|
+
|
|
9
|
+
function getBinaryPath() {
|
|
10
|
+
// Allow override via env var (for local development)
|
|
11
|
+
if (process.env.MIC_SPEAKER_BINARY_PATH) {
|
|
12
|
+
return process.env.MIC_SPEAKER_BINARY_PATH;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
16
|
+
const binName = `mic-speaker-${process.platform}-${process.arch}${ext}`;
|
|
17
|
+
const binPath = join(__dirname, binName);
|
|
18
|
+
|
|
19
|
+
if (!existsSync(binPath)) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`Could not find the mic-speaker binary for your platform (${process.platform} ${process.arch}).\n` +
|
|
22
|
+
`Expected: ${binPath}\n` +
|
|
23
|
+
`The postinstall script may have failed. Try reinstalling:\n` +
|
|
24
|
+
` npm install @acpfx/mic-speaker\n` +
|
|
25
|
+
`Or set MIC_SPEAKER_BINARY_PATH to a local build.`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return binPath;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const binPath = getBinaryPath();
|
|
33
|
+
const { status } = spawnSync(binPath, process.argv.slice(2), {
|
|
34
|
+
stdio: "inherit",
|
|
35
|
+
});
|
|
36
|
+
process.exitCode = status !== null ? status : 1;
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@acpfx/mic-speaker",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "acpfx microphone with acoustic echo cancellation",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/thisnick/acpfx",
|
|
8
|
+
"directory": "packages/node-mic-speaker"
|
|
9
|
+
},
|
|
10
|
+
"license": "ISC",
|
|
11
|
+
"bin": {
|
|
12
|
+
"acpfx-mic-speaker": "./bin/mic-speaker"
|
|
13
|
+
},
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"bin/",
|
|
19
|
+
"scripts/"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build:native": "cargo build --release && mkdir -p bin && cp target/release/mic-speaker bin/",
|
|
23
|
+
"postinstall": "node scripts/postinstall.js"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const https = require("https");
|
|
4
|
+
const http = require("http");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
|
|
8
|
+
const SUPPORTED_PLATFORMS = {
|
|
9
|
+
"darwin arm64": "mic-speaker-darwin-arm64",
|
|
10
|
+
"darwin x64": "mic-speaker-darwin-x64",
|
|
11
|
+
"linux x64": "mic-speaker-linux-x64",
|
|
12
|
+
"win32 x64": "mic-speaker-win32-x64.exe",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function hasNvidiaGpu() {
|
|
16
|
+
try {
|
|
17
|
+
require("child_process").execSync("nvidia-smi", { stdio: "ignore" });
|
|
18
|
+
return true;
|
|
19
|
+
} catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getBinaryName() {
|
|
25
|
+
const key = `${process.platform} ${process.arch}`;
|
|
26
|
+
const base = SUPPORTED_PLATFORMS[key];
|
|
27
|
+
if (!base) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`Unsupported platform: ${process.platform} ${process.arch}.\n` +
|
|
30
|
+
`Supported: ${Object.keys(SUPPORTED_PLATFORMS).join(", ")}`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Try CUDA variant on Linux/Windows when an NVIDIA GPU is present
|
|
35
|
+
if ((process.platform === "linux" || process.platform === "win32") && hasNvidiaGpu()) {
|
|
36
|
+
return base.replace(/(\.\w+)?$/, "-cuda$1");
|
|
37
|
+
}
|
|
38
|
+
return base;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function fetch(url) {
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
const lib = url.startsWith("https") ? https : http;
|
|
44
|
+
lib
|
|
45
|
+
.get(url, { headers: { "User-Agent": "mic-speaker-postinstall" } }, (res) => {
|
|
46
|
+
// Follow redirects (GitHub releases redirect to S3)
|
|
47
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
48
|
+
return fetch(res.headers.location).then(resolve, reject);
|
|
49
|
+
}
|
|
50
|
+
if (res.statusCode !== 200) {
|
|
51
|
+
reject(new Error(`HTTP ${res.statusCode} for ${url}`));
|
|
52
|
+
res.resume();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const chunks = [];
|
|
56
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
57
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
58
|
+
res.on("error", reject);
|
|
59
|
+
})
|
|
60
|
+
.on("error", reject);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function main() {
|
|
65
|
+
const pkg = require("../package.json");
|
|
66
|
+
const version = pkg.version;
|
|
67
|
+
const binaryName = getBinaryName();
|
|
68
|
+
const binDir = path.join(__dirname, "..", "bin");
|
|
69
|
+
const destPath = path.join(binDir, binaryName);
|
|
70
|
+
|
|
71
|
+
// Skip if binary already exists (e.g. local dev with pre-built binary)
|
|
72
|
+
if (fs.existsSync(destPath)) {
|
|
73
|
+
console.log(`mic-speaker: binary already exists at ${destPath}, skipping download.`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const url = `https://github.com/thisnick/acpfx/releases/download/%40acpfx/mic-speaker%40${version}/${binaryName}`;
|
|
78
|
+
console.log(`mic-speaker: downloading ${binaryName} from GitHub Releases...`);
|
|
79
|
+
console.log(` ${url}`);
|
|
80
|
+
|
|
81
|
+
let data;
|
|
82
|
+
try {
|
|
83
|
+
data = await fetch(url);
|
|
84
|
+
} catch (err) {
|
|
85
|
+
// If CUDA variant failed, fall back to CPU binary
|
|
86
|
+
const cpuName = SUPPORTED_PLATFORMS[`${process.platform} ${process.arch}`];
|
|
87
|
+
if (binaryName !== cpuName) {
|
|
88
|
+
console.log(`mic-speaker: CUDA binary not available, falling back to CPU variant...`);
|
|
89
|
+
const cpuUrl = `https://github.com/thisnick/acpfx/releases/download/%40acpfx/mic-speaker%40${version}/${cpuName}`;
|
|
90
|
+
console.log(` ${cpuUrl}`);
|
|
91
|
+
data = await fetch(cpuUrl);
|
|
92
|
+
} else {
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Ensure bin/ directory exists
|
|
98
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
99
|
+
|
|
100
|
+
fs.writeFileSync(destPath, data);
|
|
101
|
+
fs.chmodSync(destPath, 0o755);
|
|
102
|
+
|
|
103
|
+
console.log(`mic-speaker: installed ${binaryName} (${(data.length / 1024 / 1024).toFixed(1)} MB)`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
main().catch((err) => {
|
|
107
|
+
console.warn(`mic-speaker: postinstall failed — ${err.message}`);
|
|
108
|
+
console.warn(
|
|
109
|
+
"mic-speaker: the native binary could not be downloaded. " +
|
|
110
|
+
"You can build locally with: cargo build --release -p mic-speaker"
|
|
111
|
+
);
|
|
112
|
+
// Don't exit with error — allow npm install to succeed
|
|
113
|
+
});
|