嵌入式行业的大佬韦东山老师一贯是授人以鱼不如授人以渔,作为韦东山老师的忠实粉丝,同时我们也一直保持合作与联系。从大学到职场,韦东山老师的课程给我带来了飞跃性的成长,可以说让我这个原本全日制大专的毕业生,到后来通过自己的努力考上本科,再到现在攻读国外商管类的硕士研究生,一路过来,是韦东山老师教给了我学习的方法,让我有机会一路逆袭!学习任何东西,最重要是感兴趣并且能够找到适合自己的方法,持续以恒!活到老,学到老,不忘初心,方得始终,努力改变人生,奋斗永驻青春!再次感谢韦东山老师给我们带来的流媒体知识以及项目的讲解。
公众号后台回复:物联网 即可获得本文pdf带书签版本,本文后续还会持续更新新的项目实战经验以及企业实战知识点,敬请关注!
1、物联网实战项目-搭建智慧家居视频监控系统
1.1、什么是流媒体?
如下图所示:
(1) 推流端:开发板读取摄像头数据,然后将数据推送到服务器的过程。
(2) 流媒体服务器:服务器接收开发板推送过来的数据,然后进行处理。
(3) 拉流端:手机或者其它的设备,通过拉取访问服务器上的数据然后进行显示。
作为程序员我们需要写三个程序:
这里的程序员主要有三个:
1、嵌入式软件工程师
在连接摄像头的ARM板子上,实现一个推送程序,它能够一边读取摄像头的数据,一边将数据推送给服务器。
2、WEB前后端软件工程师
在服务器上,实现"流媒体服务器"程序,它能够接收ARM板子发过来的数据,并把数据转换格式发送给手机等客户端。
3、Android、IOS 、Window 等软件工程师
在手机等客户端上,实现拉取程序,它能够从服务器上拉取数据并且显示出来。
初学者在学习流媒体相关知识的时候,实际上我们可以将互联网功能去掉,我们直接在局域网内实现推拉流即可,我们可以把推送程序、流媒体服务器程序都在ARM板上运行,手机等客户端只能在同一个局域网里观看视频,或者如果真的需要加上互联网的功能,我们还可以使用内网穿透技术实现互联网视频监控。
在这里我们尝试着思考两个问题:
1.开发板是通过什么协议将摄像头的数据推送到服务器?
2.手机或者是其它的设备又是通过什么协议将服务器上的数据拉取下来?
1.2、常见的流媒体协议
HLS(HTTP LiveStreaming)是基于HTTP的,是Apple公司开放的音视频传输协议。
HTTP FLV则是将RTMP封装在HTTP协议之上的,可以更好的穿透防火墙等。
参考:HTTP-FLV直播初探- 冒雨ing - 博客园(cnblogs.com)
参考:理解RTMP、HttpFlv和HLS的正确姿势- 简书 (jianshu.com)
(1)RTMP 与 HTTP-FLV 协议
协议好用,但不代表插件好用,比如我们经常会在网页上看到插件失效了。
(2)HLS 协议
所以就给 HTTP-FLV 活过来的机会:
B站开发出了 flv.js 插件,能够把Adobe公司的插件屏蔽,所以所谓的视频监控和直播是一样的道理。
如果将ffmpeg 和 Nginx 移植到ARM板上,那么这个流程就会退化成在局域网内实现,就会变成在局域网内观看摄像头的数据。
2、MJPG-steamer方案实现
这个方案比较适合在低性能的板子上实现,CPU主频200M都没问题:
它的实现原理如下:
如上所示, MJPG-steamer是一个开源的软件,我们可以将它移植到ARM板子上,然后它可以将摄像头的数据推送到手机端,然后手机端可以直接通过浏览器来直接观看摄像头数据, MJPG-steamer非常适合初学者用于学习视频监控的知识。
2.1、MJPG-steamer 的优点和缺点
优点:
· 程序简单,所有源码一目了然,便于学习
· 对ARM板的性能要求不高,主频200MHz 的ARM芯片也可以实现。
缺点:
· 只能实现局域网的视频监控
· 要实现互联网视频监控,需要另外实现内网穿透
· MJPG-steamer没有实现声音传输
· MJPG-steamer项目已经不再维护,仅仅建议用于学习
2.2、MJPG-steamer 视频监控原理
2.2.1、JPEG、MJPG 格式简介
2.2.2、移植MJPG-steamer
在buildroot中配置:mjpg-streamer:
配置完毕以后在 Buildroot工程下执行make完成编译,然后烧写固件即可,然后就可以在ARM开发板的串口终端执行:
mjpg_streamer --help #查看帮助信息
先要在开发板端连接好摄像头( USB ),然后再连接好网线联网,使用ifconfig 命令配置ip地址,然后执行mjpg_streamer对应的命令:
执行后即成功:
然后在浏览器端输入ip地址:192.168.1.6:8080(这是我的IP和端口号),然后点击Stream,这样就可以看到摄像头里的数据了:
这个命令的源码位于Buildroot/dl/mjpg=streamer/下。
2.2.3、MJPG-steamer代码框架分析
这个程序涉及多线程编程、网络编程、动态库等的使用,比较适合初学者学习并提高自己的应用编程水平。
server线程,等待别人来连接,每创建一个连接就会多创建一个线程。
韦老师操作的命令:看当前进程里有多少个线程:cd /proc/进程id/task/ 。
其它的用法:(在开发板端)
将jpg文件存到tmp目录,然后将 tmp目录下的jpg文件推送到浏览器。(在开发板端)
3、流媒体方案的实现之ffmpeg
3.1、ffmpeg 是什么?
3.2、简单理解下什么是ffmpeg
这里涉及到了四个层:原始数据层、编码层、容器层、协议层。
[总结]视音频编解码技术零基础学习方法_雷霄骅(leixiaohua1020)的专栏
3.3、主要的视频编码技术
[总结]视音频编解码技术零基础学习方法_雷霄骅(leixiaohua1020)的专栏
目前主要使用的视频编码格式有以下:(最常用的是H.264)
3.4、主要的音频编码技术
[总结]视音频编解码技术零基础学习方法_雷霄骅(leixiaohua1020)的专栏
目前主要使用的音频编码格式有以下:(最常用的是AAC)
3.5、ffmpeg的组成
ffmpeg 基本用法 - 简书 (jianshu.com)
如下图所示:
将 mp4 解压为音频和视频的数据、将编码数据合并为flv ==> 需要libavformat
解码和编码的过程==> 需要libavcodec
处理==> 需要libswscale、libpostproc
ffmpeg 是一个命令行工具,可以指定各种参数以及其它应用程序。
3.6、ffmpeg的重要概念
3.7、ffmpeg处理音视频的过程
3.8、ffmpeg的常用参数
3.9、移植ffmpeg
配置完毕后编译,生成固件以后将其下载到开发板上去。
如何使用ffmpge?
4、流媒体方案的实现之Nginx方案
4.1、Nginx 是什么?
4.2、三种WEB服务器的比较
4.3、Nginx 在流媒体方案中的位置
4.4、让Ngnix支持RTMP、HTTPFLV协议
原生的 Ngnix 不支持 RTMP 以及 HTTPFLV ,所以我们需要移植第三方模块:
4.5、移植Nginx
在使用nginx之前,我们需要设置一下/etc/nginx/nginx,conf,在这个文件中添加rtmp节点:
让nginx支持rtmp协议,服务器会监听1935这个端口,live表示 app 的意思。
但这个端口:1935 经常会被防火墙给墙住,我们可以在 http 节点下面创建下面这个节点:
以后我们就可以使用flv协议来实现拉流的动作,当修改了配置文件以后需要重启一下nginx服务,重启命令如下:
/etc/init.d/S50nginxrestart
4.6、测试流媒体
如上所示:( ffmpeg的编解码器非常耗CPU的资源)
(1)推流方式
使用 rtmp 协议将设备结点 /dev/video1 的数据以每秒10帧( framerate )、量( -q )为10推送(推流: flv )到127.0.0.1的live这个 app 的 wei 这个路径下。
(2)拉流方式
- 使用RTMP 协议拉流
在 VLC 播放器中点击媒体->打开网络串流,输入:
rtmp://192.168.1.6/live/wei
,即可播放。
- 使用HTTP FLV协议拉流
在 VLC 播放器中点击媒体->打开网络串流,输入:
http://192.168.1.6/test? app=live&stream=wei
,就可以实现播放了,即是从192.168.1.6的test目录的 app 为live下拉取名字叫 wei 的流。
- 直接推送视频文件
ffmpeg -re -i test.mp4 -vcodec copy -acodeccopy -f flv rtmp://127.0.0.1/live/wei
-re表示保持当前的速度,-i表示选取一个文件,-vcodec表示视频编解码器,copy表示保持一致,-acodec表示音频编解码器,copy表示保持一致,然后将流( flv )推送到
rtmp://127.0.0.1/live/wei。
安装 flv.js 插件:(这样才能够直接在网页上看到直播流),参考下面这个网站,给出了很多方法:
https://pingos.io/docs/zh/quick-start#%E6%8E%A8%E6%B5%81
在开发板端的HTML文件的位置:/usr/html/目录下,这是我们网页端看推流的地方,把我们自己制作的html替换到当前目录下的html文件。
在这里看到韦老师敲命令的一个细节==>如何清除一个文件里的数据:
> 文件名
在浏览器上输入ip地址,就可以在网页上看到推流的视频了。
4.7、浏览器上观看直播流的原理
Nginx将数据流通过flv.js进行转换成html5可以识别的data,这样html5就可以显示出来了,如下图所示:
5、摄像头和声卡接口
5.1、ffmpeg如何去访问摄像头?
5.2、摄像头接口:V4L2
摄像头的数据格式:RGB、YUV、JPEG、MJPG、H.264 等等。
学习MJPG-steamer的源代码的时候,有关摄像头接口的代码在v4l2uvc.c是在这个文件里面实现的,这里列出主要的API接口:
5.3、摄像头数据在内核中的组织方法
如果能够了解摄像头的数据在内核中的组织方法,那么对摄像头数据的读取就能够彻底的掌握了!
·APP 向内核申请
·APP 把它们queue(入队)
·驱动把数据放入某个buffer
·把该buffer出列,然后处理数据
·buffer入列
以上五个步骤都是应用程序来处理队列。
5.4、声音的采集
5.5、声卡的接口:ALSA
什么是 ALSA 呢?ALSA就是AdvancedLinux Sound Architecture(先进的Linux声音架构)
5.6、让FFmpeg录制声音
-ac 指定只有一个通道。
hw:0,0 硬件的第0个声卡的第0个设备。
当然也可以用alsa的录制命令,alsa的命令比ffmeg的命令简单好用,在Buildroot中配置如下:
5.7、测试流媒体
6、内网穿透
6.1、为什么要内网穿透?
IP和端口的作用:
6.1.1、公网的IP不够用
6.1.2、对外访问时,路由器来帮忙
6.1.3、内网穿透的实现方法
(一)设置路由器(有点难度)
(二)用某些APP,比如花生壳
6.1.4、使用花生壳进行内网穿透示例
接下来就可以进行测试推流了:查看ffmpeg如何将mp4推送到流媒体服务器。在这里要注意,推流的地址要改成花生壳的外网域名,还要注意内网IP是否会冲突,如果冲突了则需要重新更改IP,如下所示:
6.2、在公网服务器上运行Nginx
如果自己开公司,买个公网服务器,比如阿里云、华为云、腾讯云等。
6.3、如何在服务器上编译Nginx?
往期精彩
Buildroot系统构建学习笔记(以百问网imx6ull开发板为例)