将 openCV C++ 视频流式传输到浏览器

Posted

技术标签:

【中文标题】将 openCV C++ 视频流式传输到浏览器【英文标题】:Streamign openCV C++ video to the browser 【发布时间】:2016-05-30 11:39:44 【问题描述】:

我正在尝试使用 C++ 中的 openCV 捕获我的内置网络摄像头,并进行一些处理。到目前为止,这是有效的。

现在我想将网络摄像头流式传输到浏览器。我该如何存档?

我应该创建一个 WebSocket 吗?还是使用 UPD 套接字? Poco::Net::WebSocket 如何在浏览器中显示该内容? html5 和 JS 可以做到吗?

谢谢。

【问题讨论】:

在浏览器中,可以使用 websockets 并连接到实时流。我猜最大的问题是运行实际的流媒体服务器并决定兼容的视频格式。我从来没有尝试过自己做,但是这个问题让我很感兴趣,我发现了这个有趣的讨论***.com/questions/21921790/… @user151496 这是一个非常有趣的话题,我已经能够通过网络套接字从webcam(html5) > server > video(html5) 进行流式传输,音频是一个主要问题,因为捕获流的支持非常有限,而且通常很难工作和。 OP 应该看看 MPEG-DASH,它比 web sockets 容易上手。 【参考方案1】:

我可能有点晚了,但由于我没有在 *** 中找到完全更新的 C++ 和 mjpeg 解决方案,所以考虑写一个新答案。

现在有一些用于 C++ 任务的简单易用的库(c++ mjpg 流式传输到 html)

https://github.com/nadjieb/cpp-mjpeg-streamer

https://github.com/jacksonliam/mjpg-streamer

https://github.com/codewithpassion/mjpg-streamer/tree/master/mjpg-streamer

我发现第一个非常简单。您需要 CMake,并在系统中安装 make。

git clone https://github.com/nadjieb/cpp-mjpeg-streamer.git;
cd cpp-mjpeg-streamer;
mkdir build && cd build;
cmake ../;
make;
sudo make install;
确保您安装了正确版本的 OpenCV。

现在,写流光:

mjpeg_server.cc

#include <opencv2/opencv.hpp>

#include <nadjieb/mjpeg_streamer.hpp>

// for convenience
using MJPEGStreamer = nadjieb::MJPEGStreamer;

int main()

    cv::VideoCapture cap;
    cap.open("demo.mp4"); 
    if (!cap.isOpened())
    
        std::cerr << "VideoCapture not opened\n";
        exit(EXIT_FAILURE);
    

    std::vector<int> params = cv::IMWRITE_JPEG_QUALITY, 90;

    MJPEGStreamer streamer;

    // By default 1 worker is used for streaming
    // if you want to use 4 workers:
    //      streamer.start(8080, 4);
    streamer.start(8000);

    // Visit /shutdown or another defined target to stop the loop and graceful shutdown
    while (streamer.isAlive())
    
        cv::Mat frame;
        cap >> frame;
        if (frame.empty())
        
            std::cerr << "frame not grabbed\n";
            //continue;
            exit(EXIT_FAILURE);
        

        // http://localhost:8080/bgr
        std::vector<uchar> buff_bgr;
        cv::imencode(".jpg", frame, buff_bgr, params);
        streamer.publish("/bgr", std::string(buff_bgr.begin(), buff_bgr.end()));

        cv::Mat hsv;
        cv::cvtColor(frame, hsv, cv::COLOR_BGR2HSV);

        // http://localhost:8080/hsv
        std::vector<uchar> buff_hsv;
        cv::imencode(".jpg", hsv, buff_hsv, params);
        streamer.publish("/hsv", std::string(buff_hsv.begin(), buff_hsv.end()));

        // std::cout<< "published" << std::endl;
    

    streamer.stop();

CMakeLists.txt

cmake_minimum_required(VERSION 3.1)

project(mjpeg_streamer CXX)

find_package(OpenCV 4.2 REQUIRED)
find_package(nadjieb_mjpeg_streamer REQUIRED)

include_directories($OpenCV_INCLUDE_DIRS)

add_executable(stream_test
  "mjpeg_server.cc")
target_compile_features(stream_test PRIVATE cxx_std_11)
target_link_libraries(stream_test PRIVATE nadjieb_mjpeg_streamer::nadjieb_mjpeg_streamer
                     $OpenCV_LIBS)


| --- mjpeg_server.cc
| --- CMakeLists.txt
| --- ...
| --- build  
      | --- demo.mp4
      | --- ...

现在,我们可以构建流媒体了。

mkdir build && cd build;
cmake ../;
make;
./stream_test

现在,如果您转到"http://ip_address:port/bgr""http://ip_address:port/hsv",您应该能够看到流。在我的例子中,ip = 192.168.1.7 / localhost, port = 8000。

如果你想用另一个服务器抓取流,

index.html

<html>
  <body>
    <img src="http://localhost:8000/bgr">
    <img src="http://localhost:8000/hsv">
  </body>
</html>

serve.py

import http.server
import socketserver

class MyHttpRequestHandler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.path = 'index.html'
        return http.server.SimpleHTTPRequestHandler.do_GET(self)

# Create an object of the above class
handler_object = MyHttpRequestHandler

PORT = 8080
my_server = socketserver.TCPServer(("", PORT), handler_object)

# Star the server
my_server.serve_forever()

python3 serve.py

最后,尽管它非常简单,但并不安全。

【讨论】:

【参考方案2】:

所以我自己找到了解决方案。概念是这样的:

我的serverWebSocket-Server 构建与POCO Library。

服务器: 在主线程中初始化相机(相机必须在主线程中初始化)。建立WebSocket 连接后,服务器从cv::VideoCapture 捕获帧,将帧转换为JPEG,并将图像编码为Base64string,最后将该字符串发送回客户端。

浏览器: 在浏览器中,收到的Base64 字符串可以被img 标签解释为图像。

<img id="image" src=""  />  

ws.onmessage = function(evt)

  $("#image").attr('src',  'data:image/jpg;base64,'+ evt.data);
;

因此,如果服务器现在在一秒钟内发送 30 帧,浏览器中就会出现流畅的livestream

【讨论】:

你能分享你的服务器代码和“OpenCV streamer”吗?

以上是关于将 openCV C++ 视频流式传输到浏览器的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV:将视频流式传输到网页浏览器/HTML页面

以任何方式将 DroidCam 视频流式传输到 OpenCV Python

将 pi 的 opencv 视频传输到 ffmpeg 以进行 Youtube 流式传输

用 C++ 流式传输视频? [关闭]

是否可以使用 OpenCV 将视频从 https://(例如 YouTube)流式传输到 python 中?

通过opencv和c ++从ip摄像头流式传输视频