Files
SFX-Library-Automation/translate_sfx.py
2025-11-20 14:28:23 +08:00

168 lines
5.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import requests
import json
import sys
# ================= 配置区域 =================
# 你的 Ollama 模型名称
MODEL_NAME = "gemma3:12b"
# Ollama API 地址
OLLAMA_API_URL = "http://localhost:11434/api/chat"
# 需要处理的文件后缀
EXTENSIONS = ('.wav', '.mp3', '.flac', '.aiff', '.ogg', '.m4a')
# 翻译缓存 (保留在内存中,处理下一个文件夹时如果有重复词,速度会飞快)
translation_cache = {}
# ===========================================
def get_translation_via_requests(filename, model):
"""使用 requests 直接调用 Ollama 接口"""
if filename in translation_cache:
return translation_cache[filename]
system_prompt = (
"You are a professional translator for Audio Sound Effects (SFX) libraries. "
"Your task is to translate English filenames into concise Simplified Chinese. "
"Rules: 1. Only output the Chinese translation. 2. Do not explain. 3. Keep technical terms accurate (e.g., 'Whoosh' -> '嗖嗖声')."
)
user_prompt = f'Translate this filename: "{filename}"'
payload = {
"model": model,
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
"stream": False,
"options": {
"temperature": 0.1
}
}
try:
response = requests.post(OLLAMA_API_URL, json=payload, timeout=60)
response.raise_for_status()
result_json = response.json()
translated_text = result_json['message']['content'].strip()
invalid_chars = '<>:"/\|?*\'"“”。'
for char in invalid_chars:
translated_text = translated_text.replace(char, '')
if not translated_text:
return None
translation_cache[filename] = translated_text
return translated_text
except Exception as e:
# 这里不打印网络报错细节以免刷屏只返回None跳过
return None
def is_already_chinese(text):
"""检查文件名里是否已经包含中文"""
for char in text:
if '\u4e00' <= char <= '\u9fff':
return True
return False
def process_folder():
"""单个文件夹处理流程"""
# 1. 获取路径
while True:
target_dir = input("\n请拖入(或粘贴)你要处理的【文件夹路径】: ").strip()
target_dir = target_dir.strip('"').strip("'") # 去除引号
if os.path.exists(target_dir):
break
else:
print("❌ 错误:路径不存在,请重新输入。")
# 2. 选择模式
print("\n请选择模式:")
print("1. 仅模拟 (只打印不修改)")
print("2. 直接执行 (修改文件名)")
mode_choice = input("请输入数字 (默认1): ").strip()
is_dry_run = True
if mode_choice == '2':
is_dry_run = False
print("\n>>> ⚠️ 警告:即将开始【真实修改】文件名! <<<")
else:
print("\n>>> 🛡️ 模拟模式:不会修改任何文件 <<<")
# 3. 扫描与处理
count = 0
success_count = 0
print(f"\n正在扫描目录: {target_dir} ...\n")
for root, dirs, files in os.walk(target_dir):
for file in files:
if file.lower().endswith(EXTENSIONS):
old_name_with_ext = file
name_part, ext_part = os.path.splitext(old_name_with_ext)
if is_already_chinese(name_part):
continue
count += 1
# 动态显示进度
print(f"[{count}] 正在思考: {name_part} ...", end="\r")
cn_name = get_translation_via_requests(name_part, MODEL_NAME)
padding = " " * 30 # 用于覆盖之前的打印内容
if cn_name:
# 格式:【中文】英文.wav
new_name_with_ext = f"{cn_name}{old_name_with_ext}"
old_path = os.path.join(root, old_name_with_ext)
new_path = os.path.join(root, new_name_with_ext)
if is_dry_run:
print(f"[模拟] {name_part} -> 【{cn_name}{padding}")
else:
try:
os.rename(old_path, new_path)
print(f"[成功] {new_name_with_ext}{padding}")
success_count += 1
except Exception as e:
print(f"[失败] {e}{padding}")
else:
# 如果翻译失败,不需要刷屏,静默跳过或简单提示
pass
print("\n" + "-"*30)
print(f"✅ 本次任务完成!扫描: {count} 个,成功重命名: {success_count} 个。")
def main():
print("=============================================")
print(" 音效文件名智能翻译工具 (Gemma + Ollama)")
print("=============================================")
print(f"当前模型: {MODEL_NAME}")
while True:
process_folder()
# 循环询问
print("\n" + "="*30)
choice = input("🔄 是否继续处理其他目录?(y/n): ").strip().lower()
if choice == 'y':
print("\n" * 2) # 空两行,视觉上分隔
continue
else:
print("\n👋 再见!")
break
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\n用户强制停止,程序退出。")