@lingjingai/scriptctl 0.63.9 → 0.63.11

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.
@@ -0,0 +1,4 @@
1
+ # 0.63.10
2
+
3
+ - 原片没有音轨时记录证据不足,保留台词与时间并继续画面审核,不再尝试无效音频提取。
4
+ - 审核视频及结构化请求使用服务端默认输出额度。
@@ -0,0 +1,4 @@
1
+ # 0.63.11
2
+
3
+ - 审核 HTTP 连接统一由调用方 AbortSignal 控制超时,避免 Undici 默认五分钟超时提前中断长模型请求。
4
+ - 模型路由失败记录底层网络错误原因。
package/dist/bin.js CHANGED
File without changes
@@ -2329,7 +2329,7 @@ import { APICallError } from "@ai-sdk/provider";
2329
2329
  import { z as z2 } from "zod";
2330
2330
 
2331
2331
  // packages/review-agent/src/media/net.ts
2332
- import { ProxyAgent } from "undici";
2332
+ import { Agent, ProxyAgent } from "undici";
2333
2333
  var cached;
2334
2334
  function proxyUrl() {
2335
2335
  for (const name of ["https_proxy", "HTTPS_PROXY", "http_proxy", "HTTP_PROXY"]) {
@@ -2341,21 +2341,21 @@ function proxyUrl() {
2341
2341
  function dispatcher() {
2342
2342
  if (cached === void 0) {
2343
2343
  const url = proxyUrl();
2344
- cached = url ? new ProxyAgent(url) : null;
2344
+ const timeouts = { headersTimeout: 0, bodyTimeout: 0 };
2345
+ cached = url ? new ProxyAgent({ uri: url, ...timeouts }) : new Agent(timeouts);
2345
2346
  }
2346
- return cached ?? void 0;
2347
+ return cached;
2347
2348
  }
2348
2349
  var proxyFetch = (input, init) => {
2349
2350
  const proxy = dispatcher();
2350
2351
  return globalThis.fetch(input, { ...init, ...proxy ? { dispatcher: proxy } : {} });
2351
2352
  };
2352
2353
  async function post(url, body, timeoutMs = 18e4, headers = {}) {
2353
- return fetch(url, {
2354
+ return proxyFetch(url, {
2354
2355
  method: "POST",
2355
2356
  headers: { "Content-Type": "application/json", ...headers },
2356
2357
  body: JSON.stringify(body),
2357
- signal: AbortSignal.timeout(timeoutMs),
2358
- ...dispatcher() ? { dispatcher: dispatcher() } : {}
2358
+ signal: AbortSignal.timeout(timeoutMs)
2359
2359
  });
2360
2360
  }
2361
2361
 
@@ -2474,12 +2474,7 @@ async function generateReviewJson(request) {
2474
2474
  { text: request.prompt }
2475
2475
  ] }],
2476
2476
  ...request.system ? { systemInstruction: { parts: [{ text: request.system }] } } : {},
2477
- generationConfig: {
2478
- temperature: 0,
2479
- responseMimeType: "application/json",
2480
- responseJsonSchema: schema,
2481
- ...request.maxOutputTokens ? { maxOutputTokens: request.maxOutputTokens } : {}
2482
- }
2477
+ generationConfig: { temperature: 0, responseMimeType: "application/json", responseJsonSchema: schema }
2483
2478
  } : {
2484
2479
  model: route.model,
2485
2480
  input: [{ role: "user", content: [
@@ -2487,7 +2482,6 @@ async function generateReviewJson(request) {
2487
2482
  { type: "input_text", text: request.prompt }
2488
2483
  ] }],
2489
2484
  ...request.system ? { instructions: request.system } : {},
2490
- ...request.maxOutputTokens ? { max_output_tokens: request.maxOutputTokens } : {},
2491
2485
  text: { format: { type: "json_schema", name: "review", schema } }
2492
2486
  };
2493
2487
  for (let attempt = 1; attempt <= route.maxAttempts; attempt++) {
@@ -2503,7 +2497,8 @@ async function generateReviewJson(request) {
2503
2497
  raw = await response.text();
2504
2498
  } catch (error) {
2505
2499
  if (!transientNetwork(error)) throw error;
2506
- failures.push(`${route.provider}/${route.model} attempt ${attempt}: ${String(error)}`);
2500
+ const cause = error instanceof Error && error.cause instanceof Error ? `; ${error.cause.name}: ${error.cause.message}` : "";
2501
+ failures.push(`${route.provider}/${route.model} attempt ${attempt}: ${String(error)}${cause}`);
2507
2502
  if (attempt < route.maxAttempts) await new Promise((resolve2) => setTimeout(resolve2, attempt * 1e3));
2508
2503
  continue;
2509
2504
  }
@@ -2579,7 +2574,6 @@ async function watchWindow(video, from, to, question, opts) {
2579
2574
  video: { data: fs3.readFileSync(clip2.path, "base64"), fps: CLIP_FPS },
2580
2575
  schema: z3.object({ answer: z3.string().min(1) }),
2581
2576
  timeoutMs: 18e4,
2582
- maxOutputTokens: 2048,
2583
2577
  callKey: opts.callKey
2584
2578
  });
2585
2579
  return { answer: result.value.answer, usage: result.usage.map((row) => ({
@@ -2613,6 +2607,20 @@ var wordsSchema = z4.array(z4.object({
2613
2607
  })).transform((words) => words.filter((word) => word.text.trim().length > 0)).pipe(z4.array(timedTextSchema));
2614
2608
  var utteranceSchema = timedTextSchema.safeExtend({ words: wordsSchema.optional() });
2615
2609
  var responseSchema = z4.object({ result: z4.object({ utterances: z4.array(utteranceSchema) }) });
2610
+ async function hasAudioTrack(video) {
2611
+ const { stdout } = await exec("ffprobe", [
2612
+ "-v",
2613
+ "error",
2614
+ "-select_streams",
2615
+ "a:0",
2616
+ "-show_entries",
2617
+ "stream=index",
2618
+ "-of",
2619
+ "csv=p=0",
2620
+ video
2621
+ ], { timeout: 3e4 });
2622
+ return stdout.trim().length > 0;
2623
+ }
2616
2624
  function parseAsr(raw) {
2617
2625
  return responseSchema.parse(raw).result.utterances;
2618
2626
  }
@@ -3169,7 +3177,7 @@ function buildTools(ctx) {
3169
3177
  }
3170
3178
 
3171
3179
  // packages/review-agent/src/agent.ts
3172
- import { Agent } from "@mastra/core/agent";
3180
+ import { Agent as Agent2 } from "@mastra/core/agent";
3173
3181
  import { z as z6 } from "zod";
3174
3182
  function seriesCard(doc) {
3175
3183
  return read(doc, "").split("\nepisodes\n")[0].trim();
@@ -3226,7 +3234,7 @@ async function reviewUnit(doc, episode, video, config, asr) {
3226
3234
  };
3227
3235
  const usage = [];
3228
3236
  const modelFailures = [];
3229
- const agent = new Agent({
3237
+ const agent = new Agent2({
3230
3238
  id: `review-ep${episode}`,
3231
3239
  name: `Script review \xB7 episode ${episode}`,
3232
3240
  instructions: systemPrompt(input),
@@ -3389,6 +3397,18 @@ function resolveComparison(doc, episode, cues, comparison) {
3389
3397
  }
3390
3398
  async function alignEpisode(doc, episode, video, scriptPath, config, onAsrComplete) {
3391
3399
  const root = path4.join(path4.dirname(scriptPath), ".review", "asr", `episode-${episode}`);
3400
+ await fs6.mkdir(root, { recursive: true });
3401
+ if (!await hasAudioTrack(video)) {
3402
+ const report2 = {
3403
+ summary: "\u539F\u7247\u6CA1\u6709\u97F3\u8F68\uFF0C\u65E0\u6CD5\u6267\u884C ASR \u6821\u65F6\uFF1B\u7EE7\u7EED\u5BA1\u6838\u753B\u9762\u4E0E\u5267\u672C\u3002",
3404
+ timestamp_corrections: [],
3405
+ missing_dialogue: [],
3406
+ notes: ["ffprobe \u786E\u8BA4\u539F\u7247\u6CA1\u6709\u97F3\u9891\u6D41\u3002\u4FDD\u7559\u73B0\u6709\u53F0\u8BCD\u53CA\u65F6\u95F4\uFF0C\u4E0D\u6839\u636E\u65E0\u97F3\u8F68\u63A8\u65AD\u53F0\u8BCD\u4E0D\u5B58\u5728\uFF1B\u770B\u7247\u6838\u5BF9\u753B\u9762\u4E0E\u5B57\u5E55\uFF0C\u65E0\u6CD5\u4ECE\u753B\u9762\u786E\u8BA4\u7684\u53D1\u58F0\u5185\u5BB9\u660E\u786E\u6807\u4E3A\u8BC1\u636E\u4E0D\u8DB3\u3002"]
3407
+ };
3408
+ const reportDir2 = await fs6.mkdtemp(path4.join(root, "no-audio-"));
3409
+ await fs6.writeFile(path4.join(reportDir2, "report.json"), JSON.stringify(report2, null, 2));
3410
+ return { report: report2, reportDir: reportDir2, usage: [] };
3411
+ }
3392
3412
  const utterances = await episodeAsr(video, root);
3393
3413
  onAsrComplete?.();
3394
3414
  const script = read(doc, String(episode), { timestamps: true });