Python OpenCV cap.read() 解压缩压缩帧?
Python OpenCV cap.read() unpacks compressed frames?
你好 Stack 社区,
我正在从 IP 摄像机流中读取帧并将它们存储在列表中,以便稍后创建视频文件。
我正在使用 python OpenCV 库,它运行良好,但是 ..
从 IP 摄像机发送的帧应该有 h264 压缩,但是当我检查帧的大小时,它们是 25 MB 的 4K 流。我运行 很快内存不足。
这不是代码,但与它类似:
import cv2
cap = cv2.VideoCapture(0)
list = []
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
frame = cv2.flip(frame,0)
list.append(frame)
cap.release()
out = cv2.VideoWriter('output.avi', -1, 20.0, (640,480))
for frm in list:
out.write(frm)
out.release()
cv2.destroyAllWindows()
好像ret, frame = cap.read()
解压了框架?
这会在每个循环中产生额外的处理,并且对于我对脚本的意图来说是不必要的,有没有办法在不解压缩帧的情况下检索帧?
提前为我可能的无知道歉。
我构建了一个测试示例,用于使用 ffmpeg-python 将 h264 流读取到内存中。
示例从文件中读取数据(我没有相机来测试它)。
我还测试了从 RTSP 流读取的代码。
代码如下(请阅读评论):
import ffmpeg
import threading
import io
in_filename = 'test_vid.264' # Input file for testing (".264" or ".h264" is a convention for elementary h264 video stream file)
## Build synthetic video, for testing:
################################################
# ffmpeg -y -r 10 -f lavfi -i testsrc=size=192x108:rate=1 -c:v libx264 -crf 23 -t 50 test_vid.264
width, height = 192, 108
(
ffmpeg
.input('testsrc=size={}x{}:rate=1'.format(width, height), f='lavfi')
.output(in_filename, vcodec='libx264', crf=23, t=50)
.overwrite_output()
.run()
)
################################################
# Use ffprobe to get video frames resolution
###############################################
# p = ffmpeg.probe(in_filename, select_streams='v');
# width = p['streams'][0]['width']
# height = p['streams'][0]['height']
###############################################
# Stream the video as array of bytes (simulate the stream from the camera for testing)
###############################################
## https://github.com/kkroening/ffmpeg-python/blob/master/examples/README.md
#sreaming_process = (
# ffmpeg
# .input(in_filename)
# .video # Video only (no audio).
# .output('pipe:', format='h264')
# .run_async(pipe_stdout=True) # Run asynchronous, and stream to stdout
#)
###############################################
# Read from stdout in chunks of 16K bytes
def reader():
chunk_len_in_byte = 16384 # I don't know what is the optimal chunk size
in_bytes = chunk_len_in_byte
# Read until number of bytes read are less than chunk_len_in_byte
# Also stop after 10000 chucks (just for testing)
chunks_counter = 0
while (chunks_counter < 10000):
in_bytes = process.stdout.read(chunk_len_in_byte) # Read 16KBytes from PIPE.
stream.write(in_bytes) # Write data to In-memory bytes streams
chunks_counter += 1
if len(in_bytes) < chunk_len_in_byte:
break
# Use public RTSP Streaming for testing
# in_stream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"
# Execute ffmpeg as asynchronous sub-process.
# The input is in_filename, and the output is a PIPE.
# Note: you should replace the input from file to camera (I might forgot an argument that tells ffmpeg to expect h264 input stream).
process = (
ffmpeg
.input(in_filename) #.input(in_stream)
.video
.output('pipe:', format='h264')
.run_async(pipe_stdin=True, pipe_stdout=True)
)
# Open In-memory bytes streams
stream = io.BytesIO()
thread = threading.Thread(target=reader)
thread.start()
# Join thread, and wait for processes to end.
thread.join()
try:
process.wait(timeout=5)
except sp.TimeoutExpired:
process.kill() # Kill subprocess in case of a timeout (there might be a timeout because input stream still lives).
#sreaming_process.wait() # sreaming_process is used
stream.seek(0) #Seek to beginning of stream.
# Write result to "in_vid.264" file for testing (the file is playable).
with open("in_vid.264", "wb") as f:
f.write(stream.getvalue())
如果你觉得有用,我可能会在代码前添加一些背景描述。
请让我知道代码是否适用于相机,以及您必须修改的内容。
你好 Stack 社区,
我正在从 IP 摄像机流中读取帧并将它们存储在列表中,以便稍后创建视频文件。 我正在使用 python OpenCV 库,它运行良好,但是 .. 从 IP 摄像机发送的帧应该有 h264 压缩,但是当我检查帧的大小时,它们是 25 MB 的 4K 流。我运行 很快内存不足。 这不是代码,但与它类似:
import cv2
cap = cv2.VideoCapture(0)
list = []
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
frame = cv2.flip(frame,0)
list.append(frame)
cap.release()
out = cv2.VideoWriter('output.avi', -1, 20.0, (640,480))
for frm in list:
out.write(frm)
out.release()
cv2.destroyAllWindows()
好像ret, frame = cap.read()
解压了框架?
这会在每个循环中产生额外的处理,并且对于我对脚本的意图来说是不必要的,有没有办法在不解压缩帧的情况下检索帧?
提前为我可能的无知道歉。
我构建了一个测试示例,用于使用 ffmpeg-python 将 h264 流读取到内存中。
示例从文件中读取数据(我没有相机来测试它)。
我还测试了从 RTSP 流读取的代码。
代码如下(请阅读评论):
import ffmpeg
import threading
import io
in_filename = 'test_vid.264' # Input file for testing (".264" or ".h264" is a convention for elementary h264 video stream file)
## Build synthetic video, for testing:
################################################
# ffmpeg -y -r 10 -f lavfi -i testsrc=size=192x108:rate=1 -c:v libx264 -crf 23 -t 50 test_vid.264
width, height = 192, 108
(
ffmpeg
.input('testsrc=size={}x{}:rate=1'.format(width, height), f='lavfi')
.output(in_filename, vcodec='libx264', crf=23, t=50)
.overwrite_output()
.run()
)
################################################
# Use ffprobe to get video frames resolution
###############################################
# p = ffmpeg.probe(in_filename, select_streams='v');
# width = p['streams'][0]['width']
# height = p['streams'][0]['height']
###############################################
# Stream the video as array of bytes (simulate the stream from the camera for testing)
###############################################
## https://github.com/kkroening/ffmpeg-python/blob/master/examples/README.md
#sreaming_process = (
# ffmpeg
# .input(in_filename)
# .video # Video only (no audio).
# .output('pipe:', format='h264')
# .run_async(pipe_stdout=True) # Run asynchronous, and stream to stdout
#)
###############################################
# Read from stdout in chunks of 16K bytes
def reader():
chunk_len_in_byte = 16384 # I don't know what is the optimal chunk size
in_bytes = chunk_len_in_byte
# Read until number of bytes read are less than chunk_len_in_byte
# Also stop after 10000 chucks (just for testing)
chunks_counter = 0
while (chunks_counter < 10000):
in_bytes = process.stdout.read(chunk_len_in_byte) # Read 16KBytes from PIPE.
stream.write(in_bytes) # Write data to In-memory bytes streams
chunks_counter += 1
if len(in_bytes) < chunk_len_in_byte:
break
# Use public RTSP Streaming for testing
# in_stream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"
# Execute ffmpeg as asynchronous sub-process.
# The input is in_filename, and the output is a PIPE.
# Note: you should replace the input from file to camera (I might forgot an argument that tells ffmpeg to expect h264 input stream).
process = (
ffmpeg
.input(in_filename) #.input(in_stream)
.video
.output('pipe:', format='h264')
.run_async(pipe_stdin=True, pipe_stdout=True)
)
# Open In-memory bytes streams
stream = io.BytesIO()
thread = threading.Thread(target=reader)
thread.start()
# Join thread, and wait for processes to end.
thread.join()
try:
process.wait(timeout=5)
except sp.TimeoutExpired:
process.kill() # Kill subprocess in case of a timeout (there might be a timeout because input stream still lives).
#sreaming_process.wait() # sreaming_process is used
stream.seek(0) #Seek to beginning of stream.
# Write result to "in_vid.264" file for testing (the file is playable).
with open("in_vid.264", "wb") as f:
f.write(stream.getvalue())
如果你觉得有用,我可能会在代码前添加一些背景描述。
请让我知道代码是否适用于相机,以及您必须修改的内容。