Python FFmpeg 查询 rtsp 太慢
Python FFmpeg query rtsp too slow
目前,我正在尝试使用python和FFmpeg来查询原始格式为h264的rtsp数据。
直播视频信息为,fps:29;分辨率:1280*720.
我希望我可以查询相同格式的数据"h264"并放入python队列中以备将来使用。
这是我的代码:
class CCTVReader(threading.Thread):
def __init__(self, queue, URL, fps=29):
super().__init__()
self.queue = queue
self.command = ["ffmpeg", "-y",
"-hwaccel", "nvdec",
"-c:v", "h264_cuvid",
"-vsync", "0",
"-max_delay", "500000",
"-reorder_queue_size", "10000",
"-i", "rtsp://xxx.xxx.xxx.xxx:xxx/Streaming/Channels/101?transportmode=multicast",
"-pix_fmt", "yuv420p",
"-preset", "slow",
"-an", "-sn",
"-vf", "fps=29",
"-"]
def run(self):
pipe = sp.Popen(self.command, stdout = sp.PIPE, bufsize=1024**3, shell=True)
timer = time.time()
counter = 0
while True:
self.queue.put(pipe.stdout.read(int(1280*720*6//4)))
但是,在我 运行 这个程序大约 10 秒后,我的控制台显示警告消息:
[rtsp @ 0000020be0fbb9c0] max delay reached. need to consume packet
[rtsp @ 0000020be0fbb9c0] RTP: missed 127 packets
看来我的命令输入不正确。
你能给我一些关于如何处理这个问题的建议吗?
非常感谢
假设你想在不修改数据的情况下抓取视频流,你需要为 FFmpeg 设置不同的参数集:
- 设置
"-c:v", "h264"
作为输入参数(在"-i"
之前),用于通知FFmpeg输入是h264
视频流。
- 将
"-c:v", "copy"
设置为输出参数(在 "-i"
之后),因此 FFmpeg 将输入视频流复制到输出 PIPE,无需修改(无需解码和编码)。
- 设置
"-f", "h264"
作为输出参数,用于将PIPE输出格式设置为h264
。
这是一个工作代码示例(请阅读评论):
import ffmpeg
import numpy as np
import subprocess as sp
import threading
import queue
class CCTVReader(threading.Thread):
def __init__(self, q, in_stream):
super().__init__()
self.q = q
self.command = ["ffmpeg",
"-c:v", "h264", # Tell ffmpeg that input stream codec is h264
"-i", in_stream, # Read stream from file vid.264
"-c:v", "copy", # Tell ffmpeg to copy the video stream as is (without decding and encoding)
"-an", "-sn", # No audio an no subtites
"-f", "h264", # Define pipe format to be h264
"-"] # Output is a pipe
def run(self):
pipe = sp.Popen(self.command, stdout=sp.PIPE, bufsize=1024**3) # Don't use shell=True (you don't need to execute the command through the shell).
# while True:
for i in range(100): # Read up to 100KBytes for testing
data = pipe.stdout.read(1024) # Read data from pip in chunks of 1024 bytes
self.q.put(data)
# Break loop if less than 1024 bytes read (not going to work with CCTV, but works with input file)
if len(data) < 1024:
break
try:
pipe.wait(timeout=1) # Wait for subprocess to finish (with timeout of 1 second).
except sp.TimeoutExpired:
pipe.kill() # Kill subprocess in case of a timeout (there should be a timeout because input stream still lives).
# Build synthetic video, for testing begins:
################################################
# width, height = 1280, 720
# in_stream = "vid.264"
# sp.Popen("ffmpeg -y -f lavfi -i testsrc=size=1280x720:duration=5:rate=1 -c:v libx264 -crf 23 -pix_fmt yuv420p " + in_stream).wait()
################################################
#in_stream = "rtsp://xxx.xxx.xxx.xxx:xxx/Streaming/Channels/101?transportmode=multicast",
#Use public RTSP Streaming for testing
in_stream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"
q = queue.Queue()
cctv_reader = CCTVReader(q, in_stream)
cctv_reader.start()
cctv_reader.join()
if q.empty():
print("There is a problem (queue is empty)!!!")
else:
# Write data from queue to file vid_from_queue.264 (for testingg)
with open("vid_from_queue.264", "wb") as queue_save_file:
while not q.empty():
queue_save_file.write(q.get())
我使用 public RTSP Streaming 并使用生成的合成视频文件测试了代码(注释了用于测试文件的代码)。
代码将输出存储到 vid_from_queue.264
。
.264
文件可以播放 - 文件格式是基本的 h264 视频流。
这是抓取的视频流的最后一帧:
目前,我正在尝试使用python和FFmpeg来查询原始格式为h264的rtsp数据。
直播视频信息为,fps:29;分辨率:1280*720.
我希望我可以查询相同格式的数据"h264"并放入python队列中以备将来使用。
这是我的代码:
class CCTVReader(threading.Thread):
def __init__(self, queue, URL, fps=29):
super().__init__()
self.queue = queue
self.command = ["ffmpeg", "-y",
"-hwaccel", "nvdec",
"-c:v", "h264_cuvid",
"-vsync", "0",
"-max_delay", "500000",
"-reorder_queue_size", "10000",
"-i", "rtsp://xxx.xxx.xxx.xxx:xxx/Streaming/Channels/101?transportmode=multicast",
"-pix_fmt", "yuv420p",
"-preset", "slow",
"-an", "-sn",
"-vf", "fps=29",
"-"]
def run(self):
pipe = sp.Popen(self.command, stdout = sp.PIPE, bufsize=1024**3, shell=True)
timer = time.time()
counter = 0
while True:
self.queue.put(pipe.stdout.read(int(1280*720*6//4)))
但是,在我 运行 这个程序大约 10 秒后,我的控制台显示警告消息:
[rtsp @ 0000020be0fbb9c0] max delay reached. need to consume packet
[rtsp @ 0000020be0fbb9c0] RTP: missed 127 packets
看来我的命令输入不正确。
你能给我一些关于如何处理这个问题的建议吗?
非常感谢
假设你想在不修改数据的情况下抓取视频流,你需要为 FFmpeg 设置不同的参数集:
- 设置
"-c:v", "h264"
作为输入参数(在"-i"
之前),用于通知FFmpeg输入是h264
视频流。 - 将
"-c:v", "copy"
设置为输出参数(在"-i"
之后),因此 FFmpeg 将输入视频流复制到输出 PIPE,无需修改(无需解码和编码)。 - 设置
"-f", "h264"
作为输出参数,用于将PIPE输出格式设置为h264
。
这是一个工作代码示例(请阅读评论):
import ffmpeg
import numpy as np
import subprocess as sp
import threading
import queue
class CCTVReader(threading.Thread):
def __init__(self, q, in_stream):
super().__init__()
self.q = q
self.command = ["ffmpeg",
"-c:v", "h264", # Tell ffmpeg that input stream codec is h264
"-i", in_stream, # Read stream from file vid.264
"-c:v", "copy", # Tell ffmpeg to copy the video stream as is (without decding and encoding)
"-an", "-sn", # No audio an no subtites
"-f", "h264", # Define pipe format to be h264
"-"] # Output is a pipe
def run(self):
pipe = sp.Popen(self.command, stdout=sp.PIPE, bufsize=1024**3) # Don't use shell=True (you don't need to execute the command through the shell).
# while True:
for i in range(100): # Read up to 100KBytes for testing
data = pipe.stdout.read(1024) # Read data from pip in chunks of 1024 bytes
self.q.put(data)
# Break loop if less than 1024 bytes read (not going to work with CCTV, but works with input file)
if len(data) < 1024:
break
try:
pipe.wait(timeout=1) # Wait for subprocess to finish (with timeout of 1 second).
except sp.TimeoutExpired:
pipe.kill() # Kill subprocess in case of a timeout (there should be a timeout because input stream still lives).
# Build synthetic video, for testing begins:
################################################
# width, height = 1280, 720
# in_stream = "vid.264"
# sp.Popen("ffmpeg -y -f lavfi -i testsrc=size=1280x720:duration=5:rate=1 -c:v libx264 -crf 23 -pix_fmt yuv420p " + in_stream).wait()
################################################
#in_stream = "rtsp://xxx.xxx.xxx.xxx:xxx/Streaming/Channels/101?transportmode=multicast",
#Use public RTSP Streaming for testing
in_stream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"
q = queue.Queue()
cctv_reader = CCTVReader(q, in_stream)
cctv_reader.start()
cctv_reader.join()
if q.empty():
print("There is a problem (queue is empty)!!!")
else:
# Write data from queue to file vid_from_queue.264 (for testingg)
with open("vid_from_queue.264", "wb") as queue_save_file:
while not q.empty():
queue_save_file.write(q.get())
我使用 public RTSP Streaming 并使用生成的合成视频文件测试了代码(注释了用于测试文件的代码)。
代码将输出存储到 vid_from_queue.264
。
.264
文件可以播放 - 文件格式是基本的 h264 视频流。
这是抓取的视频流的最后一帧: