我创建了一个next.js视频下载器,我想下载最高质量的视频。当我触发下载时,我只得到一个静音的mp4文件(高质量)和一个静音的mp3文件。这里是API文件。我如何下载视频,音频,然后将它们与ffmpeg正确合并?
import ytdl from "ytdl-core";
import fs from "fs";
import { Server } from "socket.io";
import ffmpeg from "fluent-ffmpeg";
export default async function handler(req, res) {
if (res.socket.server.io) {
console.log("Socket is already running");
res.end();
return;
}
console.log("Socket is initializing");
const io = new Server(res.socket.server);
res.socket.server.io = io;
io.on("connection", async (socket) => {
console.log(socket.id, "socketID");
const sendError = async (msg) => {
socket.emit("showError", msg);
};
const sendProgress = async (msg) => {
console.log(msg);
socket.emit("showProgress", msg);
};
const sendComplete = async (msg) => {
console.log(msg);
socket.emit("showComplete", msg);
};
const downloadVideo = async (url) => {
try {
const videoInfo = await ytdl.getInfo(url);
const outputPath = path.join(
process.cwd(),
"mp4s",
`${videoInfo.videoDetails.title}.mp4`
);
const audioPath = path.join(
process.cwd(),
"mp4s",
`${videoInfo.videoDetails.title}.mp3`
);
const videoFormat = ytdl.chooseFormat(videoInfo.formats, {
quality: "highestvideo",
filter: "videoonly",
});
const audioFormat = ytdl.chooseFormat(videoInfo.formats, {
quality: "highestaudio",
filter: "audioonly",
});
const videoStream = ytdl(url, { quality: videoFormat.itag });
const audioStream = ytdl(url, { quality: audioFormat.itag });
const videoOutput = fs.createWriteStream(outputPath);
const audioOutput = fs.createWriteStream(audioPath);
audioStream.pipe(audioOutput);
videoStream.pipe(videoOutput);
let downloadedBytes = 0;
let totalBytes =
videoFormat.contentLength || videoInfo.length_seconds * 1000000;
videoOutput.on("data", (chunk) => {
downloadedBytes += chunk.length;
const progress = Math.round((downloadedBytes / totalBytes) * 100);
sendProgress({ progress });
});
videoOutput.on("error", (err) => {
console.error(err);
sendError({
status: "error",
message: "An error occurred while writing the video file",
});
});
audioOutput.on("error", (err) => {
console.error(err);
sendError({
status: "error",
message: "An error occurred while writing the audio file",
});
});
videoOutput.on("finish", () => {
audioOutput.on("finish", () => {
if (fs.existsSync(outputPath) && fs.existsSync(audioPath)) {
const outputFile = path.join(
process.cwd(),
"mp4s",
`${videoInfo.videoDetails.title}-with-audio.mp4`
);
const command = ffmpeg()
.input(outputPath)
.input(audioPath)
.outputOptions("-c:v copy")
.outputOptions("-c:a aac")
.outputOptions("-b:a 192k")
.outputOptions("-strict -2")
.output(outputFile)
.on("end", () => {
fs.unlink(outputPath, () => {});
fs.unlink(audioPath, () => {});
sendComplete({
status: "success",
});
})
.on("error", (err) => {
console.error("ffmpeg error:", err.message);
sendError({
status: "error",
message:
"An error occurred while processing the audio and video files",
});
});
command.run();
} else {
console.error("Output or audio file not found");
sendError({
status: "error",
message: "Output or audio file not found",
});
}
});
});
} catch (error) {
console.error(error);
sendError({
status: "error",
message: "An error occurred while downloading the video",
});
}
};
socket.on("downloadVideo", downloadVideo);
});
res.end();
}
我也在使用socket.io来显示前端的进度,但是由于某些原因,我不能正确地获得进度。是否可以这样做?
1条答案
按热度按时间wd2eg0qa1#
这不是
ytdl
问题;高比特率总是没有音频,所以你必须分别下载音频和视频。这里有一个detailed how-to,用于正确地合并两个单独的流与ffmpeg
这涉及到
ffmpeg
和多个输入管道的一些知识。