使用FFmpeg拼接MP4视频后输出时长超出预期的问题求助
FFmpeg拼接MP4视频时长超出预期问题
问题现象
将两段时长1.66秒的相同MP4视频(0.mp4)拼接,预期输出时长3.32秒,但实际输出时长为3.38秒。尝试以下方式均出现相同问题:
- 使用FFmpeg concat demuxer命令:
ffmpeg -f concat -i inputs.txt -c copy mergedVideo.mp4(inputs.txt包含两行file '0.mp4') - 指定帧率的FFmpeg命令
- 使用MoviePy库执行合并代码
相关日志与检测信息
FFmpeg执行输出
ffmpeg -f concat -i inputs.txt -c copy mergedVideo.mp4 ffmpeg version 5.0.1 Copyright (c) 2000-2022 the FFmpeg developers built with clang version 12.0.1 configuration: --prefix=/Users/runner/miniforge3/conda-bld/ffmpeg_1649114094397/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_pl --cc=arm64-apple-darwin20.0.0-clang --disable-doc --disable-openssl --enable-demuxer=dash --enable-gnutls --enable-gpl --enable-hardcoded-tables --enable-libfreetype --enable-libopenh264 --enable-neon --enable-libx264 --enable-libx265 --enable-libaom --enable-libsvtav1 --enable-libxml2 --enable-libvpx --enable-pic --enable-pthreads --enable-shared --disable-static --enable-version3 --enable-zlib --enable-libmp3lame --pkg-config=/Users/runner/miniforge3/conda-bld/ffmpeg_1649114094397/_build_env/bin/pkg-config --enable-cross-compile --arch=arm64 --target-os=darwin --cross-prefix=arm64-apple-darwin20.0.0- --host-cc=/Users/runner/miniforge3/conda-bld/ffmpeg_1649114094397/_build_env/bin/x86_64-apple-darwin13.4.0-clang 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 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x1561044a0] Auto-inserting h264_mp4toannexb bitstream filter Input #0, concat, from 'inputs.txt': Duration: N/A, start: -0.064000, bitrate: 1424 kb/s Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 1355 kb/s, 50 fps, 50 tbr, 12800 tbn Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0] Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 68 kb/s Metadata: handler_name : SoundHandler vendor_id : [0][0][0][0] File 'mergedVideo.mp4' already exists. Overwrite? [y/N] y Output #0, mp4, to 'mergedVideo.mp4': Metadata: encoder : Lavf59.16.100 Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 1355 kb/s, 50 fps, 50 tbr, 12800 tbn Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0] Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 68 kb/s Metadata: handler_name : SoundHandler vendor_id : [0][0][0][0] Stream mapping: Stream #0:0 -> #0:0 (copy) Stream #0:1 -> #0:1 (copy) Press [q] to stop, [?] for help frame= 0 fps=0.0 q=-1.0 size= 0kB time=00:00:00.06 bitrate= 6.0k[mov,mp4,m4a,3gp,3g2,mj2 @ 0x154f28b20] Auto-inserting h264_mp4toannexb bitstream filter frame= 166 fps=0.0 q=-1.0 Lsize= 583kB time=00:00:03.39 bitrate=1407.4kbits/s speed= 179x video:550kB audio:29kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.737394%
ffprobe检测输出视频结果
ffprobe -v error -select_streams v -show_entries stream=codec_name,time_base,start_pts,start_time,duration -of default=noprint_wrappers=1 mergedVideo.mp4 codec_name=h264 time_base=1/12800 start_pts=0 start_time=0.000000 duration=3.380000
ffprobe检测输入视频结果
ffprobe -v error -select_streams v -show_entries stream=codec_name,time_base,start_pts,start_time,duration -of default=noprint_wrappers=1 0.mp4 codec_name=h264 time_base=1/12800 start_pts=0 start_time=0.000000 duration=1.660000
MoviePy合并代码
from moviepy.editor import VideoFileClip, concatenate_videoclips videos = [VideoFileClip("0.mp4"), VideoFileClip("0.mp4")] concatenate_videoclips(videos).write_videofile('mergedVideo.mp4')
原因分析
- MP4编辑列表或时间戳偏移:FFmpeg日志显示输入流
start: -0.064000,说明原视频可能包含隐藏的编辑列表,或帧时间戳存在偏移。即使ffprobe显示start_time=0,实际播放的时间戳基准仍有偏差,-c copy模式下会保留该偏移,拼接后累积导致时长超出预期。 - 帧时长对齐问题:原视频为50fps(每帧理论时长0.02秒),单段1.66秒对应83帧,但实际视频的帧时间戳未严格按标准间隔递增,最后一帧时长被延长。两段视频的非标准帧时长叠加,造成总时长偏差。
- Copy模式局限:
-c copy仅复制流数据,不重新生成时间戳或修正容器元数据,原视频的时间戳问题会直接传递到输出视频。MoviePy底层依赖FFmpeg,因此也出现相同问题。
解决方法
方法1:重新编码修正时间戳
放弃-c copy,让FFmpeg重新编码视频与音频,生成标准时间戳:
ffmpeg -f concat -i inputs.txt -c:v libx264 -c:a aac mergedVideo.mp4
此方法确保时间戳严格对齐,输出时长符合预期,但耗时较长。
方法2:修复原视频时间戳后拼接
先处理原视频,去除编辑列表并修正时间戳,再进行拼接:
- 修复原视频:
ffmpeg -i 0.mp4 -c copy -movflags +faststart -ignore_editlist 1 fixed_0.mp4
- 更新
inputs.txt内容为两行file 'fixed_0.mp4',再执行拼接:
ffmpeg -f concat -i inputs.txt -c copy mergedVideo.mp4
方法3:使用concat滤镜替代demuxer
concat滤镜能精确控制时间戳与流拼接,无需依赖输入文件元数据:
ffmpeg -i 0.mp4 -i 0.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a]" -map "[v]" -map "[a]" mergedVideo.mp4
此方法自动处理时间戳对齐,输出时长准确。
内容的提问来源于stack exchange,提问作者Rostyslav Mosorov
相关产品推荐
相关产品推荐

