我正在尝试将 ytdl-core 中的视频和音频与 ffmpeg 合并,并将其以 mp4 格式导出给用户。输出视频没有时间(初始持续时间)出现,并且无法搜索或导航到视频的另一点。
app.get('/downloadmp4', async (req, res)=>{
let url = req.query.url;
if (!ytdl.validateURL(url)) {
return res.sendStatus(400);
}
let title = 'video';
let info = await ytdl.getInfo(url);
title = info.videoDetails.title.replace(/[^\x00-\x7F]/g, "");
res.header('Content-Disposition', `attachment; filename="${title}.mp4"`);
let video = ytdl(url,{filter:'videoonly', quality: "highest"})
let audio = ytdl(url, {filter: 'audioonly', highWaterMark: 1<<25});
// create the ffmpeg process for muxing
const ffmpegProcess = cp.spawn(
ffmpeg,
[
'-loglevel', '0', '-hide_banner',
// input audio by pipe
"-i", "pipe:3",
// input video by pipe
"-i", "pipe:4",
// map audio and video correspondingly
"-map", "0:a",
"-map", "1:v",
// change the codec
'-c:v', 'copy',
'-c:a', 'flac',
// "-c:a", "aac",
'-crf','27',
"-preset", "veryfast",
// Allow output to be seekable, which is needed for mp4 output
'-movflags','frag_keyframe+empty_moov',
// Define output container
'-f', 'mp4', 'pipe:5',
],
{
// no popup window for Windows users
windowsHide: true,
stdio: [
// silence stdin/out, forward stderr,
"inherit", "inherit", "inherit",
// and pipe audio, video, output
"pipe", "pipe", "pipe",
],
}
);
audio.pipe(ffmpegProcess.stdio[3]);
video.pipe(ffmpegProcess.stdio[4]);
ffmpegProcess.stdio[5].pipe(res);
})
我尝试了各种格式的视频和音频以及以下命令
'-movflags','frag_keyframe+empty_moov'
,并且frag_keyframe+faststart
没有结果
查找依赖于每个轨道的
stts
中的样本表(stss
、moov
...)。这些是在混合期间构建的并在最后写出。对于普通 MP4,ffmpeg 需要向前查找以写入样本表和/或更新媒体数据大小。您正在管道输出,因此 ffmpeg 无法做到这一点。在分段模式下,示例表为空。所有元数据都存储在片段框中,玩家不使用片段框进行查找。
基本上,您不应该通过管道传输输出。