@xiping/node-utils 1.0.63 → 1.0.64

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.
@@ -4,6 +4,9 @@ import * as path from "node:path";
4
4
  import { runSync } from "./runSync.js";
5
5
  import { checkFFmpegAvailability } from "./check.js";
6
6
  import { getThumbnail } from "./getThumbnail.js";
7
+ const log = (message, data) => {
8
+ console.log("[Transcode]", message, data !== undefined ? data : "");
9
+ };
7
10
  const defaultConfig = {
8
11
  generateThumbnail: true,
9
12
  format: "hevc",
@@ -88,11 +91,18 @@ function buildTranscodeArgs(inputPath, outputPath, format, encoders) {
88
91
  function runTranscodeWithProgress(inputPath, outputPath, format, encoders, totalDuration, onProgress) {
89
92
  return new Promise((resolve, reject) => {
90
93
  const args = buildTranscodeArgs(inputPath, outputPath, format, encoders);
94
+ log("ffmpeg spawn", { totalDuration, format, outputPath });
91
95
  const child = spawn("ffmpeg", args, { stdio: ["ignore", "pipe", "pipe"] });
92
96
  let lastPercent = -1;
97
+ let hasReportedProgress = false;
98
+ let loggedUnparsedTime = false;
93
99
  const report = (progress) => {
94
100
  if (progress.percent !== lastPercent) {
95
101
  lastPercent = progress.percent;
102
+ hasReportedProgress = true;
103
+ if (progress.percent === 0 || progress.percent === 50 || progress.percent === 99 || progress.phase === "done") {
104
+ log("progress", { phase: progress.phase, percent: progress.percent, currentTime: progress.currentTime, duration: progress.duration });
105
+ }
96
106
  onProgress(progress);
97
107
  }
98
108
  };
@@ -105,6 +115,10 @@ function runTranscodeWithProgress(inputPath, outputPath, format, encoders, total
105
115
  buffer = lines.pop() ?? "";
106
116
  for (const line of lines) {
107
117
  const currentTime = parseTimeFromStderr(line);
118
+ if (/time=\d/.test(line) && !loggedUnparsedTime && currentTime == null) {
119
+ loggedUnparsedTime = true;
120
+ log("stderr time line not parsed (check locale/format)", { line: line.trim() });
121
+ }
108
122
  if (currentTime != null && totalDuration > 0) {
109
123
  const percent = Math.min(99, Math.round((currentTime / totalDuration) * 100));
110
124
  report({
@@ -118,8 +132,12 @@ function runTranscodeWithProgress(inputPath, outputPath, format, encoders, total
118
132
  }
119
133
  });
120
134
  }
121
- child.on("error", (err) => reject(err));
135
+ child.on("error", (err) => {
136
+ log("ffmpeg error", err.message);
137
+ reject(err);
138
+ });
122
139
  child.on("close", (code, signal) => {
140
+ log("ffmpeg close", { code, signal, hasReportedProgress });
123
141
  if (signal) {
124
142
  reject(new Error(`FFmpeg killed by signal: ${signal}`));
125
143
  return;
@@ -128,6 +146,9 @@ function runTranscodeWithProgress(inputPath, outputPath, format, encoders, total
128
146
  reject(new Error(`FFmpeg exited with code ${code}`));
129
147
  return;
130
148
  }
149
+ if (!hasReportedProgress) {
150
+ log("no encoding progress was parsed from stderr (progress callbacks may not have fired)");
151
+ }
131
152
  report({
132
153
  phase: "done",
133
154
  percent: 100,
@@ -155,6 +176,7 @@ export async function transcoding(inputPath, config = {}) {
155
176
  const encoders = getAvailableEncoders();
156
177
  const format = finalConfig.format;
157
178
  const duration = getDurationInSeconds(validatedPath);
179
+ log("start", { inputPath: validatedPath, format, durationSeconds: duration, hasOnProgress: !!finalConfig.onProgress });
158
180
  const dir = path.dirname(validatedPath);
159
181
  const baseName = path.basename(validatedPath, path.extname(validatedPath));
160
182
  const suffix = format === "av1" ? "_av1" : "_hevc";
@@ -165,6 +187,7 @@ export async function transcoding(inputPath, config = {}) {
165
187
  };
166
188
  await runTranscodeWithProgress(validatedPath, tempOutputPath, format, encoders, duration, reportProgress);
167
189
  if (finalConfig.generateThumbnail) {
190
+ log("generating thumbnail");
168
191
  await getThumbnail(validatedPath);
169
192
  }
170
193
  let resultPath;
@@ -177,5 +200,6 @@ export async function transcoding(inputPath, config = {}) {
177
200
  else {
178
201
  resultPath = tempOutputPath;
179
202
  }
203
+ log("done", { outputPath: resultPath });
180
204
  return { outputPath: resultPath };
181
205
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xiping/node-utils",
3
- "version": "1.0.63",
3
+ "version": "1.0.64",
4
4
  "description": "node-utils",
5
5
  "type": "module",
6
6
  "author": "The-End-Hero <527409987@qq.com>",
@@ -25,7 +25,7 @@
25
25
  "bugs": {
26
26
  "url": "https://github.com/The-End-Hero/xiping/issues"
27
27
  },
28
- "gitHead": "466588a53ef8fa8bc6562a9933f1c9d707e978e5",
28
+ "gitHead": "483df3f50a54f6d66b461c64bf05c77c68d368ad",
29
29
  "publishConfig": {
30
30
  "access": "public",
31
31
  "registry": "https://registry.npmjs.org/"