OpenCV读取具有多个流/音轨的视频文件



我有一个视频文件,它包含多个流,如下所示,使用VLC媒体播放器:视频信息

当我尝试使用Python+OpenCV阅读它时,使用以下代码:

vidObj = cv2.VideoCapture("video.avi")
ret, frame = vidObj.read()

我只能阅读视频的第一首曲目。如何同时读取所有视频曲目?

据我所知,OpenCV不允许选择视频流,所以这是不可能的。但是,使用ffmpeg命令行实用程序可以很容易地做到这一点:

import numpy as np
import json
import subprocess
def videoInfo(filename):
proc = subprocess.run([
*"ffprobe -v quiet -print_format json -show_format -show_streams".split(),
filename
], capture_output=True)
proc.check_returncode()
return json.loads(proc.stdout)
def readVideo(filename):
cmd = ["ffmpeg", "-i", filename]
streams = 0
for stream in videoInfo(filename)["streams"]:
index = stream["index"]
if stream["codec_type"] == "video":
width = stream["width"]
height = stream["height"]
cmd += "-map", f"0:{index}"
streams = streams + 1
cmd += "-f", "rawvideo", "-pix_fmt", "rgb24", "-"
shape = np.array([streams, height, width, 3])
with subprocess.Popen(cmd, stdout=subprocess.PIPE) as proc:
while True:
data = proc.stdout.read(shape.prod())  # One byte per each element
if not data:
return
yield np.frombuffer(data, dtype=np.uint8).reshape(shape)

请注意,该代码读取所有视频流,并假设每个视频流具有相同的分辨率。它缺乏正确的错误处理,但在我的科学项目中完成了任务。

例如,读取立体流:

import matplotlib.pyplot as plt
for left, right in readVideo("testvideo.mkv"):
plt.imshow(left)
plt.show()
plt.imshow(right)
plt.show()

最新更新