From 7bb47e497466b2800097e0da834e0d414373bd3109056236244881282e62d783 Mon Sep 17 00:00:00 2001 From: copecone Date: Thu, 15 Oct 2026 11:27:58 +0900 Subject: [PATCH] Fix Zero Duration Of Last Video Frame --- Util/FFmpeg/FFmpegNativeEncoder.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Util/FFmpeg/FFmpegNativeEncoder.cs b/Util/FFmpeg/FFmpegNativeEncoder.cs index 3dca24c..adff6ce 100644 --- a/Util/FFmpeg/FFmpegNativeEncoder.cs +++ b/Util/FFmpeg/FFmpegNativeEncoder.cs @@ -1594,6 +1594,16 @@ namespace ADOFAIRenderer.Util.FFmpeg if (response < 0) throw new Exception($"Error occurred while receiving packet from encoder: {GetFFmpegErrorString(response)} (Code: {response})"); + // Packet duration: 1 tick of the codec time base (1 / framerate), the display time of one frame + // at the constant frame rate of the output. Applied when the encoder leaves it unknown (0). + // The encoders output 0 here because libavcodec clears the frame duration + // unless AV_CODEC_FLAG_FRAME_DURATION is set. + // The mp4/mov muxer takes the length of the last sample from the duration of the last packet; + // with 0 the last frame has no display time and the edit list ends before it. + // Reference: https://github.com/FFmpeg/FFmpeg/blob/release/8.0/libavcodec/encode.c (encode_send_frame_internal: frame duration) + // Reference: https://github.com/FFmpeg/FFmpeg/blob/release/8.0/libavformat/movenc.c (ff_mov_write_packet: track_duration) + if (_pPacket->duration <= 0) + _pPacket->duration = 1; // Convert PTS/DTS from codec timebase → stream timebase ffmpeg.av_packet_rescale_ts(_pPacket, _pCodecContext->time_base, _pVideoStream->time_base); _pPacket->stream_index = _pVideoStream->index;