Currently, I am trying to use python with FFmpeg to query rtsp data which the original format is h264.
The information of the live stream video is, fps:29; resolution: 1280*720.
I wish that I can query the data as the same format "h264" and put into a python queue in order to the future use.
Here is my code:
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)))
However, after I run this program about 10 second, my console shows the warning message:
[rtsp @ 0000020be0fbb9c0] max delay reached. need to consume packet
[rtsp @ 0000020be0fbb9c0] RTP: missed 127 packets
It seems like my command doesn't type appropriately.
Could you kindly give me some suggestion about how to deal with this problem?
Thank you very much
Assuming you want to grab the video stream without modifying the data, you need to set different set of arguments to FFmpeg:
"-c:v", "h264"
as input argument (before "-i"
), for informing FFmpeg that the input is h264
video stream. "-c:v", "copy"
as output argument (after "-i"
), so the FFmpeg copies the input video stream to the output PIPE, without modifications (without decoding and encoding). "-f", "h264"
as output argument, for setting PIPE output format to h264
. Here is a working code sample (please read the comments):
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())
I tested the code using public RTSP Streaming and using a generated synthetic video file (code for testing with file is commented).
The code stores the output to vid_from_queue.264
.
The .264
file is playable - the file format is an elementary h264 video stream.