我使用 PyAV 库,因为它是 Python 可用的最快库之一。
这是我想使用的一个简单的代码示例:
import av
video = av.open("My_Super_Video.mp4")
total_frames = # ????
for i, frame in enumerate(video.decode(video=0)):
img = frame.to_image() # PIL image
print("Frame: %d/%d ..." % (i, total_frames))
Run Code Online (Sandbox Code Playgroud)
显然我可以使用其他库来加载该库,但是如果可能的话,我更喜欢使用 PyAV,因为它的处理速度很快。
问题1:用PyAV可以获取帧数吗?如果是,怎么办?
问题2:在这种情况下,我会考虑使用另一个库来逐帧加载和处理视频。哪个库可以让我以尽可能最高的速度完成上述操作。我知道以下内容,但不知道它们如何比较:
我有一个 Python 程序,它通过网络接收一系列 H264 视频帧,我想要显示这些视频帧,也可以选择录制这些帧。摄像机以 30FPS 的速度进行录制并尽可能快地发送帧,由于网络条件的变化,该帧率不会始终保持在 30FPS;有时它会落后然后赶上,很少会完全丢帧。
“显示”部分很简单;我不需要关心时间或流元数据,只需在帧到达时尽快显示它们:
input = av.open(get_video_stream())
for packet in input.demux(video=0):
for frame in packet.decode():
# A bunch of numpy and pygame code here to convert the frame to RGB
# row-major and blit it to the screen
Run Code Online (Sandbox Code Playgroud)
“记录”部分看起来应该很简单:
input = av.open(get_video_stream())
output = av.open(filename, 'w')
output.add_stream(template=input.streams[0])
for packet in input.demux(video=0):
for frame in packet.decode():
# ...display code...
packet.stream = output.streams[0]
output.mux_one(packet)
output.close()
Run Code Online (Sandbox Code Playgroud)
事实上,这会生成一个包含所有帧的有效 MP4 文件,如果我用它回放mplayer -fps 30它,效果很好。但这-fps 30是绝对必要的: …
是否可以使用 PyAV 将视频直接读入 3D Numpy?目前,我正在循环每一帧:
i = 0
container = av.open('myvideo.avi')
for frame in container.decode(video=0):
if i == 0: V = np.array(frame.to_ndarray(format='gray'))
else: V = np.dstack((V, np.array(frame.to_ndarray(format='gray'))))
i += 1
Run Code Online (Sandbox Code Playgroud)
第一帧定义了一个2D Numpy数组(i=0);每个后续帧 (i>0) 都使用 堆栈到第一个数组上np.dstack。理想情况下,我想一次性将整个视频读入 3D Numpy 灰度帧数组。
数据是通过套接字接收的,没有更多的外壳,它们是纯 IPB 帧,以 NAL 标头(类似于 00 00 00 01)开头。我现在使用 pyav 来解码帧,但我只能在收到第二个 pps 信息(在关键帧中)后解码数据(因此我发送到解码线程的数据块可以以 pps 和 sps 开头),否则解码()或demux()将返回错误“不存在的PPS 0引用的decode_slice_header错误”。
我想将数据馈送到可以记住前一个 P 帧的支持解码器,因此在馈送一个 B 帧后,解码器返回一个已解码的视频帧。或者某种形式的 IO,可以作为容器打开并继续由另一个线程向其中写入数据。
这是我的关键代码:
#read thread... read until get a key frame, then make a new io.BytesIO() to store the new data.
rawFrames = io.BytesIO()
while flag_get_keyFrame:()
....
content= socket.recv(2048)
rawFrames.write(content)
....
#decode thread... decode content between two key frames
....
rawFrames.seek(0)
container = av.open(rawFrames)
for packet in container.demux():
for frame in packet.decode():
self.frames.append(frame)
....
Run Code Online (Sandbox Code Playgroud)
我的代码将播放视频,但有 3~4 秒的延迟。所以我不会把所有的东西都放在这里,因为我知道它实际上并没有达到我想要实现的目标。我想在收到第一个关键帧后播放视频,并在收到后立即解码以下帧。Pyav opencv …
如何从 pts 和 time_base 或持续时间获取视频或 rtmp 流中帧的时间戳?多谢!
import av
def init_input(file_name):
global a
container = av.open(file_name)
a = container.duration
return container.decode(video=0)
url = "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov"
stream1 = init_input(url)
for frame1 in stream1:
print(frame1.pts)
print(frame1.time_base)
Run Code Online (Sandbox Code Playgroud)
PS:frame.time与实际时间不正确