我目前遇到的问题是,保存文件时,它只是说,
The "val" argument must be an instance of Readable, Iterable, or AsyncIterable. Received an instance of WriteStream
。另外,这里是它的示例日志:
[INFO] Retrieved video: 'Title'.
[INFO] Retrieved download URL: 'https://...'
[ERROR] An error occurred during download: The "val" argument must be an instance of Readable, Iterable, or AsyncIterable. Received an instance of WriteStream
undefined
[INFO] Video downloaded successfully.
node:events:491
throw er; // Unhandled 'error' event
^
Error [ERR_STREAM_DESTROYED]: Cannot call pipe after a stream was destroyed
at new NodeError (node:internal/errors:393:5)
at destroy (node:internal/streams/pipeline:58:44)
at finishImpl (node:internal/streams/pipeline:199:23)
at finish (node:internal/streams/pipeline:186:5)
at pump (node:internal/streams/pipeline:141:5)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Emitted 'error' event on Transform instance at:
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
code: 'ERR_STREAM_DESTROYED'
}
我期望下载文件时的日志类似于
[INFO] Downloading [======= ] 70%
。如果node-fetch与此不兼容,您可以使用其他模块,例如http或https模块。
async download_video(video_id: string): Promise<void> {
try {
const fetchVideo = await this.get_video(video_id);
console.log(
`[INFO] Retrieved video: '${fetchVideo.title}' by ${fetchVideo.user.name} (@${fetchVideo.user.username}).`,
);
const fetchFileUrl = await fetch(fetchVideo.fileUrl);
const parseJson = await fetchFileUrl.json();
const downloadUrl = parseJson[0].src.download;
console.log(`[INFO] Retrieved download URL: '${downloadUrl}'`);
const response = await fetch(`https:${downloadUrl}`);
const contentLength = parseInt(
response.headers.get("content-length") ?? "0",
10,
);
const sanitizedTitle = fetchVideo.title.replace(/[\\/:"*?<>|]/g, "");
const filename = `${sanitizedTitle}.${fetchVideo.file.mime.split("/")[1]}`;
let downloadedBytes = 0;
await pipeline(
response.body as unknown as stream.Readable,
new stream.PassThrough()
.on("finish", () => {
console.log(`[INFO] Video downloaded successfully.`);
})
.on("error", (err) => {
console.error(
`[ERROR] An error occurred during saving video: ${err.message}`,
);
})
.pipe(fs.createWriteStream(filename)),
new stream.Transform({
transform(chunk, _encoding, callback) {
downloadedBytes += chunk.length;
const percent = Math.round((downloadedBytes / contentLength) * 100);
const progress =
"[" + "=".repeat(percent / 5) + " ".repeat(20 - percent / 5) + "]";
process.stdout.clearLine?.(0);
process.stdout.cursorTo?.(0);
process.stdout.write(`[INFO] Downloading ${progress} ${percent}%`);
callback(null, chunk);
},
}),
);
} catch (err: any) {
console.error(`[ERROR] An error occurred during download: ${err.message}`);
}
}