@oxiaom/adoremix 1.0.55 → 1.0.57
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/audio8-assets/audio8-tts.tgz +0 -0
- package/package.json +3 -2
- package/src/cli.js +27 -0
- package/tts/providers/audio8.js +102 -24
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxiaom/adoremix",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.57",
|
|
4
4
|
"description": "AdoreMix broadcast server - cross-platform installer, runner and service manager",
|
|
5
5
|
"bin": {
|
|
6
6
|
"adoremix": "./bin/adoremix.js"
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
"templates",
|
|
42
42
|
"tts",
|
|
43
43
|
"webui",
|
|
44
|
-
"config-manager"
|
|
44
|
+
"config-manager",
|
|
45
|
+
"audio8-assets"
|
|
45
46
|
],
|
|
46
47
|
"keywords": [
|
|
47
48
|
"adoremix",
|
package/src/cli.js
CHANGED
|
@@ -510,6 +510,33 @@ function buildProgram() {
|
|
|
510
510
|
}
|
|
511
511
|
});
|
|
512
512
|
|
|
513
|
+
audio8
|
|
514
|
+
.command('fetch-model [url]')
|
|
515
|
+
.description('单独下载 Audio8 TTS 模型(572MB 0.1B INT8)到 /root/audio8/model/,与 audio8 install 解耦避免 install 卡住')
|
|
516
|
+
.action(async (url) => {
|
|
517
|
+
const mod = require('../tts/providers/audio8');
|
|
518
|
+
try {
|
|
519
|
+
process.exitCode = await mod.fetchModel({ url });
|
|
520
|
+
} catch (e) {
|
|
521
|
+
logger.error(e.message);
|
|
522
|
+
process.exitCode = 1;
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
// 顶级命令(不依赖 audio8 group)
|
|
527
|
+
program
|
|
528
|
+
.command('audio8-fetch-model [url]')
|
|
529
|
+
.description('下载 Audio8 TTS 模型(单独使用,不依赖 audio8 install)')
|
|
530
|
+
.action(async (url) => {
|
|
531
|
+
const mod = require('../tts/providers/audio8');
|
|
532
|
+
try {
|
|
533
|
+
process.exitCode = await mod.fetchModel({ url });
|
|
534
|
+
} catch (e) {
|
|
535
|
+
logger.error(e.message);
|
|
536
|
+
process.exitCode = 1;
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
|
|
513
540
|
const cfgmgr = program
|
|
514
541
|
.command('config-manager')
|
|
515
542
|
.description('设备配置管理 UI(配置 IP / 修改 config.ini / 查看日志),端口 9877,开机自启');
|
package/tts/providers/audio8.js
CHANGED
|
@@ -296,7 +296,8 @@ function install(opts) {
|
|
|
296
296
|
// 检查 config.ini 是否有预托管模型(audio8_model_dir)
|
|
297
297
|
let modelDir = '';
|
|
298
298
|
try {
|
|
299
|
-
|
|
299
|
+
// 从主包内置 src/config 读取(避免 tts/src/config 这种错误路径)
|
|
300
|
+
const cfg = require(path.join(__dirname, '..', '..', 'src', 'config'));
|
|
300
301
|
const wd = opts.workdir || process.env.ADOREMIX_WORKDIR || path.join(os.homedir(), '.local', 'share', 'adoremix');
|
|
301
302
|
modelDir = cfg.getConfigValue(wd, 'TTS.audio8_model_dir') || '';
|
|
302
303
|
} catch (e) {}
|
|
@@ -311,30 +312,45 @@ function install(opts) {
|
|
|
311
312
|
}
|
|
312
313
|
}
|
|
313
314
|
|
|
314
|
-
// 拉 Audio8_TTS
|
|
315
|
-
const MIRRORS = [
|
|
316
|
-
AUDIO8_REPO, // 官方 https
|
|
317
|
-
'https://ghproxy.cn/https://github.com/Audio8-AI/Audio8_TTS.git', // 国内代理
|
|
318
|
-
'https://hub.fastgit.xyz/Audio8-AI/Audio8_TTS.git' // fastgit 镜像
|
|
319
|
-
];
|
|
315
|
+
// 拉 Audio8_TTS 源码:先试内置 tarball(主包 audio8-assets/audio8-tts.tgz,离线),再 git 镜像,最后 codeload
|
|
320
316
|
let cloned = false;
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
317
|
+
// 1) 主包内置 tarball(最稳,完全离线)
|
|
318
|
+
const BUNDLED_TARBALL = path.join(__dirname, '..', '..', 'audio8-assets', 'audio8-tts.tgz');
|
|
319
|
+
if (fs.existsSync(BUNDLED_TARBALL)) {
|
|
320
|
+
try {
|
|
321
|
+
logger.log('=== 使用主包内置 Audio8_TTS tarball(离线) ===');
|
|
322
|
+
execSync(`rm -rf ~/audio8 && mkdir -p ~/audio8 && tar xzf "${BUNDLED_TARBALL}" --strip-components=1 -C ~/audio8 && ls ~/audio8 | head -3`, { stdio: 'inherit', shell: '/bin/bash' });
|
|
323
|
+
cloned = true;
|
|
324
|
+
} catch (e) {
|
|
325
|
+
logger.warn('内置 tarball 解压失败:' + e.message);
|
|
326
|
+
}
|
|
327
|
+
} else {
|
|
328
|
+
logger.warn(`主包内置 tarball 不存在:${BUNDLED_TARBALL}`);
|
|
329
|
+
}
|
|
330
|
+
// 2) Git 镜像(fallback)
|
|
331
|
+
if (!cloned) {
|
|
332
|
+
const MIRRORS = [
|
|
333
|
+
AUDIO8_REPO,
|
|
334
|
+
'https://ghproxy.cn/https://github.com/Audio8-AI/Audio8_TTS.git',
|
|
335
|
+
'https://hub.fastgit.xyz/Audio8-AI/Audio8_TTS.git'
|
|
336
|
+
];
|
|
337
|
+
for (let attempt = 1; attempt <= 2 && !cloned; attempt++) {
|
|
338
|
+
for (const url of MIRRORS) {
|
|
339
|
+
try {
|
|
340
|
+
logger.log(`=== 克隆 Audio8_TTS(第 ${attempt} 次): ${url} ===`);
|
|
341
|
+
execSync(`rm -rf ~/audio8_temp && git clone --depth=1 "${url}" ~/audio8_temp 2>&1 | tail -3`, { stdio: 'inherit', shell: '/bin/bash' });
|
|
342
|
+
execSync(`bash -c "cd ~/audio8_temp && (shopt -s dotglob; mv -- * ~/audio8/ 2>/dev/null || true)"`, { stdio: 'inherit', shell: '/bin/bash' });
|
|
343
|
+
execSync('rm -rf ~/audio8_temp', { stdio: 'ignore', shell: '/bin/bash' });
|
|
344
|
+
cloned = true;
|
|
345
|
+
break;
|
|
346
|
+
} catch (e) {
|
|
347
|
+
logger.warn(`克隆失败:${String(e.message).slice(0, 100)}`);
|
|
348
|
+
}
|
|
332
349
|
}
|
|
350
|
+
if (!cloned) execSync('sleep 5', { stdio: 'ignore', shell: '/bin/bash' });
|
|
333
351
|
}
|
|
334
|
-
if (cloned) break;
|
|
335
|
-
execSync('sleep 5', { stdio: 'ignore', shell: '/bin/bash' });
|
|
336
352
|
}
|
|
337
|
-
//
|
|
353
|
+
// 3) codeload tarball(最后备选)
|
|
338
354
|
if (!cloned) {
|
|
339
355
|
try {
|
|
340
356
|
logger.log('=== 备选:codeload github tarball ===');
|
|
@@ -345,8 +361,8 @@ function install(opts) {
|
|
|
345
361
|
}
|
|
346
362
|
}
|
|
347
363
|
if (!cloned) {
|
|
348
|
-
logger.error('
|
|
349
|
-
logger.warn('解决:手动在 ~/audio8 下放好 Audio8_TTS 源码再重试 install
|
|
364
|
+
logger.error('所有源都失败,无法获取 Audio8_TTS 源码');
|
|
365
|
+
logger.warn('解决:手动在 ~/audio8 下放好 Audio8_TTS 源码再重试 install');
|
|
350
366
|
return 1;
|
|
351
367
|
}
|
|
352
368
|
|
|
@@ -455,4 +471,66 @@ async function status(opts) {
|
|
|
455
471
|
}
|
|
456
472
|
}
|
|
457
473
|
|
|
458
|
-
module.exports = { synthesize, checkDeps, VOICES, DEFAULT_BASE_URL, install, uninstall, status };
|
|
474
|
+
module.exports = { synthesize, checkDeps, VOICES, DEFAULT_BASE_URL, install, uninstall, status, fetchModel };
|
|
475
|
+
|
|
476
|
+
// === fetchModel: 单独下载 Audio8 TTS 模型 ===
|
|
477
|
+
// 默认 URL:HuggingFace 0.1B INT8(~572MB,公司网差可改为自家 OSS 链接)
|
|
478
|
+
const MODEL_DEFAULT_URL = process.env.ADOREMIX_AUDIO8_MODEL_URL
|
|
479
|
+
|| 'https://huggingface.co/Audio8/audio8-TTS-0.1B-ONNX-INT8/resolve/main/';
|
|
480
|
+
// 模型要的所有文件(必须下完整,Audio8 启动会校验)
|
|
481
|
+
const MODEL_FILES = [
|
|
482
|
+
'config.json', 'tokenizer.json', 'tokenizer_config.json', 'special_tokens_map.json',
|
|
483
|
+
'model.onnx', 'model.onnx.data'
|
|
484
|
+
];
|
|
485
|
+
|
|
486
|
+
async function downloadOne(baseUrl, file, targetDir, log) {
|
|
487
|
+
const url = baseUrl.replace(/\/$/, '') + '/' + file;
|
|
488
|
+
const target = path.join(targetDir, file);
|
|
489
|
+
return new Promise((resolve, reject) => {
|
|
490
|
+
const lib = url.startsWith('https:') ? require('https') : require('http');
|
|
491
|
+
const req = lib.get(url, response => {
|
|
492
|
+
if (response.statusCode !== 200) {
|
|
493
|
+
response.resume();
|
|
494
|
+
return reject(new Error(file + ' HTTP ' + response.statusCode));
|
|
495
|
+
}
|
|
496
|
+
const ws = require('fs').createWriteStream(target);
|
|
497
|
+
response.pipe(ws);
|
|
498
|
+
ws.on('finish', () => ws.close(() => resolve(file)));
|
|
499
|
+
ws.on('error', reject);
|
|
500
|
+
});
|
|
501
|
+
req.on('error', reject);
|
|
502
|
+
req.setTimeout(600000, () => req.destroy(new Error(file + ' timeout (10min)')));
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
async function fetchModel(opts) {
|
|
507
|
+
opts = opts || {};
|
|
508
|
+
const targetDir = process.env.ADOREMIX_AUDIO8_MODEL_DIR || '/root/audio8/model';
|
|
509
|
+
const baseUrl = opts.url || MODEL_DEFAULT_URL;
|
|
510
|
+
const log = (m) => console.log(m);
|
|
511
|
+
|
|
512
|
+
log('Audio8 模型下载 → ' + targetDir);
|
|
513
|
+
log('源 URL: ' + baseUrl);
|
|
514
|
+
if (!baseUrl.endsWith('/') && !baseUrl.includes('resolve/main')) {
|
|
515
|
+
log(' (URL 应以 /resolve/main/ 结尾,自动补)');
|
|
516
|
+
}
|
|
517
|
+
require('fs').mkdirSync(targetDir, { recursive: true });
|
|
518
|
+
|
|
519
|
+
let ok = 0, fail = 0;
|
|
520
|
+
for (const f of MODEL_FILES) {
|
|
521
|
+
try {
|
|
522
|
+
log(' → ' + f + ' ...');
|
|
523
|
+
await downloadOne(baseUrl, targetDir, f, log);
|
|
524
|
+
ok++;
|
|
525
|
+
} catch (e) {
|
|
526
|
+
log(' ✗ ' + f + ' 失败: ' + e.message);
|
|
527
|
+
fail++;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
if (fail > 0) {
|
|
531
|
+
log('失败 ' + fail + ' 个,模型可能不完整(重启 Audio8 会报错)');
|
|
532
|
+
return 1;
|
|
533
|
+
}
|
|
534
|
+
log('✓ Audio8 模型就绪(' + ok + ' 个文件):' + targetDir);
|
|
535
|
+
return 0;
|
|
536
|
+
}
|