@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 +21 -2
- package/package.json +1 -1
- package/scripts/asr_srt.py +53 -11
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
|
-
|
|
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.
|
|
346
|
+
version: '1.0.3',
|
|
328
347
|
},
|
|
329
348
|
{
|
|
330
349
|
capabilities: {
|
package/package.json
CHANGED
package/scripts/asr_srt.py
CHANGED
|
@@ -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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|