mjpg-streamer


mjpg-streamer

开源地址:https://github.com/jacksonliam/mjpg-streamer
这是http://sourceforge.net/projects/mjpg-streamer/ 的一个分支,通过 input_raspicam 插件增加了对 Raspberry Pi 相机的支持。
mjpg-streamer 是一种命令行应用程序,可将 JPEG 帧从一个或多个输入插件复制到多个输出插件。它可用于通过基于 IP 的网络将 JPEG 文件从网络摄像头流式传输到各种类型的查看器,例如 Chrome、Firefox、Cambozola、VLC、mplayer 和其他能够接收 MJPG 流的软件。

它最初是为 RAM 和 CPU 资源非常有限的嵌入式设备编写的。它的前身“uvc_streamer”是因为 Linux-UVC 兼容相机直接生成 JPEG 数据而创建的,即使来自运行 OpenWRT 的嵌入式设备也允许快速和高性能的 M-JPEG 流。输入模块“input_uvc.so”从连接的网络摄像头捕获此类 JPG 帧。mjpg-streamer 现在支持各种不同的输入设备。

安装支持插件

需要的插件

  • input_file
  • input_http
  • input_opencv (documentation)
  • input_ptp2
  • input_raspicam (documentation)
  • input_uvc (documentation)
    输出插件:
  • output_file
  • output_http (documentation)
  • output_rtsp (not functional)
  • output_udp (not functional)
  • output_viewer (documentation)
  • output_zmqserver (documentation)

    安装环境

    sudo apt-get install subversion 
    sudo apt-get install imagemagick
    sudo apt-get install libv4l-dev
    sudo apt-get install cmake 
    sudo apt-get install git
    gh  clone https://github.com/jacksonliam/mjpg-streamer.git
    sudo apt-get install cmake libjpeg8-dev
    sudo apt-get install gcc g++

    安装开源mjpg-streamer

    cd mjpg_streamer 
    make all
    sudo make install

使用mjpg-streamer

开机自启动

开机自启动,参考我之前的博客内容

命令行启动

cd mjpg_streamer 
./mjpg_streamer -o "output_http.so -w ./www" -i "input_raspicam.so"

运行参数设置

mjpg_streamer -i "input_uvc.so -d /dev/video0 -r 352x288 -f 30 -q 80 -y" -o "output_http.so -p 8080 -w /www/webcam"

y是表示YUV格式。如果没有-y,默认启动是mjpeg格式,这个就报错。改成YUV格式
-d指定设备
-f 制订帧数,默认30帧
-r指定视频大小,如320×240
-q指定画质,默认80对于输出参数:
-p 指定端口,这里是8080
-w 指定网页目录,这里设置的是/www/webCam目录
-c设置通过密码访问

正常输出结果如下:
MJPG Streamer Version: svn rev: Unversioned directory
 i: Using V4L2 device.: /dev/video0
 i: Desired Resolution: 640 x 480
 i: Frames Per Second.: 15
 i: Format............: YUYV
 i: JPEG Quality......: 80
 i: TV-Norm...........: DEFAULT
 i: FPS coerced ......: from 15 to 30
 i: Frame period time ......: 66 ms
 o: www-folder-path...: www/
 o: HTTP TCP port.....: 8080
 o: username:password.: disabled
 o: commands..........: enabled

web查看

  • 取一张图片:http://192.168.1.1:8080?action=snapshot
  • 在线查看视频:http://192.168.1.1:8080?action=stream

mjpg-streamer分析

感觉这个开源项目,更像是一种jpg的web查看器,可以通过web查看到图片,压缩为jpg格式大概为34kb。

web查看mjpg-streamer图片

自带的html查看

自己制作网页查看

<img src = "http://192.168.1.125:8080/?action=stream" alt = "xxx001" >

可以通过html同时拉取多个mjpg-streamer

