@oxiaom/adoremix 1.0.56 → 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.
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxiaom/adoremix",
3
- "version": "1.0.56",
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"
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,开机自启');
@@ -471,4 +471,66 @@ async function status(opts) {
471
471
  }
472
472
  }
473
473
 
474
- 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
+ }