41f653b672
- 所有对外称呼从 QQ 改为 OBv11(注释/提示词/日志/配置项) - 新增 PlatformFormat 结构体,统一管理平台消息标记格式 - defaultPlatformFormats() 注册表替代硬编码 qqTargetRe - extractProactiveMessage 改为 Thinker 方法,遍历格式注册表匹配 - 配置项重命名: QQ_BOT_PORT → OBV11_BOT_PORT, QQBotPort → OBv11BotPort - 标记格式: 【QQ群聊】→【OBv11群聊】、【QQ私聊】→【OBv11私聊】 Co-Authored-By: Claude <noreply@anthropic.com>
143 lines
4.3 KiB
Python
143 lines
4.3 KiB
Python
#!/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()
|