FFmpeg与ytdl-core混流最高音视频生成MP4时长异常问题
问题描述
我用ytdl-core获取分离的视频和音频文件,想把它们合并成MP4并流式传输到响应里。用highestvideo和highestaudio质量参数获取文件,修改了ytdl-core-muxer模块把输出改成MP4,加了-movflags frag_keyframe+empty_moov让MP4支持拖拽。操作没报错,生成了MP4文件,但用Windows Photos打开时,视频播放正常、画质没问题,时长显示完全错误——实际时长1分32秒,但剩余时长显示约5300万小时。
我试过加固定帧率参数-r 60、生成时间戳参数-fflags +genpts,没用;也试过把视频转成h264(用libx264)、音频转成aac,问题还是没解决。
我的FFmpeg调用代码
// create the ffmpeg process for muxing const ffmpegProcess = cp.spawn( ffmpeg, [ // input audio by pipe "-thread_queue_size", "4096", "-i", "pipe:3", // input video by pipe "-thread_queue_size", "4096", "-r", "60", "-i", "pipe:4", // map audio and video correspondingly "-map", "0:a", "-map", "1:v", // change the codec "-c:v", "libx264", "-c:a", "aac", "-preset", "ultrafast", // Allow output to be seekable, which is needed for mp4 output "-movflags", "frag_keyframe+empty_moov", // output mp4 and pipe "-r", "60", "-fflags", "+genpts", "-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", ], } ); audioStream.pipe(ffmpegProcess.stdio[3]); videoStream.pipe(ffmpegProcess.stdio[4]); ffmpegProcess.stdio[5].pipe(result);
FFmpeg完整控制台输出
ffmpeg version 5.0.1-essentials_build-www.gyan.dev Copyright (c) 2000-2022 the FFmpeg developers built with gcc 11.2.0 (Rev7, Built by MSYS2 project) configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-lzma --enable-zlib --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-sdl2 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-libass --enable-libfreetype --enable-libfribidi --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libgme --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libtheora --enable-libvo-amrwbenc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-librubberband libavutil 57. 17.100 / 57. 17.100 libavcodec 59. 18.100 / 59. 18.100 libavformat 59. 16.100 / 59. 16.100 libavdevice 59. 4.100 / 59. 4.100 libavfilter 8. 24.100 / 8. 24.100 libswscale 6. 4.100 / 6. 4.100 libswresample 4. 3.100 / 4. 3.100 libpostproc 56. 3.100 / 56. 3.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'pipe:3': Metadata: major_brand : mp42 minor_version : 0 compatible_brands: isommp42 creation_time : 2022-08-21T19:56:49.000000Z Duration: 00:01:32.11, start: 0.000000, bitrate: N/A Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1280x720 [SAR 1:1 DAR 16:9], 1892 kb/s, 30 fps, 30 tbr, 15360 tbn (default) Metadata: creation_time : 2022-08-21T19:56:49.000000Z handler_name : ISO Media file produced by Google Inc. Created on: 08/21/2022. vendor_id : [0][0][0][0] Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default) Metadata: creation_time : 2022-08-21T19:56:49.000000Z handler_name : ISO Media file produced by Google Inc. Created on: 08/21/2022. vendor_id : [0][0][0][0] Input #1, matroska,webm, from 'pipe:4': Metadata: encoder : google/video-file Duration: 00:01:32.12, start: 0.000000, bitrate: N/A Stream #1:0(eng): Video: vp9 (Profile 0), yuv420p(tv, bt709), 3840x2160, SAR 1:1 DAR 16:9, 60 fps, 60 tbr, 1k tbn (default) Stream mapping: Stream #0:1 -> #0:0 (aac (native) -> aac (native)) Stream #1:0 -> #0:1 (vp9 (native) -> h264 (libx264)) [libx264 @ 0000022aa059be80] using SAR=1/1 [libx264 @ 0000022aa059be80] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2 [libx264 @ 0000022aa059be80] profile Constrained Baseline, level 5.2, 4:2:0, 8-bit [libx264 @ 0000022aa059be80] 264 - core 164 r3094 bfc87b7 - H.264/MPEG-4 AVC codec - Copyleft 2003-2022 - http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=0:0:0 analyse=0:0 me=dia subme=0 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=12 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=250 keyint_min=25 scenecut=0 intra_refresh=0 rc=crf mbtree=0 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=0 Output #0, mp4, to 'pipe:5': Metadata: major_brand : mp42 minor_version : 0 compatible_brands: isommp42 encoder : Lavf59.16.100 Stream #0:0(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default) Metadata: creation_time : 2022-08-21T19:56:49.000000Z handler_name : ISO Media file produced by Google Inc. Created on: 08/21/2022. vendor_id : [0][0][0][0] encoder : Lavc59.18.100 aac Stream #0:1(eng): Video: h264 (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 3840x2160 [SAR 1:1 DAR 16:9], q=2-31, 60 fps, 15360 tbn (default) Metadata: encoder : Lavc59.18.100 libx264 Side data: cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A [matroska,webm @ 0000022aa056cd00] Thread message queue blocking; consider raising the thread_queue_size option (current value: 4096) frame= 5527 fps= 77 q=-1.0 Lsize= 424599kB time=00:01:32.11 bitrate=37761.2kbits/s speed=1.29x video:423226kB audio:1329kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.010570% [aac @ 0000022aa05ca240] Qavg: 17828.035 [libx264 @ 0000022aa059be80] frame I:23 Avg QP:19.83 size:292044 [libx264 @ 0000022aa059be80] frame P:5504 Avg QP:22.92 size: 77519 [libx264 @ 0000022aa059be80] mb I I16..4: 100.0% 0.0% 0.0% [libx264 @ 0000022aa059be80] mb P I16..4: 26.5% 0.0% 0.0% P16..4: 14.1% 0.0% 0.0% 0.0% 0.0% skip:59.3% [libx264 @ 0000022aa059be80] coded y,uvDC,uvAC intra: 10.6% 27.6% 7.0% inter: 6.5% 12.8% 1.4% [libx264 @ 0000022aa059be80] i16 v,h,dc,p: 57% 26% 8% 9% [libx264 @ 0000022aa059be80] i8c dc,h,v,p: 43% 24% 25% 7% [libx264 @ 0000022aa059be80] kb/s:37637.70
解决方案
问题出在empty_moov标记上:它会让FFmpeg不写入包含时长等核心元数据的完整moov原子,Windows Photos这类播放器依赖这个原子读取正确时长。要同时支持流式拖拽和正确显示时长,调整参数即可:
- 替换movflags参数:把
-movflags frag_keyframe+empty_moov改成-movflags frag_keyframe+faststart。faststart会把moov原子移到文件开头,既支持流式拖拽,又保留了完整的时长元数据。 - 移除重复参数:删除输出部分的
-r 60,输入里指定一次帧率就足够。 - 可选优化:在音频输入参数里加
-vn,明确忽略音频流里附带的视频轨道,避免潜在干扰。
修改后的FFmpeg参数数组:
[ // input audio by pipe,明确忽略视频轨道 "-thread_queue_size", "4096", "-vn", "-i", "pipe:3", // input video by pipe "-thread_queue_size", "4096", "-i", "pipe:4", // map audio and video correspondingly "-map", "0:a", "-map", "1:v", // change the codec "-c:v", "libx264", "-c:a", "aac", "-preset", "ultrafast", // 支持流式拖拽且保留完整元数据 "-movflags", "frag_keyframe+faststart", // 确保时间戳正确 "-fflags", "+genpts", "-f", "mp4", "pipe:5", ]
内容的提问来源于stack exchange,提问作者Niek Peters
相关产品推荐
相关产品推荐

