#!/usr/bin/env python3 """ 使用 AnimeWwise 引擎无头提取昔涟语音。 不需要 GUI,直接调用 extract.py 的核心逻辑。 """ import os import sys # 添加 AnimeWwise 到路径 AWW_DIR = r"D:\Project\Code\Uni\Cyrene-Voice-Model\tools\AnimeWwise" sys.path.insert(0, AWW_DIR) os.chdir(AWW_DIR) from extract import WwiseExtract # 输入目录 HSR_AUDIO = r"D:\MeowG\Honkai:Star_Rail\StarRail_Data\Persistent\Audio\AudioPackage\Windows\Chinese(PRC)" OUTPUT_DIR = r"D:\Project\Code\Uni\Cyrene-Voice-Model\data\cyrene_extracted" MAP_FILE = "hkrpg.map" print("=" * 60) print("昔涟语音提取 (AnimeWwise Headless)") print("=" * 60) # 1. 初始化提取器 extractor = WwiseExtract() # 2. 加载映射 print("\n[1/4] 加载角色映射...") extractor.load_map(MAP_FILE) # 3. 加载音频文件 print("\n[2/4] 加载 .pck 文件...") pck_files = sorted([ os.path.join(HSR_AUDIO, f) for f in os.listdir(HSR_AUDIO) if f.endswith(".pck") and ("VoBanks" in f or "External_del_3." in f) ]) print(f" 找到 {len(pck_files)} 个目标 .pck 文件") # 进度回调 def progress(data): if data[0] == "total": pct = int(data[1]) if pct % 20 == 0: print(f" 加载进度: {pct:.0f}%") file_structure = extractor.load_folder( _map=MAP_FILE, files=pck_files, diff_path="", base_path=HSR_AUDIO, progress=progress, ) # 4. 搜索昔涟 print("\n[3/4] 搜索昔涟语音...") def search_cyrene(structure, path=""): """递归搜索文件结构中包含昔涟相关名称的文件""" results = [] cyrene_terms = ['cyrene', 'mimi', 'xilian', 'mem', 'de_moi_ge'] # 搜索文件夹 folders = structure.get("folders", {}) for folder_name, folder_content in folders.items(): sub_path = f"{path}/{folder_name}" if path else folder_name results.extend(search_cyrene(folder_content, sub_path)) # 搜索文件 for file_entry in structure.get("files", []): file_name = file_entry[0].lower() file_path = f"{path}/{file_entry[0]}" for term in cyrene_terms: if term in file_name or term in file_path.lower(): results.append((path, file_entry[0], file_entry[1])) break return results matches = search_cyrene(file_structure) print(f" 找到 {len(matches)} 个昔涟相关文件") if len(matches) == 0: print("\n 未匹配到昔涟,显示所有顶层目录结构:") folders = file_structure.get("folders", {}) for name in sorted(folders.keys()): count = len(folders[name].get("files", [])) # 递归统计 def count_all(s): total = len(s.get("files", [])) for v in s.get("folders", {}).values(): total += count_all(v) return total total = count_all(folders[name]) print(f" {name}/ ({total} files)") # 也搜一下其他可能的名称 print("\n 搜索所有包含'voice'的路径...") voice_matches = search_cyrene(file_structure) # 换个方式搜 def search_all(structure, prefix=""): for folder_name, folder_content in structure.get("folders", {}).items(): sub = f"{prefix}/{folder_name}" if prefix else folder_name sub_lower = sub.lower() if any(t in sub_lower for t in ['voice', 'char', 'npc', 'player', 'avatar']): print(f" {sub}/") search_all(folder_content, sub) search_all(file_structure) else: for path, name, meta in matches[:30]: print(f" {path}/{name}") # 5. 提取 if matches: print(f"\n[4/4] 提取 {len(matches)} 个文件到 {OUTPUT_DIR}...") output_files = [] for path, name, meta in matches: output_files.append({ "path": path.split("/") if path else [], "name": name, "source": meta["source"], "offset": meta["offset"], "size": meta["size"], "original_name": meta["original_name"], }) extractor.extract_files( _input=HSR_AUDIO, files=output_files, output=OUTPUT_DIR, _format="wav", progress=progress, ) print(f"\n完成!文件保存在 {OUTPUT_DIR}") else: print("\n未找到昔涟语音。可能需要用 AnimeWwise GUI 手动浏览文件结构。") extractor.reset()