@mingxy/ocosay 1.1.8 → 1.1.10
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/core/backends/index.js +6 -2
- package/dist/package.json +1 -1
- package/dist/plugin.js +114 -27
- package/package.json +1 -1
- package/scripts/install-portaudio.cjs +131 -76
|
@@ -75,7 +75,11 @@ export function createBackend(type = BackendType.AUTO, options = {}) {
|
|
|
75
75
|
try {
|
|
76
76
|
const naudiodon = require('naudiodon');
|
|
77
77
|
if (naudiodon) {
|
|
78
|
-
|
|
78
|
+
const devices = naudiodon.getDevices();
|
|
79
|
+
if (devices && devices.length > 0) {
|
|
80
|
+
return new NaudiodonBackend(options);
|
|
81
|
+
}
|
|
82
|
+
logger.debug('naudiodon has no audio devices, skipping');
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
85
|
catch (err) {
|
|
@@ -93,7 +97,7 @@ export function createBackend(type = BackendType.AUTO, options = {}) {
|
|
|
93
97
|
case 'win32':
|
|
94
98
|
return new PowerShellBackend(options);
|
|
95
99
|
default:
|
|
96
|
-
|
|
100
|
+
return new HowlerBackend(options);
|
|
97
101
|
}
|
|
98
102
|
}
|
|
99
103
|
function createBackendByType(type, options) {
|
package/dist/package.json
CHANGED
package/dist/plugin.js
CHANGED
|
@@ -7485,7 +7485,11 @@ function createBackend(type = "auto" /* AUTO */, options = {}) {
|
|
|
7485
7485
|
try {
|
|
7486
7486
|
const naudiodon = __require("naudiodon");
|
|
7487
7487
|
if (naudiodon) {
|
|
7488
|
-
|
|
7488
|
+
const devices = naudiodon.getDevices();
|
|
7489
|
+
if (devices && devices.length > 0) {
|
|
7490
|
+
return new NaudiodonBackend(options);
|
|
7491
|
+
}
|
|
7492
|
+
logger.debug("naudiodon has no audio devices, skipping");
|
|
7489
7493
|
}
|
|
7490
7494
|
} catch (err) {
|
|
7491
7495
|
logger.error({ err }, "failed to initialize naudiodon backend");
|
|
@@ -7502,7 +7506,7 @@ function createBackend(type = "auto" /* AUTO */, options = {}) {
|
|
|
7502
7506
|
case "win32":
|
|
7503
7507
|
return new PowerShellBackend(options);
|
|
7504
7508
|
default:
|
|
7505
|
-
|
|
7509
|
+
return new HowlerBackend(options);
|
|
7506
7510
|
}
|
|
7507
7511
|
}
|
|
7508
7512
|
function createBackendByType(type, options) {
|
|
@@ -9594,7 +9598,7 @@ async function ensureNaudiodonCompiled() {
|
|
|
9594
9598
|
return;
|
|
9595
9599
|
} catch {
|
|
9596
9600
|
logger8.info("naudiodon not compiled, will attempt to compile");
|
|
9597
|
-
notificationService.info("\u6B63\u5728\u7F16\u8BD1 naudiodon...", "Ocosay \u97F3\u9891\u540E\u7AEF");
|
|
9601
|
+
notificationService.info("\u6B63\u5728\u7F16\u8BD1 naudiodon...", "Ocosay \u97F3\u9891\u540E\u7AEF", 5e3);
|
|
9598
9602
|
}
|
|
9599
9603
|
try {
|
|
9600
9604
|
const naudiodonPath = dirname2(require2.resolve("naudiodon"));
|
|
@@ -9604,54 +9608,137 @@ async function ensureNaudiodonCompiled() {
|
|
|
9604
9608
|
stdio: "inherit"
|
|
9605
9609
|
});
|
|
9606
9610
|
logger8.info("naudiodon compiled successfully");
|
|
9607
|
-
notificationService.success("naudiodon \u7F16\u8BD1\u6210\u529F", "\u97F3\u9891\u540E\u7AEF\u5DF2\u5C31\u7EEA");
|
|
9611
|
+
notificationService.success("naudiodon \u7F16\u8BD1\u6210\u529F", "\u97F3\u9891\u540E\u7AEF\u5DF2\u5C31\u7EEA", 5e3);
|
|
9608
9612
|
} catch (err) {
|
|
9609
9613
|
logger8.warn({ err }, "naudiodon rebuild failed, checking for PortAudio");
|
|
9610
|
-
notificationService.warning("naudiodon \u7F16\u8BD1\u5931\u8D25", "\u6B63\u5728\u5C1D\u8BD5\u5B89\u88C5 PortAudio...");
|
|
9611
|
-
const installed = installPortAudio();
|
|
9612
|
-
if (installed) {
|
|
9614
|
+
notificationService.warning("naudiodon \u7F16\u8BD1\u5931\u8D25", "\u6B63\u5728\u5C1D\u8BD5\u5B89\u88C5 PortAudio...", 5e3);
|
|
9615
|
+
const installed = await installPortAudio();
|
|
9616
|
+
if (installed.success) {
|
|
9613
9617
|
try {
|
|
9614
9618
|
const naudiodonPath = dirname2(require2.resolve("naudiodon"));
|
|
9615
|
-
notificationService.info("\u6B63\u5728\u91CD\u65B0\u7F16\u8BD1 naudiodon...", "Ocosay");
|
|
9619
|
+
notificationService.info("\u6B63\u5728\u91CD\u65B0\u7F16\u8BD1 naudiodon...", "Ocosay", 5e3);
|
|
9616
9620
|
execSync("npm rebuild naudiodon", {
|
|
9617
9621
|
cwd: naudiodonPath,
|
|
9618
9622
|
stdio: "inherit"
|
|
9619
9623
|
});
|
|
9620
9624
|
logger8.info("naudiodon compiled successfully after PortAudio install");
|
|
9621
|
-
notificationService.success("naudiodon \u7F16\u8BD1\u6210\u529F", "\u97F3\u9891\u540E\u7AEF\u5DF2\u5C31\u7EEA");
|
|
9625
|
+
notificationService.success("naudiodon \u7F16\u8BD1\u6210\u529F", "\u97F3\u9891\u540E\u7AEF\u5DF2\u5C31\u7EEA", 5e3);
|
|
9622
9626
|
} catch (retryErr) {
|
|
9623
9627
|
logger8.error({ err: retryErr }, "naudiodon compile failed even after PortAudio install");
|
|
9624
|
-
notificationService.error("naudiodon \u7F16\u8BD1\u5931\u8D25", "\u81EA\u52A8\u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u5C1D\u8BD5\u624B\u52A8\u5B89\u88C5");
|
|
9628
|
+
notificationService.error("naudiodon \u7F16\u8BD1\u5931\u8D25", "\u81EA\u52A8\u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u5C1D\u8BD5\u624B\u52A8\u5B89\u88C5", 8e3);
|
|
9625
9629
|
markNaudiodonSkipped();
|
|
9626
9630
|
}
|
|
9627
9631
|
} else {
|
|
9628
9632
|
logger8.error("PortAudio install failed");
|
|
9629
|
-
notificationService.error("PortAudio \u5B89\u88C5\u5931\u8D25", "\u81EA\u52A8\u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u5C1D\u8BD5\u624B\u52A8\u5B89\u88C5");
|
|
9633
|
+
notificationService.error("PortAudio \u5B89\u88C5\u5931\u8D25", "\u81EA\u52A8\u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u5C1D\u8BD5\u624B\u52A8\u5B89\u88C5", 8e3);
|
|
9630
9634
|
markNaudiodonSkipped();
|
|
9631
9635
|
}
|
|
9632
9636
|
}
|
|
9633
9637
|
}
|
|
9634
|
-
function
|
|
9635
|
-
const platform = process.platform;
|
|
9636
|
-
logger8.info({ platform }, "installing PortAudio for platform");
|
|
9637
|
-
notificationService.info("\u6B63\u5728\u5B89\u88C5 PortAudio...", `\u5E73\u53F0: ${platform}`);
|
|
9638
|
+
function execCmd(cmd) {
|
|
9638
9639
|
try {
|
|
9639
|
-
|
|
9640
|
-
|
|
9641
|
-
} else if (platform === "darwin") {
|
|
9642
|
-
execSync("brew install portaudio", { stdio: "inherit" });
|
|
9643
|
-
} else if (platform === "win32") {
|
|
9644
|
-
execSync("choco install portaudio -y", { stdio: "inherit" });
|
|
9645
|
-
} else {
|
|
9646
|
-
logger8.warn("unsupported platform for automatic PortAudio install");
|
|
9647
|
-
return false;
|
|
9648
|
-
}
|
|
9649
|
-
return true;
|
|
9640
|
+
const output = execSync(cmd, { stdio: "pipe", encoding: "utf8" });
|
|
9641
|
+
return { success: true, output };
|
|
9650
9642
|
} catch (err) {
|
|
9651
|
-
|
|
9643
|
+
return { success: false, output: err.message || "" };
|
|
9644
|
+
}
|
|
9645
|
+
}
|
|
9646
|
+
function isWsl2() {
|
|
9647
|
+
if (process.platform !== "linux") return false;
|
|
9648
|
+
try {
|
|
9649
|
+
return require2("fs").readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft");
|
|
9650
|
+
} catch {
|
|
9652
9651
|
return false;
|
|
9653
9652
|
}
|
|
9654
9653
|
}
|
|
9654
|
+
function checkAlsa() {
|
|
9655
|
+
const result = execCmd("which aplay");
|
|
9656
|
+
if (!result.success) return false;
|
|
9657
|
+
const test = execCmd("aplay -l");
|
|
9658
|
+
return test.success && !test.output.includes("no soundcards");
|
|
9659
|
+
}
|
|
9660
|
+
async function installPortAudio() {
|
|
9661
|
+
const platform = process.platform;
|
|
9662
|
+
const wsl = isWsl2();
|
|
9663
|
+
logger8.info({ platform, wsl }, "installing PortAudio");
|
|
9664
|
+
const runInstall = async (cmd, desc) => {
|
|
9665
|
+
logger8.info(`Running: ${cmd}`);
|
|
9666
|
+
notificationService.info(desc, "\u6B63\u5728\u5B89\u88C5...", 5e3);
|
|
9667
|
+
try {
|
|
9668
|
+
execSync(cmd, { stdio: "inherit" });
|
|
9669
|
+
return true;
|
|
9670
|
+
} catch (err) {
|
|
9671
|
+
const msg = err.message || "";
|
|
9672
|
+
if (msg.includes("sudo") || msg.includes("password") || msg.includes("Password")) {
|
|
9673
|
+
notificationService.error(
|
|
9674
|
+
"\u9700\u8981 sudo \u6743\u9650",
|
|
9675
|
+
"\u8BF7\u624B\u52A8\u8FD0\u884C: sudo apt-get update && sudo apt-get install -y alsa-utils",
|
|
9676
|
+
8e3
|
|
9677
|
+
);
|
|
9678
|
+
logger8.error({ err }, "sudo password required");
|
|
9679
|
+
return false;
|
|
9680
|
+
}
|
|
9681
|
+
if (msg.includes("already") || msg.includes("is already")) {
|
|
9682
|
+
logger8.info("already installed");
|
|
9683
|
+
return true;
|
|
9684
|
+
}
|
|
9685
|
+
notificationService.error(desc + " \u5931\u8D25", msg.substring(0, 100), 8e3);
|
|
9686
|
+
logger8.error({ err }, `install failed: ${desc}`);
|
|
9687
|
+
return false;
|
|
9688
|
+
}
|
|
9689
|
+
};
|
|
9690
|
+
if (platform === "linux" || wsl) {
|
|
9691
|
+
notificationService.info("\u68C0\u6D4B\u97F3\u9891\u8BBE\u5907...", "\u97F3\u9891\u540E\u7AEF", 5e3);
|
|
9692
|
+
if (checkAlsa()) {
|
|
9693
|
+
logger8.info("alsa-utils already available and working");
|
|
9694
|
+
notificationService.success("alsa-utils \u5C31\u7EEA", "\u97F3\u9891\u540E\u7AEF\u5DF2\u53EF\u7528", 5e3);
|
|
9695
|
+
return { success: true, message: "alsa" };
|
|
9696
|
+
}
|
|
9697
|
+
notificationService.info("\u5B89\u88C5 alsa-utils...", "\u97F3\u9891\u540E\u7AEF", 5e3);
|
|
9698
|
+
const alsaInstalled = await runInstall(
|
|
9699
|
+
"sudo apt-get update && sudo apt-get install -y alsa-utils",
|
|
9700
|
+
"\u5B89\u88C5 alsa-utils"
|
|
9701
|
+
);
|
|
9702
|
+
if (alsaInstalled) {
|
|
9703
|
+
if (checkAlsa()) {
|
|
9704
|
+
notificationService.success("alsa-utils \u5B89\u88C5\u6210\u529F", "\u97F3\u9891\u540E\u7AEF\u5DF2\u5C31\u7EEA", 5e3);
|
|
9705
|
+
return { success: true, message: "alsa" };
|
|
9706
|
+
} else {
|
|
9707
|
+
notificationService.warning("alsa-utils \u5B89\u88C5\u540E\u68C0\u6D4B\u5931\u8D25", "\u7EE7\u7EED\u5C1D\u8BD5\u5176\u4ED6\u65B9\u6848", 5e3);
|
|
9708
|
+
}
|
|
9709
|
+
}
|
|
9710
|
+
notificationService.info("\u5B89\u88C5 libportaudio-dev...", "\u97F3\u9891\u540E\u7AEF", 5e3);
|
|
9711
|
+
const portaudioInstalled = await runInstall(
|
|
9712
|
+
"sudo apt-get update && sudo apt-get install -y libportaudio-dev",
|
|
9713
|
+
"\u5B89\u88C5 libportaudio-dev"
|
|
9714
|
+
);
|
|
9715
|
+
if (portaudioInstalled) {
|
|
9716
|
+
notificationService.success("libportaudio-dev \u5B89\u88C5\u6210\u529F", "\u97F3\u9891\u540E\u7AEF\u5DF2\u5C31\u7EEA", 5e3);
|
|
9717
|
+
return { success: true, message: "portaudio" };
|
|
9718
|
+
}
|
|
9719
|
+
notificationService.warning("PortAudio \u5B89\u88C5\u5931\u8D25", "\u97F3\u9891\u53EF\u80FD\u65E0\u6CD5\u6B63\u5E38\u5DE5\u4F5C", 5e3);
|
|
9720
|
+
markNaudiodonSkipped();
|
|
9721
|
+
return { success: false, message: "linux install failed" };
|
|
9722
|
+
}
|
|
9723
|
+
if (platform === "darwin") {
|
|
9724
|
+
const installed = await runInstall("brew install portaudio", "\u5B89\u88C5 PortAudio (macOS)");
|
|
9725
|
+
if (installed) {
|
|
9726
|
+
return { success: true, message: "portaudio" };
|
|
9727
|
+
}
|
|
9728
|
+
markNaudiodonSkipped();
|
|
9729
|
+
return { success: false, message: "macos install failed" };
|
|
9730
|
+
}
|
|
9731
|
+
if (platform === "win32") {
|
|
9732
|
+
const installed = await runInstall("choco install portaudio -y", "\u5B89\u88C5 PortAudio (Windows)");
|
|
9733
|
+
if (installed) {
|
|
9734
|
+
return { success: true, message: "portaudio" };
|
|
9735
|
+
}
|
|
9736
|
+
markNaudiodonSkipped();
|
|
9737
|
+
return { success: false, message: "windows install failed" };
|
|
9738
|
+
}
|
|
9739
|
+
markNaudiodonSkipped();
|
|
9740
|
+
return { success: false, message: "unsupported platform" };
|
|
9741
|
+
}
|
|
9655
9742
|
var __filename = fileURLToPath(import.meta.url);
|
|
9656
9743
|
var __dirname2 = dirname2(__filename);
|
|
9657
9744
|
var id = "ocosay";
|
package/package.json
CHANGED
|
@@ -1,117 +1,172 @@
|
|
|
1
1
|
const { execSync, spawn } = require('child_process');
|
|
2
2
|
const fs = require('fs');
|
|
3
|
-
const
|
|
3
|
+
const readline = require('readline');
|
|
4
4
|
|
|
5
|
+
const platform = process.platform;
|
|
5
6
|
const isWSL = fs.existsSync('/proc/version') &&
|
|
6
7
|
fs.readFileSync('/proc/version', 'utf8').includes('Microsoft');
|
|
7
|
-
const platform = process.platform;
|
|
8
8
|
|
|
9
9
|
const log = {
|
|
10
|
-
info: (msg) => console.log(
|
|
11
|
-
success: (msg) => console.log(
|
|
12
|
-
warn: (msg) => console.log(
|
|
13
|
-
error: (msg) => console.error(
|
|
10
|
+
info: (msg) => console.log(`[INFO] ${msg}`),
|
|
11
|
+
success: (msg) => console.log(`[OK] ${msg}`),
|
|
12
|
+
warn: (msg) => console.log(`[WARN] ${msg}`),
|
|
13
|
+
error: (msg) => console.error(`[ERROR] ${msg}`)
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
function
|
|
16
|
+
function exec(cmd, ignoreError = false) {
|
|
17
|
+
try {
|
|
18
|
+
const output = execSync(cmd, { stdio: 'pipe', encoding: 'utf8' });
|
|
19
|
+
return { success: true, output };
|
|
20
|
+
} catch (err) {
|
|
21
|
+
if (ignoreError) return { success: false, output: '' };
|
|
22
|
+
return { success: false, output: err.message };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function askPassword() {
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
const rl = readline.createInterface({
|
|
29
|
+
input: process.stdin,
|
|
30
|
+
output: process.stdout
|
|
31
|
+
});
|
|
32
|
+
rl.question('需要 sudo 权限,请输入密码: ', (password) => {
|
|
33
|
+
rl.close();
|
|
34
|
+
resolve(password);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function runWithSudo(cmd) {
|
|
40
|
+
// 先尝试直接运行(可能已缓存密码)
|
|
17
41
|
try {
|
|
18
42
|
execSync(cmd, { stdio: 'ignore' });
|
|
19
43
|
return true;
|
|
20
|
-
} catch {
|
|
44
|
+
} catch { /* 继续尝试密码 */ }
|
|
45
|
+
|
|
46
|
+
// 需要密码
|
|
47
|
+
const password = await askPassword();
|
|
48
|
+
if (!password) {
|
|
49
|
+
log.error('未输入密码,安装取消');
|
|
21
50
|
return false;
|
|
22
51
|
}
|
|
52
|
+
|
|
53
|
+
return new Promise((resolve) => {
|
|
54
|
+
const proc = spawn('bash', ['-c', `echo "${password}" | sudo -S ${cmd}`], {
|
|
55
|
+
stdio: 'inherit'
|
|
56
|
+
});
|
|
57
|
+
proc.on('close', (code) => resolve(code === 0));
|
|
58
|
+
proc.on('error', () => resolve(false));
|
|
59
|
+
});
|
|
23
60
|
}
|
|
24
61
|
|
|
25
|
-
async function
|
|
26
|
-
return new Promise((resolve
|
|
62
|
+
async function execCmd(cmd) {
|
|
63
|
+
return new Promise((resolve) => {
|
|
27
64
|
const shell = platform === 'win32' ? 'powershell' : 'bash';
|
|
28
65
|
const args = platform === 'win32' ? ['-Command', cmd] : ['-c', cmd];
|
|
29
66
|
const proc = spawn(shell, args, { stdio: 'inherit' });
|
|
30
|
-
proc.on('close', (code) => (code === 0
|
|
31
|
-
proc.on('error',
|
|
67
|
+
proc.on('close', (code) => resolve(code === 0));
|
|
68
|
+
proc.on('error', () => resolve(false));
|
|
32
69
|
});
|
|
33
70
|
}
|
|
34
71
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
await runCmd('brew install portaudio');
|
|
43
|
-
return true;
|
|
44
|
-
} catch {
|
|
45
|
-
return false;
|
|
72
|
+
function checkAlsa() {
|
|
73
|
+
const result = exec('which aplay');
|
|
74
|
+
if (result.success) {
|
|
75
|
+
const aplayOutput = exec('aplay -l');
|
|
76
|
+
if (aplayOutput.success && !aplayOutput.output.includes('no soundcards')) {
|
|
77
|
+
return { available: true, type: 'alsa', command: result.output.trim() };
|
|
78
|
+
}
|
|
46
79
|
}
|
|
80
|
+
return { available: false, type: null, command: result.success ? result.output.trim() : null };
|
|
47
81
|
}
|
|
48
82
|
|
|
49
|
-
async function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
log.info('安装 PortAudio (WSL)...');
|
|
55
|
-
try {
|
|
56
|
-
await runCmd('sudo apt-get update && sudo apt-get install -y libportaudio-dev portaudio');
|
|
57
|
-
return true;
|
|
58
|
-
} catch {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
83
|
+
async function installAlsaUtils() {
|
|
84
|
+
log.info('安装 alsa-utils...');
|
|
85
|
+
return runWithSudo('apt-get update && apt-get install -y alsa-utils');
|
|
61
86
|
}
|
|
62
87
|
|
|
63
|
-
async function
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
await runCmd('choco install portaudio -y');
|
|
75
|
-
return true;
|
|
76
|
-
} catch {
|
|
77
|
-
return false;
|
|
88
|
+
async function installPortAudioDev() {
|
|
89
|
+
log.info('安装 libportaudio-dev...');
|
|
90
|
+
return runWithSudo('apt-get update && apt-get install -y libportaudio-dev');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function testAlsaPlayback() {
|
|
94
|
+
const result = exec('aplay -l');
|
|
95
|
+
if (!result.success) return { success: false, reason: 'aplay 命令不可用' };
|
|
96
|
+
if (result.output.includes('no soundcards') || result.output.includes('no devices')) {
|
|
97
|
+
return { success: false, reason: '没有音频设备' };
|
|
78
98
|
}
|
|
99
|
+
return { success: true, devices: result.output };
|
|
79
100
|
}
|
|
80
101
|
|
|
81
102
|
async function main() {
|
|
82
|
-
console.log('
|
|
83
|
-
console.log('====================');
|
|
103
|
+
console.log('=== 音频环境检测与安装脚本 ===');
|
|
84
104
|
console.log(`平台: ${platform}${isWSL ? ' (WSL)' : ''}`);
|
|
85
105
|
console.log('');
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
success
|
|
92
|
-
|
|
93
|
-
|
|
106
|
+
|
|
107
|
+
// 步骤1: 检测 alsa
|
|
108
|
+
log.info('检测 alsa...');
|
|
109
|
+
const alsa = checkAlsa();
|
|
110
|
+
if (alsa.available) {
|
|
111
|
+
log.success(`alsa 可用: ${alsa.command}`);
|
|
112
|
+
const test = testAlsaPlayback();
|
|
113
|
+
if (test.success) {
|
|
114
|
+
log.success('alsa 播放设备检测通过:');
|
|
115
|
+
console.log(test.devices);
|
|
116
|
+
log.success('=== 音频环境就绪 ===');
|
|
117
|
+
process.exit(0);
|
|
118
|
+
} else {
|
|
119
|
+
log.warn(`alsa 测试失败: ${test.reason}`);
|
|
120
|
+
}
|
|
94
121
|
} else {
|
|
95
|
-
log.
|
|
122
|
+
log.warn('alsa 未安装');
|
|
96
123
|
}
|
|
97
124
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
log.error('
|
|
103
|
-
log.error('PortAudio 安装失败,请手动安装:');
|
|
104
|
-
log.error('========================================');
|
|
105
|
-
if (platform === 'darwin') {
|
|
106
|
-
log.error(' brew install portaudio');
|
|
107
|
-
} else if (isWSL) {
|
|
108
|
-
log.error(' sudo apt-get install -y libportaudio-dev portaudio');
|
|
109
|
-
} else if (platform === 'win32') {
|
|
110
|
-
log.error(' choco install portaudio');
|
|
111
|
-
log.error(' 或下载: https://www.portaudio.com/download.html');
|
|
112
|
-
}
|
|
125
|
+
// 步骤2: 安装 alsa-utils
|
|
126
|
+
log.info('安装 alsa-utils...');
|
|
127
|
+
const installed = await installAlsaUtils();
|
|
128
|
+
if (!installed) {
|
|
129
|
+
log.error('alsa-utils 安装失败');
|
|
113
130
|
process.exit(1);
|
|
114
131
|
}
|
|
132
|
+
log.success('alsa-utils 安装成功');
|
|
133
|
+
|
|
134
|
+
// 步骤3: 重新检测
|
|
135
|
+
const alsa2 = checkAlsa();
|
|
136
|
+
if (alsa2.available) {
|
|
137
|
+
const test = testAlsaPlayback();
|
|
138
|
+
if (test.success) {
|
|
139
|
+
log.success('alsa 播放设备检测通过:');
|
|
140
|
+
console.log(test.devices);
|
|
141
|
+
log.success('=== 音频环境就绪 ===');
|
|
142
|
+
process.exit(0);
|
|
143
|
+
} else {
|
|
144
|
+
log.warn(`检测到 alsa 但无播放设备: ${test.reason}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// 步骤4: WSL 安装 PortAudio
|
|
149
|
+
if (isWSL) {
|
|
150
|
+
log.info('安装 libportaudio-dev...');
|
|
151
|
+
await installPortAudioDev();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 最终检测
|
|
155
|
+
const alsa3 = checkAlsa();
|
|
156
|
+
if (alsa3.available) {
|
|
157
|
+
const test = testAlsaPlayback();
|
|
158
|
+
if (test.success) {
|
|
159
|
+
log.success('=== 音频环境就绪 ===');
|
|
160
|
+
process.exit(0);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
log.error('=== 无法配置音频环境 ===');
|
|
165
|
+
if (isWSL) {
|
|
166
|
+
log.error('WSL 没有音频设备');
|
|
167
|
+
log.error('方案: 配置 Windows 音频转发或手动安装音频驱动');
|
|
168
|
+
}
|
|
169
|
+
process.exit(1);
|
|
115
170
|
}
|
|
116
171
|
|
|
117
172
|
main();
|