Replies: 10 comments
-
|
Beta Was this translation helpful? Give feedback.
-
The problem is that it will cause video freezes and the video cannot be played at fps speed. The result of my analysis is that the speed of tbr must be consistent with the fps speed to avoid video freezes. In addition, I will write a demo to test it. @WyattBlue |
Beta Was this translation helpful? Give feedback.
-
This is a demo I wrote. As long as I enable the add_video_pts_dts method and set pts and dts myself, the tbr value in the rtmp stream will be greater than the fps value and become 100. As long as I do not set pts and dts myself, the tbr value will be the normal sum. Consistent fps @WyattBlue You try this demo import fractions
import os
import queue
import threading
import time
import av
class TestAvLive:
def __init__(self, rtsp, rtmp):
self.frame_queue = queue.Queue()
self.video_pts = 10
self.audio_pts = 10
self.frame_count = 0
self.rtsp = rtsp
self.rtmp = rtmp
def test_in(self):
options = {'buffer_size': '1024000', 'rtsp_transport': 'tcp', 'stimeout': '20000000', 'max_delay': '500000'}
self.in_video = av.open(self.rtsp, 'r', format=None, options=options, metadata_errors='strict')
self.in_video.streams.video[0].thread_type = "AUTO"
self.in_video_stream = self.in_video.streams.video[0]
self.in_audio_stream = self.in_video.streams.audio[0]
for packet in self.in_video.demux(self.in_video_stream, self.in_audio_stream):
if packet.stream.type == 'video':
for frame in packet.decode():
self.frame_queue.put((frame, 'video'))
elif packet.stream.type == 'audio':
self.frame_queue.put((packet, 'audio'))
def get_frame_duration(self):
in_video_stream = self.in_video_stream
in_audio_stream = self.in_audio_stream
print(in_video_stream.time_base, in_audio_stream.time_base)
try:
video_frame_duration = in_video_stream.time_base.denominator / 25
audio_frame_duration = in_audio_stream.time_base.denominator / in_audio_stream.rate
except Exception as e:
video_frame_duration = 3600
audio_frame_duration = 1000
print(video_frame_duration, audio_frame_duration)
return int(video_frame_duration), audio_frame_duration
def add_video_pts_dts(self, packet):
return packet
for i in packet:
i.pts = i.dts = self.video_pts
self.video_pts += self.video_frame_duration
return packet
def test_out(self):
time.sleep(2)
audio_rate = 44100
self.video_frame_duration, self.audio_frame_duration = self.get_frame_duration()
out_archive = av.open(self.rtmp, 'w', format='flv')
encode_m = "h264_nvenc" if os.name == 'posix' else "h264"
archive_video_stream = out_archive.add_stream(encode_m, rate=25, options={"framerate": '25'})
archive_audio_stream = out_archive.add_stream('aac', rate=audio_rate)
archive_video_stream.height = 1080
archive_video_stream.width = 1920
archive_video_stream.bit_rate = 3072000
archive_video_stream.pix_fmt = 'nv12'
archive_video_stream.gop_size = 60
archive_video_stream.time_base = fractions.Fraction(1, 25)
print(archive_video_stream.time_base)
archive_video_stream.framerate = fractions.Fraction(25, 1)
archive_audio_stream.time_base = fractions.Fraction(1, audio_rate)
print(archive_video_stream.time_base, archive_audio_stream.time_base)
while True:
frame, data_type = self.frame_queue.get()
if data_type == 'video':
print("video pts:{} dts:{}".format(frame.pts, frame.dts))
undistort_frame = frame.to_ndarray(format='bgr24')
frame = av.VideoFrame.from_ndarray(undistort_frame, format='bgr24')
out_video_packet = self.add_video_pts_dts(archive_video_stream.encode(frame))
out_archive.mux(out_video_packet)
self.frame_count += 1
elif data_type == 'audio':
out_archive.mux(frame)
def run(self):
threads = [
threading.Thread(target=self.test_in),
threading.Thread(target=self.test_out),
]
[thread.start() for thread in threads]
[thread.join() for thread in threads]
if __name__ == '__main__':
rtsp = "rtsp://admin:abc@[email protected]:554/ch1/stream1"
rtmp = 'rtmp://192.168.1.91:1935/live/6666/9944'
t = TestAvLive(rtsp,rtmp)
t.run()
|
Beta Was this translation helpful? Give feedback.
-
When I run it, I get this. I don't think it show cases the actual problem
|
Beta Was this translation helpful? Give feedback.
-
You need to modify the addresses of rtmp and rtsp in the demo
|
Beta Was this translation helpful? Give feedback.
-
If you enable the add_video_pts_dts method and set pts and dts yourself, it will cause tbr to become 100 instead of consistent with the value of fps, which will cause the video stream to freeze. So my question is how to control the value of this tbr
|
Beta Was this translation helpful? Give feedback.
-
Does this only happen in rtmp inputs? Can you replicate this in other rtmp streams? |
Beta Was this translation helpful? Give feedback.
-
Yes, I tested other rtmp streams and it was the same. I tried to write the input rtmp stream to an mp4 video file and it was the same.
This is the output result
When I try to change the time base to match the frame rate
|
Beta Was this translation helpful? Give feedback.
-
When I turn off the custom setting pts, the output mp4 file seems to become normal, but I
When I turn off the custom pts setting and set the time scale to 90000, the output mp4 file seems to be normal. But if I output the rtmp stream, set the time scale to 90000 and turn off the custom pts setting, the picture will become very stuck. Only when the time scale is set to the same as the pts will it not be stuck. I don't understand why this happens. |
Beta Was this translation helpful? Give feedback.
-
@WyattBlue Hello, I roughly know the problem. It is because the time base scale of rtmp is 1/1000. If I set it greater than 1000, it will cause abnormal playback of rtmp stream, so it must be set to 1000 or set to the same size as the frame rate. For this problem, can pyav make a judgment? If in write mode and flv mode, the time scale of the video stream cannot be greater than 1000, and the default is 1000 |
Beta Was this translation helpful? Give feedback.
-
When I set the pts and dts myself, the btr will become 100 uncontrollably. When I don't modify the pts and dts, the value of the btr is consistent with the fps.
When I modify pts and dts
When I don't modify pts and dts
I also set time_base:
Beta Was this translation helpful? Give feedback.
All reactions