首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JavaCV的摄像头实战之五:推流

JavaCV的摄像头实战之五:推流

作者头像
程序员欣宸
发布于 2021-12-07 02:04:26
发布于 2021-12-07 02:04:26
1.7K00
代码可运行
举报
文章被收录于专栏:实战docker实战docker
运行总次数:0
代码可运行

本篇概览

  • 本文是《JavaCV的摄像头实战》的第五篇,一起来考虑个问题:本地摄像头的内容,如何让网络上的其他人看见?
  • 这就涉及到了推流,如下图,基于JavaCV的应用将摄像头的视频帧推送到媒体服务器,观看者用播放器软件远程连接媒体服务器,就能观看摄像头的内容了:
  • 今天的主要工作就是开发上图的JavaCV应用,然后验证功能是否正常;

编码

  • 《JavaCV的摄像头实战之一:基础》一文创建的simple-grab-push工程中已写好父类AbstractCameraApplication,本篇继续使用该工程,创建子类实现那些抽象方法即可
  • 编码前先回顾父类的基础结构,如下图,粗体是父类定义的各个方法,红色块都是需要子类来实现抽象方法,所以接下来,咱们以本地窗口预览为目标实现这三个红色方法即可:
  • 新建文件RecordCamera.java,这是AbstractCameraApplication的子类,其代码很简单,接下来按上图顺序依次说明
  • 《JavaCV的摄像头实战之一:基础》中已部署好了媒体服务器,这里定义一个成员变量保存媒体服务器的推流地址,请您按自己的情况调整:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static final String RECORD_ADDRESS = "rtmp://192.168.50.43:21935/hls/camera";
  • 还要准备一个成员变量,推流的时候在帧上添加时间戳:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected long startRecordTime = 0L;
  • 将视频帧推送到媒体服务器的功能来自FrameRecorder,这是个抽象类,本篇用到的是其子类FFmpegFrameRecorder,所以定义FrameRecorder类型的成员变量:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
	// 帧录制器
    protected FrameRecorder recorder;
  • 然后是初始化操作,请注意各项参数设置(1280*720分辨率摄像头的情况):
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @Override
    protected void initOutput() throws Exception {
        // 实例化FFmpegFrameRecorder,将SRS的推送地址传入
        recorder = FrameRecorder.createDefault(RECORD_ADDRESS, getCameraImageWidth(), getCameraImageHeight());

        // 降低启动时的延时,参考
        // https://trac.ffmpeg.org/wiki/StreamingGuide)
        recorder.setVideoOption("tune", "zerolatency");
        // 在视频质量和编码速度之间选择适合自己的方案,包括这些选项:
        // ultrafast,superfast, veryfast, faster, fast, medium, slow, slower, veryslow
        // ultrafast offers us the least amount of compression (lower encoder
        // CPU) at the cost of a larger stream size
        // at the other end, veryslow provides the best compression (high
        // encoder CPU) while lowering the stream size
        // (see: https://trac.ffmpeg.org/wiki/Encode/H.264)
        // ultrafast对CPU消耗最低
        recorder.setVideoOption("preset", "ultrafast");
        // Constant Rate Factor (see: https://trac.ffmpeg.org/wiki/Encode/H.264)
        recorder.setVideoOption("crf", "28");
        // 2000 kb/s, reasonable "sane" area for 720
        recorder.setVideoBitrate(2000000);

        // 设置编码格式
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);

        // 设置封装格式
        recorder.setFormat("flv");

        // FPS (frames per second)
        // 一秒内的帧数
        recorder.setFrameRate(getFrameRate());
        // Key frame interval, in our case every 2 seconds -> 30 (fps) * 2 = 60
        // 关键帧间隔
        recorder.setGopSize((int)getFrameRate()*2);

        // 帧录制器开始初始化
        recorder.start();
    }
  • 接下来是output方法,关键是recorder.record,另外要注意时间戳的计算和设置:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @Override
    protected void output(Frame frame) throws Exception {
        if (0L==startRecordTime) {
            startRecordTime = System.currentTimeMillis();
        }

        // 时间戳
        recorder.setTimestamp(1000 * (System.currentTimeMillis()-startRecordTime));

        // 存盘
        recorder.record(frame);
    }
  • 最后是处理视频的循环结束后,程序退出前要做的事情,即关闭帧抓取器:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @Override
    protected void releaseOutputResource() throws Exception {
        recorder.close();
    }
  • 另外还要注意两帧之间的延时,由于推流涉及到网络,因此不能像本地预览那样根据帧率严格计算,实际间隔要更小一些:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @Override
    protected int getInterval() {
        // 相比本地预览,推流时两帧间隔时间更短
        return super.getInterval()/4;
    }
  • 至此,推流功能已开发完成,再写上main方法,注意参数600表示抓取和录制的操作执行600秒:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static void main(String[] args) {
        new RecordCamera().action(600);
    }
  • 运行main方法,等到控制台输出下图红框的内容时,表示已经开始推流:
  • 用本机或局域网内另一台电脑,用VLC软件打开刚才推流的地址rtmp://192.168.50.43:21935/hls/camera,稍等几秒钟后开始正常播放:
  • 还可用VLC的工具查看编码信息:
  • 至此,咱们已完成了推流功能,验证远程播放也正常,得益于JavaCV的强大,整个过程是如此的轻松愉快,接下来请继续关注欣宸原创,《JavaCV的摄像头实战》系列还会呈现更多丰富的应用;
  • 此刻聪明的您一定发现了问题:只推视频吗?连声音都没有,就这?没错,接下来的实战,咱们该挑战音频处理了

