#!/usr/bin/env python3 # -*- coding: utf-8 -*- """analyze-model-lang-matrix.py — 解析 sysvoices-dom,生成 model × lang × voice 矩阵""" import re, json, sys from collections import defaultdict PATH = r"C:/Users/caoyg/AppData/Local/Temp/sysvoices-dom.txt" text = open(PATH, encoding='utf-8').read() # 阿里云页面有 4 个章节(每个章节都重复了"本页导读"导航,所以取第一个匹配即可) SECTIONS = [ ('cosyvoice-v3-flash', r'cosyvoice-v3-flash\s*音色列表'), ('cosyvoice-v3-plus', r'cosyvoice-v3-plus\s*音色列表'), ('cosyvoice-v2', r'cosyvoice-v2\s*音色列表'), ('cosyvoice-v1', r'cosyvoice-v1\s*音色列表'), ] # 取每个模型标题第一个出现的位置(跳过右侧栏的目录) positions = [] for model, pat in SECTIONS: matches = list(re.finditer(pat, text)) # 选最小位置的(主体内容不是侧栏目录) if matches: m = min(matches, key=lambda x: x.start()) positions.append((m.start(), model)) positions.sort() all_voices = defaultdict(list) all_voices_per_model = {} for i, (start, model) in enumerate(positions): end = positions[i + 1][0] if i + 1 < len(positions) else len(text) section = text[start:end] voices = [] pos = [mm.start() for mm in re.finditer(r'名称[::]\s*.+?\n', section)] pos.append(len(section)) for j in range(len(pos) - 1): chunk = section[pos[j]:pos[j + 1]] v = {} n = re.search(r'^名称[::]\s*(.+?)\s*$', chunk, re.MULTILINE) if n: v['name'] = n.group(1).strip() vp = re.search(r'voice参数[::]\s*(\w+)', chunk) if vp: v['voice_id'] = vp.group(1) t = re.search(r'特质[::]\s*(.+?)\n', chunk) if t: v['desc'] = t.group(1).strip()[:80] a = re.search(r'年龄[::]\s*(.+?)\n', chunk) if a: v['age'] = a.group(1).strip() l = re.search(r'语言[::]\s*(.+?)\n', chunk) if l: v['lang'] = l.group(1).strip()[:60] v['instruct'] = '支持' if 'Instruct:支持' in chunk else '不支持' if 'Instruct:不支持' in chunk else '?' if v.get('name'): voices.append(v) all_voices_per_model[model] = voices # 输出汇总 sys.stdout.reconfigure(encoding='utf-8') total_voices = 0 all_langs = set() for model, voices in all_voices_per_model.items(): print(f'\n=== {model}: {len(voices)} 个音色 ===') lang_count = defaultdict(int) for v in voices: lang = v.get('lang', '?') for l in re.split('[、,]', lang): l = l.strip() if not l: continue all_langs.add(l) lang_count[l] += 1 for l, c in sorted(lang_count.items(), key=lambda x: (-x[1], x[0])): print(f' {l}: {c}') total_voices += len(voices) print(f'\n========== 总览 ==========') print(f'总音色数: {total_voices}') print(f'涉及语种 ({len(all_langs)} 种):') for l in sorted(all_langs): print(f' - {l}') # 写 JSON 给前端用 with open(r"C:/Users/caoyg/AppData/Local/Temp/alicloud-voices-matrix.json", 'w', encoding='utf-8') as f: json.dump(all_voices_per_model, f, ensure_ascii=False, indent=2) print(f'\nJSON: {len(all_voices_per_model)} 个模型 → C:/Users/caoyg/AppData/Local/Temp/alicloud-voices-matrix.json')