当前位置:   article > 正文

imx6ull视频监控项目,从kernel,buildroot,nginx,ffmpeg实现摄像头推流,vlc及web拉流_im6ull的摄像头

im6ull的摄像头

写这一篇目的是记录自己使用buildroot 构建根文件系统 实现摄像头推流到VLC 及 web端

主要介绍的是

1. buildroot构建根文件系统
2. ffmpeg 及nginx 的配置
3. Linux内核构建
4. 如何将摄像头的视频在web上面显示 (由于自己没找到教程,期间踩了很多坑,最后成功在web上面显示)

主要参考资料

1. 正点原子驱动开发指南
2. 百问网韦东山-【物联网实战项目】手把手教你如何从0搭建智慧家居中的视频监控系统

设备

1. imx6ull开发板,我用的正点原子的
2. usb摄像头

1 buildroot构建根文件系统

参考:正点原子-buildroot构建根文件系统
解压完成buildroot之后
由于buildroot和uboot、linux kernel一样支持图形化配置
输入 make menuconfig

1.1 配置Target options

在这里插入图片描述

1.2 配置Toolchain

此配置项用于配置交叉编译工具链,也就是交叉编译器,这里设置为我们自己所使用的交
叉编译器即可。 buildroot 其实是可以自动下载交叉编译器的,但是都是从国外服务器下载的,
鉴于国内的网络环境,强烈推荐大家设置成自己所使用的交叉编译器

在这里插入图片描述

1.3 配置System configuration

此选项用于设置一些系统配置,比如开发板名字、欢迎语、用户名、密码等。需要配置的
项目和其对应的内容如下
在这里插入图片描述

1.4 配置Filesystem images

此选项配置我们最终制作的根文件系统为什么格式的

在这里插入图片描述

1.5 禁止编译linux内核和uboot

buildroot 不仅仅能构建根文件系统,也可以编译 linux 内核和 uboot。当配置 buildroot,使
能 linux 内核和 uboot 以后 buildroot 就会自动下载最新的 linux 内核和 uboot 源码并编译。但是
我们一般都不会使用 buildroot 下载的 linux 内核和 uboot,因为 buildroot 下载的 linux 和 uboot
官方源码,里面会缺少很多驱动文件,而且最新的 linux 内核和 uboot 会对编译器版本号有要
求,可能导致编译失败。因此我们需要配置 buildroot,关闭 linux 内核和 uboot 的编译,只使用
buildroot 来构建根文件系统
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.6 配置Target packages

此选项用于配置要选择的第三方库或软件

1.6.1 配置ffmpeg

Target packages > Audio and video applications > ffmpeg

在这里插入图片描述

1.6.2 配置nginx

Target packages > Networking applications > nginx

由于nginx本身是没有rtmp功能的,是依靠第三方模块支持的,所以需要将模块一同编译进nginx。

需要用到nginx-rtmp-modules
需要用到http-flv,推荐使用nginx-http-flv-module,他比nginx-rtmp-modules更强大,支持web推流

先勾选nginx所有的选项

在这里插入图片描述

将下载下来的nginx-rtmp-modules 放到 buildroot/dl/nginx目录下,一般要自己创建。

然后在menuconfig下配置nginxaddtional modules添加nginx-rtmp-modules的地址

需要使用http-flv的话,将库换成下面这个:

注意:我用的是nginx-http-flv-module 1.2.7 版本 可以支持http推流 操作和上面是一样的
在这里插入图片描述

2 Linux内核构建

因为正点原子的内核源码默认没有开启,UVC设备类驱动,需要自己配置并编译

打开正点原子的内核代码 或者 自己移植的nxp的内核代码

输入 make menuconfig

勾选如下选项

Device Drivers -->
	USB support -->
		Support for Host-side USB -->
			USB announce new devices
	Multimedia support -->
		Cameras/video grabbers support
    	Media Controller API
    	V4L2 sub-device usersapce API
    Media USB Adapters -->
    	USB Video Class (UVC) -->
    		UVC input events device support
    V4L platform devices -->
    	soC camera support
    	platform camera support
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

完成之后make一下

新的镜像文件在 arch/arm/boot /下

copy到开发板进行测试

2.1 nginx的配置

系统以及文件系统移植完毕之后

etc/nginx/下的nginx.conf文件里面添加如下

将 worker_processes  改为 auto

添加:
rtmp {
    server {
        listen 1935; # 监听 1935 端口
        chunk_size 4096;
        application live{
        allow publish 127.0.0.1;
        allow play all;
        live on; # 打开直播
        record off; # 关闭 record
        meta copy;
    }
    } 
}

在http目录下添加
location /test {
	    flv_live on;
        chunked_transfer_encoding on;
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
}


修改http目录下的html文件目录
location / {
  root   /var/www/html/;    目录要从根目录写起
  index  index.html;
  }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

配置完之后需要重启nginx : /etc/init.d/S50nginx restart

2.2 html页面配置

index.html我是放在/var/www/html/目录下 默认目录是/usr/html/ 这个根据你自己的想法
参考博客: https://blog.csdn.net/igocsdn/article/details/118753920

<!DOCTYPE html>
<html>
<head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <title>flv.js demo</title>
    <style>
        .mainContainer {
            display: block;
            width: 1024px;
            margin-left: auto;
            margin-right: auto;
        }

        .urlInput {
            display: block;
            width: 100%;
            margin-left: auto;
            margin-right: auto;
            margin-top: 8px;
            margin-bottom: 8px;
        }

        .centeredVideo {
            display: block;
            width: 100%;
            height: 576px;
            margin-left: auto;
            margin-right: auto;
            margin-bottom: auto;
        }

        .controls {
            display: block;
            width: 100%;
            text-align: left;
            margin-left: auto;
            margin-right: auto;
        }
    </style>
</head>
<body>
<div class="mainContainer">
    <video id="videoElement" class="centeredVideo" controls autoplay width="1024" height="576" muted>Your browser is too old which doesn't support HTML5 video.</video>
</div>
<br>
<div class="controls">
    <!--<button οnclick="flv_load()">加载</button>-->
    <button onclick="flv_start()">开始</button>
    <button onclick="flv_pause()">暂停</button>
    <button onclick="flv_destroy()">停止</button>
    <input style="width:100px" type="text" name="seekpoint" />
    <button onclick="flv_seekto()">跳转</button>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/flv.js/1.5.0/flv.min.js"></script>

<script>
    var player = document.getElementById('videoElement');
    if (flvjs.isSupported()) {
        var flvPlayer = flvjs.createPlayer({
            type: 'flv',
            url: 'http://192.168.31.98/test?app=live&stream=os',
            "isLive": true,
            hasAudio: false,
            hasVideo: true,
            //withCredentials: false,
            //cors: true
        }, {
            enableWorker: true,	// 开启多线程
            enableStashBuffer: false,
            lazyLoad: false,
            lazyLoadMaxDuration: 0,
            lazyLoadRecoverDuration: 0,
            deferLoadAfterSourceOpen: false,
            fixAudioTimestampGap: true,
            autoCleanupSourceBuffer: true,
        });
        flvPlayer.attachMediaElement(videoElement);
        flvPlayer.load(); //加载
        flv_start();
    }

    function flv_start() {
        player.play();
    }

    function flv_pause() {
        player.pause();
    }

    function flv_destroy() {
        player.pause();
        player.unload();
        player.detachMediaElement();
        player.destroy();
        player = null;
    }

    function flv_seekto() {
        player.currentTime = parseFloat(document.getElementsByName('seekpoint')[0].value);
    }
</script>
</body>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104

2.3 遇到的问题

2.3.1 nginx-http-flv-module版本问题

nginx-rtmp-module 这个库是不支持http的,推流VLC没有问题 ,但是不能推流http-flv,

为了推流web 换了nginx-http-flv-module库,但是报以下错误
在这里插入图片描述

遇到 Input/output error:期间也困扰了一下,最后发现是版本问题 ,换了低版本就行了
实测nginx-http-flv-module 1.2.7可以用

2.3.2 使能x264库