源码下载

  • 《JavaCV的摄像头实战》的完整源码可在GitHub下载到,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):

名称

链接

备注

项目主页

https://github.com/zq2599/blog_demos

该项目在GitHub上的主页

git仓库地址(https)

https://github.com/zq2599/blog_demos.git

该项目源码的仓库地址,https协议

git仓库地址(ssh)

git@github.com:zq2599/blog_demos.git

该项目源码的仓库地址,ssh协议

  • 这个git项目中有多个文件夹,本篇的源码在javacv-tutorials文件夹下,如下图红框所示:
  • javacv-tutorials里面有多个子工程,《JavaCV的摄像头实战》系列的代码在simple-grab-push工程下:
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/12/02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
EasyGBS告警功能如何实现普通用户登录显示对应告警信息?
去年,我们成功在EasyGBS平台增加了GB告警功能,随后不久,EasyCVR也增加了告警功能。近期,我们对告警功能提出了新的要求,就是允许普通用户登录EasyGBS后,能够看到自身权限下的告警信息。
TSINGSEE青犀视频
2021/08/17
5240
EasyGBS告警功能如何实现普通用户登录显示对应告警信息?
EasyGBS录像计划查询通道列表添加通道及设备名称搜索功能
目前EasyGBS录像计划查询通道列表的时候,右上角搜索框只能搜索设备id和通道id,用户使用起来不方便,所以我们需要添加一个可以根据设备名称以及通道名称搜索的功能。
TSINGSEE青犀视频
2021/08/31
5810
EasyGBS删除告警信息后无法同步删除告警录像和快照的优化
在TSINGSEE青犀视频平台中,EasyGBS和EasyCVR结构化智能分析平台都是支持告警上报功能的,当EasyGBS在底层数据收集上来后,在对原始数据解析,增加了告警计算后将告警信息持久化,当监测有异常情况时,系统就会自动截取快照并记录时间。
TSINGSEE青犀视频
2021/09/27
1.2K0
国标GB28181协议视频结构化平台EasyGBS如何上传设备告警信息至平台上?
在TSINGSEE青犀视频平台中,EasyGBS和EasyCVR结构化智能分析平台都是支持告警上报功能的,当EasyGBS在底层数据收集上来后,在对原始数据解析,增加了告警计算后将告警信息持久化,当监测有异常情况时,系统就会自动截取快照并记录时间。
TSINGSEE青犀视频
2021/04/12
6730
国标GB28181协议视频平台EasyGBS如何实现CDN推流分发?
在直播系统中加入CDN,是传输内容尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输速度更快、更稳定。因此TSINGSEE青犀视频为了提高国标协议下视频传输的质量,在国标GB28181协议视频平台EasyGBS通道添加了CDN功能。
TSINGSEE青犀视频
2021/02/24
8350
mysql分页读取数据重复问题
服务端开发过程中,我们通常需要与mysql数据库进行数据交互。在大多数情况下,由于数据量过大、网络时延、mysql参数配置限制,以及业务逻辑的限制等,需要我们对所需的数据进行分页读取。尤其是需要读取的数据量过大时,我们经常会遇到下面这种错误类型。
闻说社
2024/12/02
5760
mysql分页读取数据重复问题
测试需求平台17-产品管理分页功能和样式优化
数据较多时候使用分页控制信息数量,也可以进行页面的转跳,常搭配 列表List 或 表格Table 使用。
MegaQi
2023/10/21
3070
测试需求平台17-产品管理分页功能和样式优化
WinForm程序虚拟分页(实时加载数据)
通过访问数据库的分页存储过程获取某一页的数据 由于这个类的代码并非我写的,所以这里不在公布了 此类公开的几个字段和一个方法如下
liulun
2022/05/09
1.1K0
Pagination(分页) 从前台到后端总结
困惑了我一段时间的网页分页,今天特地整理了一下我完成不久的项目。下面我要分享下我这个项目的分页代码,项目源代码:https://github.com/MuYunyun/ZHITWeb
牧云云
2022/03/10
1.4K0
Pagination(分页) 从前台到后端总结
Flutter快速开发——列表分页加载封装
在 App 中,列表数据加载是一个很常见的功能,几乎大多数 App 中都存在列表数据的展示,而对于大数据量的列表展示,为提高用户体验、减少服务器压力等,一般采用分页加载列表数据,首次只加载一页数据,当用户向下滑动列表到底部时再触发加载下一页数据。
loongwind
2022/09/27
6.7K4
Flutter快速开发——列表分页加载封装
GraphQL+Koa2实现服务端API结合Apollo+Vue
注意:GraphQL 是 api 的查询语言,而不是数据库。从这个意义上说,它是数据库无关的, 而且可以在使用 API 的任何环境中有效使用,我们可以理解为 GraphQL 是基于 API 之上的一 层封装,目的是为了更好,更灵活的适用于业务的需求变化
前端进阶之旅
2022/07/29
5.6K1
GraphQL+Koa2实现服务端API结合Apollo+Vue
记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题
最近有项目反应,在服务器CPU使用较高的时候,我们的事件查询页面非常的慢,查询几条记录竟然要4分钟甚至更长,而且在翻第二页的时候也是要这么多的时间,这肯定是不能接受的,也是让现场用SQLServerProfiler把语句抓取了上来。 用ROW_NUMBER()进行分页 我们看看现场抓上来的分页语句: select top 20 a.*,ag.Name as AgentServerName,,d.Name as MgrObjTypeName,l.UserName as userName from event
逸鹏
2018/04/11
1.9K0
记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题
Django 使用Paginator分页器
上方的分页代码还有一个不足之处,当我们的页码数量过多时,会全部展示出来,整个页面都是很不美观,我们直接在上方代码上稍加修改一下试试.
王 瑞
2022/12/28
1.3K0
Django 使用Paginator分页器
我自己写的一个分页控件(源码和演示代码)PostBack分页版 for vs2003、SQL Server
温馨提示: asp.net分页控件已经升级了,基于.net2.0 ,支持多种数据库。 正式命名为:QuickPager Asp.net 2.0 分页控件。 网站:www.natureFW.com 下载:http://www.naturefw.com/down/List1.aspx 在线演示:http://demo.naturefw.com 上一篇随笔: 我的分页控件(未完,待续)——控件件介绍及思路 一、分页控件的工作层次     如果按照三层的划分方式来说,应该算作工作在 UI层 和 逻辑层
用户1174620
2018/02/08
1.1K0
测试开发:Python + Flask 实现接口接收 Disk 信息
今天分享的内容是基于:测试开发:Python + Flask 实现接口接收内存信息 来进一步分享如何使用 Python + Flask 实现接收 Disk 的信息。
Wu_Candy
2022/07/04
3670
测试开发:Python + Flask 实现接口接收 Disk 信息
day04_MySQL学习笔记_01
数据库(DataBase,DB):指长期保存在计算机的存储设备上,按照一定规则组织起来,可以被各种用户或应用共享的数据集合。(文件系统)
黑泽君
2018/10/11
9100
day04_MySQL学习笔记_01
18 . Go之操作Mysql和sqlx使用
bindvars的一个常见误解是,它们用来在sql语句中插入值。它们其实仅用于参数化,不允许更改SQL语句的结构。例如,使用bindvars尝试参数化列或表名将不起作用:
iginkgo18
2022/05/09
1.9K0
javaWeb核心技术第十二篇之分页和条件
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
海仔
2019/09/18
9540
Bootstrap Bootstrap表格插件bootstrap-table配置与应用小结
https://gitee.com/ishouke/front_end_plugin/blob/master/jquery-3.2.1.min.js
授客
2019/09/10
13.8K0
Bootstrap Bootstrap表格插件bootstrap-table配置与应用小结
GridView实战一:自定义分页、排序、修改、插入、删除
前言:   在某次公司面试时被问到对GridView操作的熟悉程度,在那之前一直用Repeater内嵌table标签对GridView操作确实很少,于是最近在项目的后台上对GridView进行了一番实操,本文和后面的另一篇GridView实战二:使用ObjectDataSource数据源控件均是这段时间的一些总结。   GridView优点就是集数据绑定、分页、排序、删、改于一身,提高了开发效率;缺点嘛,就是运行效率低,并且它本身不带添加功能。于是GridView用于后台开发是一个不错的选择,而前台页面还是
^_^肥仔John
2018/01/18
3.2K0
GridView实战一:自定义分页、排序、修改、插入、删除
推荐阅读
相关推荐
EasyGBS告警功能如何实现普通用户登录显示对应告警信息?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验