简体   繁体   English

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

[英]OpenCV read video files with multiple streams/tracks

I have a video file that contains multiple streams as shown below using VLC media player: Video Information我有一个包含多个流的视频文件,如下所示,使用 VLC 媒体播放器:视频信息

When I try to read it using Python + OpenCV using the following code:当我尝试使用 Python + OpenCV 使用以下代码阅读它时:

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

I can only read the first track of the video.我只能阅读视频的第一首曲目。 How can I read all the video tracks at the same time?如何同时读取所有视频轨道?

As far as I could tell, OpenCV does not allow choosing video stream, so this is not possible.据我所知,OpenCV 不允许选择视频 stream,所以这是不可能的。 However, you can do it rather easily with ffmpeg command line utilities:但是,您可以使用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)

Note that the code reads all video streams and assumes that each has the same resolution.请注意,代码读取所有视频流并假设每个视频流具有相同的分辨率。 It lacks proper error handling but got the job done in my scientific project.它缺乏适当的错误处理,但在我的科学项目中完成了工作。

For example, reading stereoscopic stream:比如读取立体stream:

import matplotlib.pyplot as plt

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM