欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

本篇概览

  • 本文是《JavaCV的摄像头实战》的第五篇,一起来考虑个问题:本地摄像头的内容,如何让网络上的其他人看见?

  • 这就涉及到了推流,如下图,基于JavaCV的应用将摄像头的视频帧推送到媒体服务器,观看者用播放器软件远程连接媒体服务器,就能观看摄像头的内容了:

  • 今天的主要工作就是开发上图的JavaCV应用,然后验证功能是否正常;

编码

  • 《JavaCV的摄像头实战之一:基础》一文创建的simple-grab-push工程中已写好父类AbstractCameraApplication,本篇继续使用该工程,创建子类实现那些抽象方法即可

  • 编码前先回顾父类的基础结构,如下图,粗体是父类定义的各个方法,红色块都是需要子类来实现抽象方法,所以接下来,咱们以本地窗口预览为目标实现这三个红色方法即可:

  • 新建文件RecordCamera.java,这是AbstractCameraApplication的子类,其代码很简单,接下来按上图顺序依次说明

  • 《JavaCV的摄像头实战之一:基础》中已部署好了媒体服务器,这里定义一个成员变量保存媒体服务器的推流地址,请您按自己的情况调整:

private static final String RECORD_ADDRESS = "rtmp://192.168.50.43:21935/hls/camera";
  • 还要准备一个成员变量,推流的时候在帧上添加时间戳:
protected long startRecordTime = 0L;
  • 将视频帧推送到媒体服务器的功能来自FrameRecorder,这是个抽象类,本篇用到的是其子类FFmpegFrameRecorder,所以定义FrameRecorder类型的成员变量:
	// 帧录制器
protected FrameRecorder recorder;
  • 然后是初始化操作,请注意各项参数设置(1280*720分辨率摄像头的情况):
    @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,另外要注意时间戳的计算和设置:
    @Override
protected void output(Frame frame) throws Exception {
if (0L==startRecordTime) {
startRecordTime = System.currentTimeMillis();
} // 时间戳
recorder.setTimestamp(1000 * (System.currentTimeMillis()-startRecordTime)); // 存盘
recorder.record(frame);
}
  • 最后是处理视频的循环结束后,程序退出前要做的事情,即关闭帧抓取器:
    @Override
protected void releaseOutputResource() throws Exception {
recorder.close();
}
  • 另外还要注意两帧之间的延时,由于推流涉及到网络,因此不能像本地预览那样根据帧率严格计算,实际间隔要更小一些:
    @Override
protected int getInterval() {
// 相比本地预览,推流时两帧间隔时间更短
return super.getInterval()/4;
}
  • 至此,推流功能已开发完成,再写上main方法,注意参数600表示抓取和录制的操作执行600秒:
    public static void main(String[] args) {
new RecordCamera().action(600);
}
  • 运行main方法,等到控制台输出下图红框的内容时,表示已经开始推流:

  • 用本机或局域网内另一台电脑,用VLC软件打开刚才推流的地址rtmp://192.168.50.43:21935/hls/camera,稍等几秒钟后开始正常播放:

  • 还可用VLC的工具查看编码信息:

  • 至此,咱们已完成了推流功能,验证远程播放也正常,得益于JavaCV的强大,整个过程是如此的轻松愉快,接下来请继续关注欣宸原创,《JavaCV的摄像头实战》系列还会呈现更多丰富的应用;

  • 此刻聪明的您一定发现了问题:只推视频吗?连声音都没有,就这?没错,接下来的实战,咱们该挑战音频处理了

源码下载

名称 链接 备注
项目主页 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工程下:

你不孤单,欣宸原创一路相伴

https://github.com/zq2599/blog_demos

JavaCV的摄像头实战之五:推流的更多相关文章

  1. JavaCV的摄像头实战之七:推流(带声音)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<JavaCV的摄像头实战> ...

  2. JavaCV的摄像头实战之一:基础

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 关于<JavaCV的摄像头实战>系列 &l ...

  3. JavaCV的摄像头实战之二:本地窗口预览

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. JavaCV的摄像头实战之四:抓图

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<JavaCV的摄像头实战> ...

  5. JavaCV的摄像头实战之六:保存为mp4文件(有声音)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. JavaCV 采集摄像头和麦克风数据推送到流媒体服务器

    越来越觉得放弃JavaCV FFmpeg native API,直接使用JavaCV二次封装的API开发是很明智的选择,使用JavaCV二次封装的API开发避免了各种内存操作不当引起的crash. 上 ...

  7. [Java聊天室server]实战之五 读写循环(服务端)

    前言 学习不论什么一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的"多谋善断":本系列尽管涉及的是socket相关的知识,但学习之前,更 ...

  8. 利用ffmpeg一步一步编程实现摄像头采集编码推流直播系统

    了解过ffmpeg的人都知道,利用ffmpeg命令即可实现将电脑中摄像头的画面发布出去,例如发布为UDP,RTP,RTMP等,甚至可以发布为HLS,将m3u8文件和视频ts片段保存至Web服务器,普通 ...

  9. kubebuilder实战之五:operator编码

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

随机推荐

  1. 玩转 ByteBuffer

    为什么要讲 Buffer 首先为什么一个小小的 Buffer 我们需要单独拎出来聊?或者说,Buffer 具体是在哪些地方被用到的呢? 例如,我们从磁盘上读取一个文件,并不是直接就从磁盘加载到内存中, ...

  2. 【安卓】AndroidStudio使用本地gradle进行build的配置

    1.修改setting使用local gradle2.将下载的gradle-6.7.1-all.zip放入E:/AndroidProject文件夹 修改gradle-wapper.propertie使 ...

  3. Java初学者作业——实现控制台的猜数字游戏。游戏运行时产生一个1~100之间的随机数字

    返回本章节 返回作业目录 需求说明: (1)实现控制台的猜数字游戏.游戏运行时产生一个1-100之间的随机数字 (2)要求用户从控制台输入数字,若输入的数字比随机数小,则输出"太小了,再大一 ...

  4. MongoDB常用命令(2)

    1.创建数据库 use testdb 2.创建集合 db.t_member.insert({name:"zhaomin",age:23}) 3.查询 db.t_member.fin ...

  5. EMQX源码编译过程

    以emqx4.0.7版本为例 1.安装erlang环境 可以参考:https://www.cnblogs.com/shanfeng1000/p/11951703.html 这里需要注意一下,要按照em ...

  6. Kafka基础教程(二):Kafka安装

    因为kafka是基于Zookeeper的,而Zookeeper一般都是一个分布式的集群,尽管kafka有自带Zookeeper,但是一般不使用自带的,都是使用外部安装的,所以首先我们需要安装Zooke ...

  7. 『无为则无心』Python函数 — 30、Python变量的作用域

    目录 1.作用于的概念 2.局部变量 3.全局变量 4.变量的查找 5.作用域中可变数据类型变量 6.多函数程序执行流程 1.作用于的概念 变量作用域指的是变量生效的范围,在Python中一共有两种作 ...

  8. Selenium_使用switch_to.alert处理弹窗(14)

    与switch_to.window 和 switch_to.frame 相比,switch_to.alert的alert方法使用了@property 装饰器,所以在使用时alert被当成属性调用. 演 ...

  9. Linux查看进程启动时间和运行多长时间

    Linux 查看进程启动时间和运行多长时间 启动时间 ps -eo lstart 运行多长时间 ps -eo etime -bash-4.1$ ps -eo pid,lstart,etime | gr ...

  10. ANT之macrodef

    macrodef 的意思是宏定义, 可以理解为自定义函数. 对于大型部署,可以提高代码利用率. 为了方便理解,请看代码示例: <macrodef name="macro-send-fi ...