TypeScript中ytdl-core音视频流合并时child_process stdio类型错误
解决TypeScript中child_process自定义stdio管道的类型不兼容问题
在你的代码中,TypeScript报错是因为child_process.ChildProcess的stdio数组元素类型被定义为Readable | Writable | null | undefined,而ytdl返回的可读流调用pipe()方法时,要求参数必须是明确的WritableStream类型。以下是几种可行的解决方法:
方法1:类型断言(快速解决)
直接通过类型断言告诉TypeScript,你明确知道stdio[3]和stdio[4]是可写流:
audio.pipe(ffmpegProcess.stdio[3] as cp.Writable); video.pipe(ffmpegProcess.stdio[4] as cp.Writable); // 输出流同样可以断言 (ffmpegProcess.stdio[5] as cp.Readable).pipe(res);
方法2:类型守卫(更安全)
如果想避免类型断言带来的潜在风险,可以先检查流的存在性和类型,确保安全后再使用:
// 处理音频流管道 const audioDest = ffmpegProcess.stdio[3]; if (audioDest && typeof audioDest.write === 'function') { audio.pipe(audioDest); } // 处理视频流管道 const videoDest = ffmpegProcess.stdio[4]; if (videoDest && typeof videoDest.write === 'function') { video.pipe(videoDest); } // 处理输出流管道 const outputSrc = ffmpegProcess.stdio[5]; if (outputSrc && typeof outputSrc.pipe === 'function') { outputSrc.pipe(res); }
完整修正代码
import express, { Request, Response } from "express"; import ytdl from "ytdl-core"; import cp from "child_process"; import ffmpeg from "ffmpeg-static"; const app = express(); app.get("/downloadmerged", (req: Request, res: Response) => { res.setHeader("Content-Type", "video/mp4"); res.setHeader( `Content-Disposition`, `attachment; filename="Merged.mp4"` ); const ref = "https://www.youtube.com/watch?v=aR-KAldshAE"; const audio = ytdl(ref, { filter: "audioonly", quality: "highestaudio" }); const video = ytdl(ref, { filter: "videoonly", quality: "highestvideo" }); // 断言ffmpeg路径为字符串,避免类型错误 const ffmpegPath = ffmpeg as string; const ffmpegProcess = cp.spawn( ffmpegPath, [ "-loglevel", "0", "-hide_banner", "-itsoffset", "3.0", "-i", "pipe:3", "-i", "pipe:4", "-vf", "scale=320:240", "-c:v", "libx265", "-x265-params", "log-level=0", "-c:a", "flac", "-f", "matroska", "pipe:5", ], { windowsHide: true, stdio: [ "inherit", "inherit", "inherit", "pipe", "pipe", "pipe", ], } ); ffmpegProcess.on("close", () => { process.stdout.write("\n\n\n"); console.log("done"); }); // 使用类型断言解决类型不兼容问题 audio.pipe(ffmpegProcess.stdio[3] as cp.Writable); video.pipe(ffmpegProcess.stdio[4] as cp.Writable); (ffmpegProcess.stdio[5] as cp.Readable).pipe(res); }); app.listen(3000, () => { console.log("Server running on port 3000"); });
另外,确保你已经安装了必要的类型依赖:
npm install @types/node @types/express @types/ytdl-core --save-dev
内容的提问来源于stack exchange,提问作者Abhigyan Kumar
相关产品推荐
相关产品推荐

