@ww_nero/media 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -279,7 +279,26 @@ const runAsrScript = (audioPath, outputPath, uploadUrl, apiKey) => {
279
279
  if (code === 0) {
280
280
  resolve(stdout.trim());
281
281
  } else {
282
- const errorMsg = stderr.trim() || stdout.trim() || `进程退出码: ${code}`;
282
+ // 尝试解析结构化的 ASR 错误信息
283
+ const stderrContent = stderr.trim();
284
+ const asrErrorMatch = stderrContent.match(/ASR_ERROR:\s*(\{.*\})/);
285
+ if (asrErrorMatch) {
286
+ try {
287
+ const errorInfo = JSON.parse(asrErrorMatch[1]);
288
+ const parts = [errorInfo.error || '识别失败'];
289
+ if (errorInfo.audio_url) {
290
+ parts.push(`静态资源地址: ${errorInfo.audio_url}`);
291
+ }
292
+ if (errorInfo.details) {
293
+ parts.push(`服务器错误信息: ${errorInfo.details}`);
294
+ }
295
+ reject(new Error(parts.join('\n')));
296
+ return;
297
+ } catch {
298
+ // JSON 解析失败,使用原始错误信息
299
+ }
300
+ }
301
+ const errorMsg = stderrContent || stdout.trim() || `进程退出码: ${code}`;
283
302
  reject(new Error(errorMsg));
284
303
  }
285
304
  });
@@ -324,7 +343,7 @@ const asr = async ({ working_directory, audio_file }) => {
324
343
  const server = new Server(
325
344
  {
326
345
  name: 'media',
327
- version: '1.0.2',
346
+ version: '1.0.3',
328
347
  },
329
348
  {
330
349
  capabilities: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ww_nero/media",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "MCP server for media processing, including ASR speech recognition",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -119,6 +119,14 @@ def get_static_url(upload_url: str, filename: str) -> str:
119
119
  return f"{base_url.rstrip('/')}/{filename}"
120
120
 
121
121
 
122
+ class AsrError(Exception):
123
+ """ASR 识别错误,包含静态资源 URL 和错误详情"""
124
+ def __init__(self, message: str, audio_url: str = None, details: str = None):
125
+ self.audio_url = audio_url
126
+ self.details = details
127
+ super().__init__(message)
128
+
129
+
122
130
  def transcribe_audio(audio_url: str, api_key: str) -> list:
123
131
  """
124
132
  调用阿里云 ASR 接口进行语音识别
@@ -133,14 +141,17 @@ def transcribe_audio(audio_url: str, api_key: str) -> list:
133
141
  dashscope.api_key = api_key
134
142
 
135
143
  # 发起异步识别请求
136
- transcribe_response = Transcription.async_call(
137
- model='paraformer-v2',
138
- file_urls=[audio_url],
139
- language_hints=['zh', 'en', 'ja']
140
- )
144
+ try:
145
+ transcribe_response = Transcription.async_call(
146
+ model='paraformer-v2',
147
+ file_urls=[audio_url],
148
+ language_hints=['zh', 'en', 'ja']
149
+ )
150
+ except Exception as e:
151
+ raise AsrError(f"ASR 请求失败: {e}", audio_url=audio_url, details=str(e))
141
152
 
142
153
  if not transcribe_response or not hasattr(transcribe_response, 'output'):
143
- raise Exception("ASR 请求失败: 无效的响应")
154
+ raise AsrError("ASR 请求失败: 无效的响应", audio_url=audio_url)
144
155
 
145
156
  # 轮询等待识别完成
146
157
  while True:
@@ -151,10 +162,26 @@ def transcribe_audio(audio_url: str, api_key: str) -> list:
151
162
  transcribe_response = Transcription.fetch(task=transcribe_response.output.task_id)
152
163
 
153
164
  if transcribe_response.status_code != HTTPStatus.OK:
154
- raise Exception(f"ASR 识别失败: {transcribe_response.status_code}")
165
+ error_msg = getattr(transcribe_response, 'message', str(transcribe_response.status_code))
166
+ raise AsrError(
167
+ f"ASR 识别失败: {transcribe_response.status_code}",
168
+ audio_url=audio_url,
169
+ details=error_msg
170
+ )
155
171
 
156
172
  if transcribe_response.output.task_status == 'FAILED':
157
- raise Exception("ASR 识别任务失败")
173
+ # 尝试获取更详细的错误信息
174
+ error_details = None
175
+ results = transcribe_response.output.get('results', [])
176
+ for result in results:
177
+ if result.get('subtask_status') == 'FAILED':
178
+ error_details = result.get('message', '未知错误')
179
+ break
180
+ raise AsrError(
181
+ "ASR 识别任务失败",
182
+ audio_url=audio_url,
183
+ details=error_details
184
+ )
158
185
 
159
186
  # 获取识别结果
160
187
  results = transcribe_response.output.get('results', [])
@@ -190,6 +217,7 @@ def main():
190
217
  print("错误: 请通过 --api-key 参数或 ASR_API_KEY 环境变量提供 API Key", file=sys.stderr)
191
218
  sys.exit(1)
192
219
 
220
+ audio_url = None
193
221
  try:
194
222
  # 1. 上传音频文件
195
223
  print(f"正在上传音频文件: {args.audio}")
@@ -205,8 +233,7 @@ def main():
205
233
  transcriptions = transcribe_audio(audio_url, api_key)
206
234
 
207
235
  if not transcriptions:
208
- print("警告: 未获取到识别结果", file=sys.stderr)
209
- sys.exit(1)
236
+ raise AsrError("未获取到识别结果", audio_url=audio_url)
210
237
 
211
238
  # 4. 生成 SRT 文件
212
239
  subtitle_count = asr_to_srt(transcriptions, args.output)
@@ -216,8 +243,23 @@ def main():
216
243
  except FileNotFoundError as e:
217
244
  print(f"错误: {e}", file=sys.stderr)
218
245
  sys.exit(1)
246
+ except AsrError as e:
247
+ # 输出结构化的错误信息,包含静态资源 URL
248
+ error_info = {
249
+ 'error': str(e),
250
+ 'audio_url': e.audio_url or audio_url,
251
+ 'details': e.details
252
+ }
253
+ print(f"ASR_ERROR: {json.dumps(error_info, ensure_ascii=False)}", file=sys.stderr)
254
+ sys.exit(1)
219
255
  except Exception as e:
220
- print(f"错误: {e}", file=sys.stderr)
256
+ # 其他错误也尝试包含静态资源 URL
257
+ error_info = {
258
+ 'error': str(e),
259
+ 'audio_url': audio_url,
260
+ 'details': None
261
+ }
262
+ print(f"ASR_ERROR: {json.dumps(error_info, ensure_ascii=False)}", file=sys.stderr)
221
263
  sys.exit(1)
222
264
 
223
265