OpenCV 不会从 RTMP 源捕获帧,而 FFmpeg 会

OpenCV won't capture frames from a RTMP source, while FFmpeg does

我的目标是每秒从 rtmp 流中捕获一个帧,并使用 OpenCV 对其进行处理。我正在使用 FFmpeg 版本 N-71899-g6ef3426 和带有 Java 接口的 OpenCV 2.4.9(但我首先尝试使用 Python)。 目前,我只能采取简单而肮脏的解决方案,即使用 FFmpeg 捕获图像,将它们存储在磁盘中,然后从我的 OpenCV 程序中读取这些图像。这是我正在使用的 FFmpeg 命令:

ffmpeg -i "rtmp://antena3fms35livefs.fplive.net:1935/antena3fms35live-live/stream-lasexta_1 live=1" -r 1 capImage%03d.jpg

这目前对我有用,至少对于这个具体的 rtmp 源是这样。然后我需要以正确的方式从我的 OpenCV 程序中读取这些图像。这部分我还没有实际实现,因为我正在寻找更好的解决方案。

我认为理想的方法是直接从 OpenCV 捕获 rtmp 帧,但我找不到实现它的方法。这是 Python 中的代码,我正在使用:

cv2.namedWindow("camCapture", cv2.CV_WINDOW_AUTOSIZE)
cap = cv2.VideoCapture()
cap.open('"rtmp://antena3fms35livefs.fplive.net:1935/antena3fms35live-live/stream-lasexta_1 live=1"')
if not cap.open:
    print "Not open"
while (True):
    err,img = cap.read()
    if img and img.shape != (0,0):
        cv2.imwrite("img1", img)
        cv2.imshow("camCapture", img)
    if err:
        print err
        break
    cv2.waitKey(30)

我还尝试使用 grab() 和 retrieve() 函数,而不是 read() 函数,但没有任何好的结果。每次都在执行 read() 函数,但没有收到 "img" 或 "err"。 还有其他方法吗?或者也许没有办法从这样的流中直接从 OpenCV 2.4.9 获取帧?

我读过 OpenCV 使用 FFmpeg 来执行此类任务,但如您所见,在我的例子中,FFmpeg 能够从流中获取帧,而 OpenCV 则不能。

在我找不到直接从 OpenCV 获取帧的方法的情况下,我的下一个想法是以某种方式通过管道将 FFmpeg 输出到 OpenCV,这似乎更难实现。

任何想法, 谢谢!

更新 1: 我在 Windows 8.1。由于我是从 Eclipse PyDev 运行 宁 python 脚本,这次我从 cmd 运行 它,我收到以下警告:

warning: Error opening file (../../modules/highgui/src/cap_ffmpeg_impl.hpp:545)

据我所知,此警告意味着文件路径错误或不支持编解码器。现在,问题是一样的。 OpenCV 不能从这个来源获取帧吗?

实际上我花了一天多的时间来弄清楚如何解决这个问题。最后我在this link的帮助下解决了这个问题。 这是客户端代码。

    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/opencv.hpp>

    using namespace cv;

    int main(int, char**) {
        cv::VideoCapture vcap;
        cv::Mat image;
        const std::string videoStreamAddress = "rtmp://192.168.173.1:1935/live/test.flv";
        if(!vcap.open(videoStreamAddress)) {
            std::cout << "Error opening video stream or file" << std::endl;
            return -1;
        }

        cv::namedWindow("Output Window");
        cv::Mat edges;
        for(;;) {
            if(!vcap.read(image)) {
                std::cout << "No frame" << std::endl;
                cv::waitKey();
            }
            cv::imshow("Output Window", image);
            if(cv::waitKey(1) >= 0) break;
        }
    }

注意:在这种情况下,我创建了一个 android 应用程序来获取实时视频并将其发送到部署在我创建的 PC.So 中的 rtmp 服务器 wowza这个用于实时视频处理的 C++ 实现。

python -c "import cv2; print(cv2.getBuildInformation())"   

检查用ffmpeg构建opencv。如果是正确的,你的代码应该没问题。

如果没有,用ffmpeg重建opencv。 在 osx

brew install opencv --with-ffmpeg