@oadank/dsh-input-tools 0.3.17 → 0.3.18

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.
Files changed (2) hide show
  1. package/lib/index.js +34 -14
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -51,6 +51,23 @@ const VOICE_DESIGN_SAMPLE_KEYS = ['asmr', 'docu', 'elder']
51
51
  // [2026-08-22] AI 自动模式的年龄感 6 档(用户实时可改,禁止自由文本)
52
52
  const AI_AGE_LABELS = { infant: '婴儿感', child: '幼儿感', teen: '少年感', young: '青年感', middle: '中年感', old: '老年感' }
53
53
 
54
+ // [2026-08-22] 年龄×性别 → 无歧义身份短语(XDN 实测: "老年感+女孩"分维度拼接自相矛盾,
55
+ // "女孩"是中心词→年龄被降级→萝莉化;且"忽略性别/年龄"注把"沙哑/苍老"等最强质感词删了)。
56
+ // 改为"老年女性/小女孩/少女"这类中心词明确的合并短语,年龄不会再被降级。
57
+ function ageGenderIdentity(ageKey, genderKey) {
58
+ const male = genderKey === 'male'
59
+ const female = genderKey === 'female'
60
+ switch (ageKey) {
61
+ case 'infant': return male ? '男婴' : female ? '女婴' : '婴儿'
62
+ case 'child': return male ? '小男孩' : female ? '小女孩' : '小孩'
63
+ case 'teen': return male ? '少年' : female ? '少女' : '少年'
64
+ case 'young': return male ? '青年男性' : female ? '青年女性' : '青年人'
65
+ case 'middle': return male ? '中年男性' : female ? '中年女性' : '中年人'
66
+ case 'old': return male ? '老年男性' : female ? '老年女性' : '老年人'
67
+ default: return male ? '男性' : female ? '女性' : ''
68
+ }
69
+ }
70
+
54
71
  let bundledInitDone = false
55
72
  /** 首次加载把自带素材落地到 DSH_HOME:克隆样本 mp3 拷贝 + 首次安装自动注册小团团。 */
