TNOT commited on
Commit
ae5fcb7
·
1 Parent(s): d49edbe

fix: 使用 micromamba 安装 MFA

Browse files
Files changed (2) hide show
  1. app.py +53 -68
  2. src/mfa_runner.py +18 -59
app.py CHANGED
@@ -88,94 +88,79 @@ def setup_environment():
88
 
89
 
90
  def setup_mfa_linux():
91
- """Linux 环境下安装 MFA"""
92
  import shutil
93
 
94
  def verify_mfa_working():
95
  """验证 MFA 是否能正常工作(包括 kalpy 依赖)"""
96
  try:
97
  result = subprocess.run(
98
- [sys.executable, "-c", "from _kalpy.gmm import AccumAmDiagGmm; print('ok')"],
99
  capture_output=True,
100
  text=True,
101
- timeout=10
102
  )
103
- return result.returncode == 0 and "ok" in result.stdout
104
  except Exception:
105
  return False
106
 
107
- # 检查 mfa 是否已可用且能正常工作
108
- mfa_path = shutil.which("mfa")
109
- if mfa_path:
110
- if verify_mfa_working():
111
- logger.info("MFA 已安装且工作正常 (系统路径)")
112
- return
113
- else:
114
- logger.warning("MFA 已安装但 kalpy 模块缺失,需要修复...")
115
 
116
- # 检查是否以通过 python -m 调用
117
- try:
118
- result = subprocess.run(
119
- [sys.executable, "-m", "montreal_forced_aligner", "version"],
120
- capture_output=True,
121
- text=True,
122
- timeout=30
123
- )
124
- if result.returncode == 0 and verify_mfa_working():
125
- logger.info(f"MFA 已安装 (Python 模块): {result.stdout.strip()}")
126
- return
127
- except Exception:
128
- pass
129
 
130
- logger.info("正在安装 MFA 及其依赖...")
 
 
 
131
 
132
  try:
133
- # 安装 kalpyMFA 3.x 的核心依赖
134
- logger.info("安装 kalpy...")
135
- subprocess.run(
136
- [sys.executable, "-m", "pip", "install", "kalpy"],
137
- check=True,
138
- capture_output=True,
139
- text=True
140
- )
141
- logger.info("kalpy 安装完成")
 
 
142
 
143
- # 安装 MFA
144
- logger.info("安装 montreal-forced-aligner...")
145
- result = subprocess.run(
146
- [sys.executable, "-m", "pip", "install",
147
- "montreal-forced-aligner"],
148
- check=True,
149
- capture_output=True,
150
- text=True
151
- )
152
- logger.info("MFA pip 安装完成")
 
 
 
153
 
154
- # 验证安装
155
- if verify_mfa_working():
156
- verify = subprocess.run(
157
- [sys.executable, "-m", "montreal_forced_aligner", "version"],
158
- capture_output=True,
159
- text=True,
160
- timeout=30
161
- )
162
- if verify.returncode == 0:
163
- logger.info(f"MFA 版本: {verify.stdout.strip()}")
164
- else:
165
- logger.warning("MFA 安装后 kalpy 仍不可用,可能需要重启")
166
 
 
 
167
  except subprocess.CalledProcessError as e:
168
- logger.warning(f"MFA pip 安装失败: {e.stderr if e.stderr else e}")
169
- try:
170
- subprocess.run(
171
- ["conda", "install", "-c", "conda-forge",
172
- "montreal-forced-aligner", "-y"],
173
- check=True,
174
- capture_output=True
175
- )
176
- logger.info("MFA conda 安装完成")
177
- except Exception as e2:
178
- logger.error(f"MFA 安装失败: {e2}")
179
 
180
 
181
  def download_all_models():
 
88
 
89
 
90
  def setup_mfa_linux():
91
+ """Linux 环境下安装 MFA(使用 micromamba)"""
92
  import shutil
93
 
94
  def verify_mfa_working():
95
  """验证 MFA 是否能正常工作(包括 kalpy 依赖)"""
96
  try:
97
  result = subprocess.run(
98
+ ["mfa", "version"],
99
  capture_output=True,
100
  text=True,
101
+ timeout=30
102
  )
103
+ return result.returncode == 0
104
  except Exception:
105
  return False
106
 
107
+ # 检查 mfa 是否已可用
108
+ if shutil.which("mfa") and verify_mfa_working():
109
+ logger.info("MFA 已安装且工作正常")
110
+ return
 
 
 
 
111
 
112
+ logger.info("MFA 用,尝试使用 micromamba 安装...")
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
+ # micromamba 安装路径
115
+ mamba_root = Path("/tmp/micromamba")
116
+ mamba_bin = mamba_root / "bin" / "micromamba"
117
+ mfa_env = mamba_root / "envs" / "mfa"
118
 
119
  try:
120
+ # 1. 安装 micromamba如果不存在
121
+ if not mamba_bin.exists():
122
+ logger.info("下载 micromamba...")
123
+ mamba_root.mkdir(parents=True, exist_ok=True)
124
+
125
+ # 下载并安装 micromamba
126
+ subprocess.run([
127
+ "bash", "-c",
128
+ f'curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj -C {mamba_root} bin/micromamba'
129
+ ], check=True, capture_output=True, timeout=120)
130
+ logger.info("micromamba 下载完成")
131
 
132
+ # 2. 使用 micromamba 创建环境并安装 MFA
133
+ if not (mfa_env / "bin" / "mfa").exists():
134
+ logger.info("使用 micromamba 安装 MFA...")
135
+ env = os.environ.copy()
136
+ env["MAMBA_ROOT_PREFIX"] = str(mamba_root)
137
+
138
+ subprocess.run([
139
+ str(mamba_bin), "create", "-n", "mfa",
140
+ "-c", "conda-forge",
141
+ "montreal-forced-aligner", "kalpy", "kaldi=*=cpu*",
142
+ "-y"
143
+ ], env=env, check=True, capture_output=True, text=True, timeout=600)
144
+ logger.info("MFA 安装完成")
145
 
146
+ # 3. 将 MFA 环境的 bin 目录加入 PATH
147
+ mfa_bin_dir = mfa_env / "bin"
148
+ if mfa_bin_dir.exists():
149
+ os.environ["PATH"] = f"{mfa_bin_dir}:{os.environ.get('PATH', '')}"
150
+ logger.info(f"已将 {mfa_bin_dir} 加入 PATH")
151
+
152
+ # 验证安装
153
+ if verify_mfa_working():
154
+ logger.info("MFA 验证通过")
155
+ else:
156
+ logger.warning("MFA 安装后验证失败")
 
157
 
158
+ except subprocess.TimeoutExpired:
159
+ logger.error("MFA 安装超时")
160
  except subprocess.CalledProcessError as e:
161
+ logger.error(f"MFA 安装失败: {e.stderr[-500:] if e.stderr else e}")
162
+ except Exception as e:
163
+ logger.error(f"MFA 安装异常: {e}")
 
 
 
 
 
 
 
 
164
 
165
 
166
  def download_all_models():
src/mfa_runner.py CHANGED
@@ -32,7 +32,7 @@ def check_mfa_available() -> bool:
32
  """
33
  检查 MFA 是否可用
34
  Windows: 检查外挂 Python 环境
35
- Linux: 检查系统 mfa 命令或 Python 模块,并验证 kalpy 依赖
36
  """
37
  if IS_WINDOWS:
38
  if not MFA_ENGINE_DIR.exists():
@@ -43,46 +43,26 @@ def check_mfa_available() -> bool:
43
  return False
44
  return True
45
  else:
46
- # Linux/macOS: 需要验证 kalpy 依赖是否可用
47
- import sys
48
-
49
- def verify_kalpy():
50
- """验证 kalpy 模块是否可导入"""
51
  try:
52
  result = subprocess.run(
53
- [sys.executable, "-c", "from _kalpy.gmm import AccumAmDiagGmm; print('ok')"],
54
  capture_output=True,
55
  text=True,
56
- timeout=10
57
  )
