diff --git a/av/video/stream.py b/av/video/stream.py index be1fcaf9d..ed8a79aea 100644 --- a/av/video/stream.py +++ b/av/video/stream.py @@ -63,6 +63,8 @@ def decode(self, packet: Packet | None = None): @cython.cfunc def _finalize_for_output(self): Stream._finalize_for_output(self) + if self.codec_context is not None: + self.ptr.avg_frame_rate = self.codec_context.ptr.framerate # avcodec_parameters_from_context() overwrites codecpar.coded_side_data, # so inject the display matrix after it, before avformat_write_header(). if self.codec_context is not None and self._has_display_matrix: diff --git a/tests/test_encode.py b/tests/test_encode.py index 294cc815b..e6015ae1b 100644 --- a/tests/test_encode.py +++ b/tests/test_encode.py @@ -162,6 +162,26 @@ def test_encoding_with_pts(self) -> None: assert packet.time_base == Fraction(1, 24) output.mux(packet) + def test_set_rate_after_add_stream(self) -> None: + path = self.sandboxed("deferred_rate.mp4") + + with av.open(path, "w") as output: + stream = output.add_stream("mpeg4") + stream.codec_context.framerate = Fraction(30, 1) + stream.width = 16 + stream.height = 16 + + for i in range(30): + frame = VideoFrame(16, 16, "yuv420p") + frame.pts = i + frame.time_base = Fraction(1, 30) + output.mux(stream.encode(frame)) + + output.mux(stream.encode(None)) + + with av.open(path) as input_: + assert input_.streams.video[0].average_rate == 30 + def test_encoding_with_unicode_filename(self) -> None: path = self.sandboxed("¢∞§¶•ªº.mov")