@mingxy/ocosay 1.1.7 → 1.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/core/backends/index.js +7 -3
- package/dist/core/backends/naudiodon-backend.js +8 -0
- package/dist/package.json +1 -1
- package/dist/plugin.js +6428 -6335
- package/package.json +1 -1
- package/scripts/install-portaudio.cjs +131 -76
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();
|