@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.
- package/lib/src/ffmpeg/transcode.js +25 -1
- package/package.json +2 -2
|
@@ -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) =>
|
|
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.
|
|
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": "
|
|
28
|
+
"gitHead": "483df3f50a54f6d66b461c64bf05c77c68d368ad",
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public",
|
|
31
31
|
"registry": "https://registry.npmjs.org/"
|