代码如下:

  <body>
    <div id="main">
        <ul>
            <li><img src = "http://192.168.1.125:8080/?action=stream" alt = "xxx001" ></li>
            <li><img src = "http://192.168.1.168:8080/?action=stream" alt = "xxx002" ></li>
            <li><img src = "http://192.168.1.210:8080/?action=stream" alt = "xxx003" ></li>
            <li><img src = "http://192.168.1.190:8080/?action=stream" alt = "xxx004" ></li>
            <li><img src = "http://192.168.1.247:8080/?action=stream" alt = "xxx005" ></li>
            <li><img src = "http://192.168.1.196:8080/?action=stream" alt = "xxx006" ></li>
            <li><img src = "http://192.168.1.220:8080/?action=stream" alt = "xxx007" ></li>
            <li><img src = "http://192.168.1.164:8080/?action=stream" alt = "xxx008" ></li>
            <li><img src = "http://192.168.1.147:8080/?action=stream" alt = "xxx009" ></li>
            <li><img src = "http://192.168.1.186:8080/?action=stream" alt = "xxx010" ></li>
        </ul>
    <div>
    <div id="gray">
        <div class="IMG">
        </div>
    </div>
    <div class="r-but"></div>
    <div class="l-but"></div>
    <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
    <script type="text/javascript">
        var i =0;
        $("#main ul li").click(function(){
            $("#gray").show();
            $(".l-but").show();
            $(".r-but").show();
            /*var _bigSrc=$(this).find("img").attr("src");
            alert(_bigSrc);
            $("#gray .IMG img").attr("src",_bigSrc);*/
            index=$(this).index();
            /*alert(index);*/
            i=index;
            $("#gray .IMG img").eq(i).fadeIn().siblings().fadeOut();
                /*alert(i);*/
        });
        $(".r-but").click(function(){
            /*
                index++;
                alert(index);
                _bigSrc=$(#Main ul li).eq().find("img").attr("bigSrc");
                $(".gray .IMG img .BIGIMG").attr("src",_bigSrc);
            */
            i++;
              if(i<16 && i>0){
                  /*$(".pic img").eq(i).show().siblings().hide();*/
                  $("#gray .IMG img").eq(i).fadeIn().siblings().fadeOut();
                /*alert(i);*/
              }else{
                  i=0;
                  $("#gray .IMG img").eq(i).fadeIn().siblings().fadeOut();
              }14-12-10
          });
        $(".l-but").click(function(){
            i--;
              if(i<16 && i>0){
                  /*$(".pic img").eq(i).show().siblings().hide();*/
                  $("#gray .IMG img").eq(i).fadeIn().siblings().fadeOut();
                /*alert(i);*/
              }else{
                  i=16;
                  $("#gray .IMG img").eq(i).fadeIn().siblings().fadeOut();
              }
          });
        $("#gray").click(function(){
            $(this).hide();
            $(".l-but").hide();
            $(".r-but").hide();
        });
    </script>
  </body>
</html>
</span></strong>

显示效果:

对于单张图片可以进行放大显示。

python爬取mjpg-streamer图片

可以通过urllib爬取图片,获取传输时延。

源码

# -*- coding:utf-8 -*-
import cv2
import numpy as np
from urllib import request
import time
# -*- coding: utf-8 -*-
from concurrent.futures import ThreadPoolExecutor
import threading
import time

url = "http://192.168.3.111:8080/?action=snapshot"
url2 = "http://192.168.3.101:8080/?action=snapshot"
# 定义获取线程return返回测试的方法
def action_a(max):
    my_sum = max + 1
    return my_sum


def action_b(max):
    my_sum = max + 100
    time.sleep(3)
    return my_sum

def downloadImg(url):
    time1=time.time()
    with request.urlopen(url) as f:
        data = f.read()
        img1 = np.frombuffer(data, np.uint8)
        # print("img1 shape ", img1.shape) # (83653,)
        img_cv = cv2.imdecode(img1, cv2.IMREAD_ANYCOLOR)
    print(url, "time:", time.time() - time1)
    return img_cv

结果显示

python多台拉取显示

为了获取结果采用线程进行显示

线程池

while True:
    # 创建包含2个线程的线程池
    pool = ThreadPoolExecutor(max_workers=2)
    # 向线程池提交一个任务, 20和10会作为action_a/b()方法的参数
    future1 = pool.submit(downloadImg, url)
    future2 = pool.submit(downloadImg, url2)

    # 判断future1线程是否结束---返回False表示该线程未结束,True表示该线程已经结束
    print("future1线程的状态:" + str(future1.done()))  # 此时future1线程已结束
    # 判断future2线程是否结束
    print("future2线程的状态:" + str(future2.done()))  # 此时future2线程未结束,因为休眠了3秒

    cv2.imshow("frame", future1.result())
    cv2.imshow("frame2", future2.result())
    cv2.waitKey(1)

    # 关闭线程池
    pool.shutdown()

cv2.destroyAllWindows()

自制线程


# -*- coding: utf-8 -*-
import threading, time

"""
用类包装线程;调用时可以获取线程的return返回值
"""


# 定义一个MyThread.py线程类
class MyThread(threading.Thread):
    def __init__(self, func, args=()):
        super(MyThread, self).__init__()
        self.func = func
        self.args = args

    def run(self):
        time.sleep(2)
        self.result = self.func(*self.args)

    def get_result(self):
        threading.Thread.join(self)  # 等待线程执行完毕
        try:
            return self.result
        except Exception:
            return None


# 获取多线程return返回值的测试方法
def admin(number):
    uiu = number
    for i in range(10):
        uiu = uiu + i
    return uiu


if __name__ == "__main__":
    # 创建四个线程
    more_th1 = MyThread(admin, (5,))
    more_th2 = MyThread(admin, (10,))
    more_th3 = MyThread(admin, (50,))
    more_th4 = MyThread(admin, (78,))

    # 启动线程
    more_th1.start()
    more_th2.start()
    more_th3.start()
    more_th4.start()

    # 线程等待(即:等待四个线程都运行完毕,才会执行之后的代码)
    more_th1.join()
    more_th2.join()
    more_th3.join()
    more_th4.join()

    # 输出线程执行方法后的的返回值
    print(more_th1.get_result())
    print(more_th2.get_result())
    print(more_th3.get_result())
    print(more_th4.get_result())

结论:

自制线程效果优于自制线程。
结果:

更多内容:

参考文章

源码解析

https://wiki.openwrt.org/doc/howto/webcam

https://blog.csdn.net/zhengqijun_/article/details/72473177

https://www.cnblogs.com/wanghuaijun/p/8098460.html


文章作者: 万鲲鹏
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 万鲲鹏 !
评论
  目录