然后我想推流到web端,还需要用到x264这个库,默认ffmpeg是没有使能的,需要我们自己添加

在这里插入图片描述

添加x264库

先安装好x264库,可以参考 x264的交叉编译和移植
我是安装在/home/os/tools/libx264/下面

然后进入buildroot 配置界面 在make menuconfigffmpeg 里面最后一个选项输入如下

--enable-libx264 --extra-cflags=-I/home/os/tools/libx264/include --extra-ldflags=-L/home/os/tools/libx264/lib
  • 1

在这里插入图片描述

注意:先要删除之前生成的 ffmpeg 目录(也就是 output/build 目录下的ffmpeg),才会重新生成

经过测试还需要将安装好的x264目录下的lib目录拷贝到开发板/usr/lib目录下
在这里插入图片描述

2.3.2 踩过的坑

root /var/www/html/; 目录要从根目录写起 目录没写对

3 推流测试

推流摄像头

推流
ffmpeg -vsync 1  -use_wallclock_as_timestamps 1 -i /dev/video1  -vf 'format=pix_fmts=yuv420p,scale=320:200' -c:v libx264 -preset ultrafast -tune zerolatency -f flv rtmp://127.0.0.1/live/os

-vsync 1: 设置垂直同步为 1,确保输出帧与输入帧的同步。(能解决推流一段时间报时间戳的问题)解决了之前遗留问题。
-vf 'format=pix_fmts=yuv420p': 使用视频滤镜来设置输出视频的像素格式为 YUV420P。这是一种普遍支持的像素格式,适用于大多数流媒体服务器。
-c:v libx264: 指定视频编码器为 libx264,这是一个高效的 H.264 编码器。
-use_wallclock_as_timestamps 1:使用系统时钟作为时间戳,确保输出流的时间戳与实际时间同步。
scale=320:200:将视频的分辨率缩放为 320x200 像素,imx6ull性能有限,为了保证输出画面同步(实时性)因此需要降低画面质量。
-preset ultrafast: 设置编码速度为 ultrafast,这意味着编码速度非常快,但可能会牺牲一些编码效率。
-tune zerolatency: 使用 zerolatency 优化参数,以减少编码延迟,使得实时推流更加实时响应。
-f flv: 指定输出格式为 FLV(Flash 视频)。这是一种常用的流媒体格式,适用于许多流媒体服务器。

也可以用下面命令推流  但是好像web端是显示不了的   原因应该是没有指定编码器
ffmpeg -f v4l2 -framerate 10 -i /dev/video1 -q 10  -f flv rtmp://127.0.0.1/live/os

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

3.1 网页端:测试几乎没有延迟

在这里插入图片描述

3.2 VLC:会有10秒左右的延迟

在这里插入图片描述

3.3 推流MP4文件

需要声音的话,可以开启index.html里面的声音(hasAudio)选项,开启声音选项,但是推流摄像头会受到影响,因此推流摄像头需要将声音选项去掉

ffmpeg -re -i lx.mp4 -vcodec copy -acodec copy -f flv rtmp://127.0.0.1/live/os

-re: 指定以实时速度(real-time)读取输入文件。这将使 FFmpeg 按照视频的原始帧速率进行处理,而不是尽可能快地处理。

-vcodec copy: 使用 -vcodec 参数指定视频编码器为 "copy",表示直接复制原始视频流而不进行重新编码。这样可以保持原始视频流的编码格式、质量和参数不变。

-acodec copy: 使用 -acodec 参数指定音频编码器为 "copy",表示直接复制原始音频流而不进行重新编码。这样可以保持原始音频流的编码格式、质量和参数不变。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4 实现内网穿透

软件:花生壳,其他的类似软件也行,我看了一下基本上都有免费套餐。

内网穿透----自定义映射:配置内网主机和内网端口

在这里插入图片描述

添加好之后,打开VLC,输入下面链接

https://你的外网域名/test?app=live&stream=os
  • 1

在这里插入图片描述
至此,我们可以实现在外网访问,手机端VLC也是一样。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/550695
推荐阅读
相关标签
  

闽ICP备14008679号