JavaCV 采集摄像头和麦克风数据推送到流媒体服务器
越来越觉得放弃JavaCV FFmpeg native API,直接使用JavaCV二次封装的API开发是很明智的选择,使用JavaCV二次封装的API开发避免了各种内存操作不当引起的crash。
上一次介绍了 JavaCV 采集摄像头及桌面视频数据,这次介绍一下如何采集摄像头和麦克风数据推送到流媒体服务器。
引入依赖
跟上一次一样,这里使用的还是最新的JavaCV库(1.5.5).
<properties>
<javacpp.version>1.5.5</javacpp.version>
</properties>
<dependencies>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>${javacpp.version}</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>${javacpp.version}</version>
</dependency>
</dependencies>
视频采集录制
在 JavaCV 采集摄像头及桌面视频数据 介绍了两种采集摄像头数据的方法,这里采用第一种,即使用 OpencvFrameGrabber 采集摄像头数据。
public class VideoRecorder implements Runnable {
private static final int VIDEO_DEVICE_INDEX = 0;
private FFmpegFrameRecorder recorder;
private int width, height;
public VideoRecorder(FFmpegFrameRecorder recorder, int width, int height) {
this.recorder = recorder;
this.width = width;
this.height = height;
}
@Override
public void run() {
try {
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(VIDEO_DEVICE_INDEX);
grabber.setImageWidth(width);
grabber.setImageHeight(height);
grabber.start();
long startTS = 0, videoTS = 0;
Frame frame = null;
while (!Thread.interrupted() && (frame = grabber.grab()) != null) {
if (startTS == 0) {
startTS = System.currentTimeMillis();
}
videoTS = 1000 * (System.currentTimeMillis() - startTS);
if (videoTS > recorder.getTimestamp()) {
recorder.setTimestamp(videoTS);
}
recorder.record(frame);
}
grabber.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
音频采集录制
音频采集直接使用JDK的API即可,直接读麦克风的数据塞给录制器,采样率为44100,16bit,小端模式。
public class AudioRecoder implements Runnable {
private FFmpegFrameRecorder recorder;
private int channels;
private int sampleRate;
public AudioRecoder(FFmpegFrameRecorder recorder, int sampleRate, int channels) {
this.recorder = recorder;
this.sampleRate = sampleRate;
this.channels = channels;
}
@Override
public void run() {
try {
AudioFormat format = new AudioFormat(Float.valueOf(sampleRate), 16, channels, true, false);
TargetDataLine line = (TargetDataLine) AudioSystem.getLine(new DataLine.Info(TargetDataLine.class, format));
line.open(format);
line.start();
int sampleRate = (int) format.getSampleRate();
int numChannels = format.getChannels();
byte[] buffer = new byte[sampleRate * numChannels];
while (!Thread.interrupted()) {
int nBytesRead = 0;
while (nBytesRead == 0) {
nBytesRead = line.read(buffer, 0, line.available());
}
int nSamplesRead = nBytesRead / 2;
short[] samples = new short[nSamplesRead];
ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(samples);
ShortBuffer sBuff = ShortBuffer.wrap(samples, 0, nSamplesRead);
recorder.recordSamples(sampleRate, numChannels, sBuff);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
录制推流
这里的录制推流涉及音频和视频,音频和视频分开线程采集并录制,这样可以降低延迟,在录制推流方面还可以通过设置录制参数降低延迟:
recorder.setVideoOption("tune", "zerolatency");
recorder.setVideoOption("preset", "ultrafast");
启动录制推流器,视频采集录制线程和音频采集录制线程,开始推流:
recorder.start();
Thread vt = new Thread(new VideoRecorder(recorder, width, height));
Thread at = new Thread(new AudioRecoder(recorder, sampleRate, channels));
vt.start();
at.start();
vt.join();
at.join();
效果展示
可以使用VLC拉取程序的推流查看效果:

拉流的音视频流信息:

录制推流完整源码可以在公众号上获取
=========================================================
关注公众号 “HiIT青年” 发送 “javacv-recoder” 获取。(如果没有收到回复,可能是你之前取消过关注。)

关注公众号,阅读更多文章。
JavaCV 采集摄像头和麦克风数据推送到流媒体服务器的更多相关文章
- EasyDarwin开源手机直播方案:EasyPusher手机直播推送,EasyDarwin流媒体服务器,EasyPlayer手机播放器
在不断进行EasyDarwin开源流媒体服务器的功能和性能完善的同时,我们也配套实现了目前在安防和移动互联网行业比较火热的移动端手机直播方案,主要就是我们的 EasyPusher直播推送项目 和 Ea ...
- javaCV开发详解之6:本地音频(话筒设备)和视频(摄像头)抓取、混合并推送(录制)到服务器(本地)
javaCV系列文章: javacv开发详解之1:调用本机摄像头视频 javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG.j ...
- JavaCV 采集摄像头及桌面视频数据
javacv 封装了javacpp-presets库很多native API,简化了开发,对java程序员来说比较友好. 之前使用JavaCV库都是使用ffmpeg native API开发,这种方式 ...
- C# 数据推送 实时数据推送 轻量级消息订阅发布 多级消息推送 分布式推送
前言 本文将使用一个NuGet公开的组件技术来实现数据订阅推送功能,由服务器进行推送数据,客户端订阅指定的数据后,即可以接收服务器推送过来的数据,包含了自动重连功能,使用非常方便 nuget地址:ht ...
- 使用Node.js实现数据推送
业务场景:后端更新数据推送到客户端(Java部分使用Tomcat服务器). 后端推送数据的解决方案有很多,比如轮询.Comet.WebSocket. 1. 轮询对于后端来说开发成本最低,就是按照传统的 ...
- 基于Web的数据推送技术(转)
基于Web的数据推送技术 对于实时性数据显示要求比较高的系统,比如竞价,股票行情,实时聊天等,我们的解决方案有以下几种.1. HTTP请求发送模式,一般可以基于ajax的请求,比如每3秒一次访问下服务 ...
- javascript之数据推送
我们使用ajax与后台服务进行交互,常常是通过触发事件来单次交互,但对于有些web应用来说,需要前台与后台保持长连接,前端不定时地接收后台推送的数据信息, 例如:股票行情分析.聊天室和网页在线游戏等. ...
- HTML5支持服务器发送事件(Server-Sent Events)-单向消息传递数据推送(C#示例)
传统的WEB应用程序通信时的简单时序图: 现在Web App中,大都有Ajax,是这样子: HTML5有一个Server-Sent Events(SSE)功能,允许服务端推送数据到客户端.(通常叫数据 ...
- SSE技术详解:使用 HTTP 做服务端数据推送应用的技术
SSE ( Server-sent Events )是 WebSocket 的一种轻量代替方案,使用 HTTP 协议. 严格地说,HTTP 协议是没有办法做服务器推送的,但是当服务器向客户端声明接下来 ...
随机推荐
- learning free programming resources form top university of the world
learning free programming resources form top university of the world Harvard university https://www. ...
- 纯CSS实现内容放大缩小效果
先搭架子 再实现第一个内容 填充更多内容 拆掉border,查看最终效果 html代码 <!-- 服务 --> <div class="service"> ...
- yum install valgrind.x86_64
Reference: https://cloudlinux.zendesk.com/hc/en-us/articles/115004075294-Fix-rpmdb-Thread-died-in-Be ...
- 控制流程-if/while/for
目录 一.控制流程之if判断 1.单分支结构 2.双分支结构 3.多分支结构 二.控制流程之while循环 1.基本使用 2.break 3.continue 三.流程控制之for循环 1.break ...
- Django之csrf中间件及auth模块使用
目录 一.基于配置文件的编程思想 1. importlib 模块 2. 配置文件 二.跨站请求伪造(csrf) 1.csrf简介以及由来 2.Django中的csrf中间件如何使用 2.1 普通for ...
- ImportError: No module named _ssl解决方法
import ssl时出现ImportError: No module named _ssl错误是因为咱安装Python的时候没有把ssl模块编译进去导致的. 解决步骤: 系统没有openssl,手动 ...
- [源码解析] 消息队列 Kombu 之 基本架构
[源码解析] 消息队列 Kombu 之 基本架构 目录 [源码解析] 消息队列 Kombu 之 基本架构 0x00 摘要 0x01 AMQP 1.1 基本概念 1.2 工作过程 0x02 Poll系列 ...
- 基于 react + electron 开发及结合爬虫的应用实践🎅
前言 Electron 是一个可以使用 Web 技术如 JavaScript.HTML 和 CSS 来创建跨平台原生桌面应用的框架.借助 Electron,我们可以使用纯 JavaScript 来调用 ...
- if...else和switch...case
一.位运算 class Demo01 { public static void main(String[] args) { int a = 5; int b = 3; /* 0000 0101 |00 ...
- ubuntu上pyecharts V1版本环境搭建
1 背景 今天想用pyecharts画图,在新的环境下使用pip安装之后发现,导入pyecharts模块一直失败,报错如下. 图 1 导入pyecharts错误图 请注意:我这里使用的python版本 ...