56
73
  async function ensureBundledAssets(config, parsed) {
@@ -384,25 +401,28 @@ async function synthesizeXiaomiVoiceDesign(text, cfg, globalCfg, voiceDesc, over
384
401
  const vdMode = cfg?.mode
385
402
  let desc = (voiceDesc ?? '').trim()
386
403
  if (vdMode === 'ai') {
387
- // [2026-08-22] AI 模式:身份一律以用户实时配置的锚点为准(锁定项),AI 的 voiceDesc
388
- // 只作为"语气/情绪要求"接在后面——AI 偷懒不读设置/写错身份也影响不到,必须按设置执行。
389
- const g = cfg?.aiGender === 'male' ? '男孩' : cfg?.aiGender === 'female' ? '女孩' : ''
390
- const a = AI_AGE_LABELS[cfg?.aiAge] ?? ''
404
+ // [2026-08-22] AI 模式:身份一律以用户实时配置的锚点为准(锁定项)。
405
+ // 修复(XDN 实测): ①"老年感+女孩"分维度拼接→身份自相矛盾(模型选"女孩"→萝莉化),
406
+ // 改 ageGenderIdentity 合并成"老年女性/小女孩/少女"等无歧义短语;
407
+ // ②"性别/年龄表述忽略"注把 AI 写的"沙哑/苍老/低沉"等最强质感词删了,
408
+ // 改为只锁定性别/年龄, 允许情绪与音色质感词保留并强化。
409
+ const gKey = cfg?.aiGender === 'male' ? 'male' : cfg?.aiGender === 'female' ? 'female' : ''
410
+ const aKey = AI_AGE_LABELS[cfg?.aiAge] !== undefined ? cfg.aiAge : ''
411
+ const identity = ageGenderIdentity(aKey, gKey)
391
412
  const lockG = cfg?.lockGender === true
392
413
  const lockA = cfg?.lockAge === true
393
414
  const lockT = cfg?.lockTimbre === true
394
- const identityParts = []
395
- if (lockA && a !== '') identityParts.push(a)
396
- if (lockG && g !== '') identityParts.push(g)
415
+ const gLabel = gKey === 'male' ? '男' : gKey === 'female' ? '女' : ''
416
+ const aLabel = AI_AGE_LABELS[aKey] ?? ''
397
417
  const anchorText = [
398
- lockG ? '性别固定为' + (g !== '' ? g : '每次一致') : '',
399
- lockA ? '年龄感固定为' + (a !== '' ? a : '每次一致') : '',
418
+ lockG ? '性别固定为' + (gLabel !== '' ? gLabel : '每次一致') : '',
419
+ lockA ? '年龄感固定为' + (aLabel !== '' ? aLabel : '每次一致') : '',
400
420
  lockT ? '音色质感保持稳定' : '',
401
421
  ].filter(Boolean).join('、')
402
- if (identityParts.length > 0 || anchorText !== '') {
403
- desc = '一位' + identityParts.join('') + '的声音(身份硬性要求:' + (anchorText !== '' ? anchorText : '按上述身份')
404
- + ';若与其他描述冲突,一律以本身份为准)。'
405
- + (desc !== '' ? '语气/情绪要求:' + desc + '(其中提到的性别/年龄表述忽略,以身份为准)'
422
+ if (identity !== '' || anchorText !== '') {
423
+ desc = (identity !== '' ? '一位' + identity + '的声音(身份硬性要求:' + (anchorText !== '' ? anchorText : '按上述身份')
424
+ + ';若与其他描述冲突,一律以本身份为准)。' : '')
425
+ + (desc !== '' ? '语气/情绪要求:' + desc + '(性别/年龄以身份为准;音色质感与语气情绪按本描述执行——如"沙哑、苍老、低沉、气声"等质感词应保留并强化)。'
406
426
  : '语气情绪要饱满生动:像真人一样带喜怒哀乐、笑音、撒娇或急切等起伏,禁止平淡。')
407
427
  } else if (desc === '') {
408
428
  desc = '语气情绪要饱满生动:像真人一样带喜怒哀乐、笑音、撒娇或急切等起伏,禁止平淡。'
@@ -1382,7 +1402,7 @@ async function apply(ctx) {
1382
1402
  + '③ 写语速节奏(快/慢/沉稳)和情绪底色(高亢/松弛/温软/克制);④ 可加风格锚点(拍卖师/纪录片旁白/电台主播)和辨识度小癖好(字尾带颤音等);'
1383
1403
  + '⑤ 一到两句话白描,不分段,不写场景/动作/真实演员名。'
1384
1404
  + '模式以 voice_config 返回的 voiceDesign.mode 为准:「交给 AI 自动发挥(ai)」时身份由系统按用户锚点(genderValue=女/男、ageValue=婴儿感~老年感、timbre)锁定,'
1385
- + '你只需按对话情境写"情绪/语气/语速表演指令"(如"带笑音、尾音上挑、语速放慢"),不得写与锚点冲突的性别/年龄;'
1405
+ + '你只需按对话情境写"情绪/语气/语速/音色质感表演指令"(如"带笑音、尾音上挑、语速放慢、沙哑低沉"),不得写与锚点冲突的性别/年龄;'
1386
1406
  + 'voice_config 返回的 context 字段是「自定义音色描述」模式用的,AI 模式下禁止使用或复述它。'
1387
1407
  + '「官方示例/自定义音色描述」模式:底嗓固定为 voice_config 的 voiceDesign.context,voiceDesc 只作为情绪/风格叠加在底嗓后面(不改变底嗓身份);'
1388
1408
  + '只有用户明确要求"换一种完全不同的声音"时才传 overrideVoice=true 整体替换底嗓。'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oadank/dsh-input-tools",
3
- "version": "0.3.17",
3
+ "version": "0.3.18",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "lib/index.js",