58
- return result.returncode == 0 and "ok" in result.stdout
59
- except Exception:
60
- return False
61
-
62
- # 先检查 kalpy 是否可用
63
- if not verify_kalpy():
64
- logger.warning("kalpy 模块不可用,MFA 无法正工作")
65
- return False
66
-
67
- # 检查系统 mfa 命令
68
- mfa_path = shutil.which("mfa")
69
- if mfa_path:
70
- logger.info(f"找到系统 MFA: {mfa_path}")
71
- return True
72
-
73
- # 尝试检查 Python 模块方式
74
- try:
75
- result = subprocess.run(
76
- [sys.executable, "-m", "montreal_forced_aligner", "version"],
77
- capture_output=True,
78
- text=True,
79
- timeout=30
80
- )
81
- if result.returncode == 0:
82
- logger.info(f"MFA 可用 (Python 模块): {result.stdout.strip()}")
83
- return True
84
- except Exception as e:
85
- logger.warning(f"MFA Python 模块检查失败: {e}")
86
 
87
  return False
88
 
@@ -91,33 +71,12 @@ def _get_mfa_command() -> list:
91
  """
92
  获取 MFA 命令前缀
93
  Windows: 使用外挂 Python 调用
94
- Linux: 优先使用 Python 模块方式(更可靠),否则使用系统 mfa 命令
95
  """
96
  if IS_WINDOWS:
97
  return [str(MFA_PYTHON), "-m", "montreal_forced_aligner"]
98
  else:
99
- # Linux: 优先使用 Python 模块方式(确保使用当前 Python 环境的依赖)
100
- import sys
101
-
102
- # 检查 Python 模块是否可用
103
- try:
104
- result = subprocess.run(
105
- [sys.executable, "-m", "montreal_forced_aligner", "version"],
106
- capture_output=True,
107
- text=True,
108
- timeout=10
109
- )
110
- if result.returncode == 0:
111
- return [sys.executable, "-m", "montreal_forced_aligner"]
112
- except Exception:
113
- pass
114
-
115
- # 回退到系统命令
116
- if shutil.which("mfa"):
117
- return ["mfa"]
118
-
119
- # 最后尝试 Python 模块(即使上面检查失败,也许运行时能工作)
120
- return [sys.executable, "-m", "montreal_forced_aligner"]
121
 
122
 
123
  def _build_mfa_env() -> dict:
 
32
  """
33
  检查 MFA 是否可用
34
  Windows: 检查外挂 Python 环境
35
+ Linux: 检查 mfa 命令是否可用
36
  """
37
  if IS_WINDOWS:
38
  if not MFA_ENGINE_DIR.exists():
 
43
  return False
44
  return True
45
  else:
46
+ # Linux/macOS: 检查 mfa 命令
47
+ mfa_path = shutil.which("mfa")
48
+ if mfa_path:
49
+ # 验证 mfa 能正常运行
 
50
  try:
51
  result = subprocess.run(
52
+ ["mfa", "version"],
53
  capture_output=True,
54
  text=True,
55
+ timeout=30
56
  )
57
+ if result.returncode == 0:
58
+ logger.info(f"MFA 可用: {result.stdout.strip()}")
59
+ return True
60
+ else:
61
+ logger.warning(f"MFA 命令执行失败: {result.stderr or result.stdout}")
62
+ except Exception as e:
63
+ logger.warning(f"MFA 验证异: {e}")
64
+ else:
65
+ logger.warning("未找到 mfa 命令,请使用 conda/micromamba 安装: conda install -c conda-forge montreal-forced-aligner")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  return False
68
 
 
71
  """
72
  获取 MFA 命令前缀
73
  Windows: 使用外挂 Python 调用
74
+ Linux: 使用系统 mfa 命令
75
  """
76
  if IS_WINDOWS:
77
  return [str(MFA_PYTHON), "-m", "montreal_forced_aligner"]
78
  else:
79
+ return ["mfa"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
 
82
  def _build_mfa_env() -> dict: