Skip to content

MP4 vfr video stream does not have accurate duration #2335

Description

@oakaigh

PyAV version: 17.0.1

Code to reproduce:

import av
import av.codec.context
from fractions import Fraction

path = "test.mp4"
timescale = 360_000
tb = Fraction(1, timescale)

# durations = [10, 10]
# durations = [10, 20]
# durations = [10, 11, 13]
durations = [10, 11, 13, 21]
# durations = [1012 for _ in range(21)]
# durations = [1001, 997, 1031, 1009, 1013, 991, 1049]
pts = [0]
for d in durations[:-1]:
    pts.append(pts[-1] + d)

expected_stream_duration = sum(durations)

c = av.open(
    path,
    mode="w",
    container_options={
        "movie_timescale": str(timescale),
        "video_track_timescale": str(timescale),
    #   "movflags": "+negative_cts_offsets",
    #   "use_editlist": "0",
    #   "use_editlist": "auto",
    },
)

s = c.add_stream("libx264")
s.width = 480
s.height = 320
s.pix_fmt = "yuv420p"
s.time_base = tb
s.codec_context.time_base = tb
s.codec_context.flags |= av.codec.context.Flags.frame_duration
# s.codec_context.max_b_frames = 0
s.options = {
    # "preset": "ultrafast",
    # "tune": "zerolatency",
    # "x264-params": "bframes=0",
}

for p, d in zip(pts, durations):
    f = av.VideoFrame(480, 320, "yuv420p")
    f.pts = p
    f.duration = d
    f.time_base = tb

    for packet in s.encode(f):
        c.mux(packet)

for packet in s.encode():
    c.mux(packet)

c.close()

c = av.open(path)
(s,) = c.streams.video
actual_stream_duration = s.duration

print("stream.time_base:", s.time_base)
print("expected stream.duration:", expected_stream_duration)
print("actual stream.duration:  ", actual_stream_duration)
print("delta:                   ", actual_stream_duration - expected_stream_duration)

assert s.time_base == tb
assert actual_stream_duration == expected_stream_duration

Output

stream.time_base: 1/360000
expected stream.duration: 55
actual stream.duration:   44
delta:                    -11
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[50], line 71
     68 print("delta:                   ", actual_stream_duration - expected_stream_duration)
     70 assert s.time_base == tb
---> 71 assert actual_stream_duration == expected_stream_duration

AssertionError:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions