前言
查看了相关文章然后一笔一笔打代码再调试成功出结果,
eguid的博客
不保证代码能够原封不动就能运行,
这里做一下记录。
ps:代码内容有改动,原版的可以看原作者的。
代码内容
package net.w2p.JCVStudio.zhiboStudy;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Point;
import org.bytedeco.opencv.opencv_core.Scalar;
import org.bytedeco.opencv.opencv_videoio.VideoCapture;
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 在lesson01基础上继续优化。测试推流--推到本地文件或者推到远程服务器上面。
* https://blog.csdn.net/eguid_1/article/details/52678775
* 推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG、javaCV-openCV)
* 推流器 测试。
* 原创本博客已停止维护!-eguid 发布于2016-09-27 11:50:00 阅读数 30135 收藏
* **/
public class Lesson02 {
/***
* 添加水印并且导出为一个MP4文件。
*
* **/
public void push(
String outputUrl
,final int frameRate
) throws Exception {
//做好自己!--eguid!http://www.eguid.cc
String msg="fps:";//水印文字
// 水印文字位置
Point point = new Point(10, 50);
// 颜色,使用黄色
Scalar scalar = new Scalar(0, 255, 255, 0);
DecimalFormat df=new DecimalFormat(".##");//数字格式化
VideoCapture vc=null;
//遍历查找摄像头
int index=-1;
for(;index<2;index++){
vc=new VideoCapture(index);
if(vc.grab()){
//找到摄像头设备,退出遍历
System.err.println("做好自己!--eguid温馨提示,获取本机当前摄像头序号:"+index);
break;
}
vc.close();//没找到设备,释放资源
}
//vc为null,并且设备没正常开启,说明没找到设备
if(vc!=null&&!vc.isOpened()){
System.err.println("无法找到摄像头,请检查是否存在摄像头设备");
return;
}
//使用java的JFrame显示图像
CanvasFrame cFrame = new CanvasFrame("做好自己!--eguid!http://www.eguid.cc",
CanvasFrame.getDefaultGamma()/2.2);
cFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// cFrame.setAlwaysOnTop(true);
//javacv提供的转换器,方便mat转换为Frame
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
Mat mat=new Mat();
double start=System.currentTimeMillis();
double end;
Frame ftmp=null;
Java2DFrameConverter converter1 = new Java2DFrameConverter();
OpenCVFrameConverter.ToIplImage converter2 = new OpenCVFrameConverter.ToIplImage();
final String outputFilePath=outputUrl;
FFmpegFrameRecorder recorder = null;
long startTime=0;
long videoTS=0;
final ConcurrentHashMap<String,Object> map4Middle=new ConcurrentHashMap<>(2);
cFrame.addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
System.out.println("Closed");
FFmpegFrameRecorder recorder2=null;
if(map4Middle.get("recorder")!=null){
recorder2=(FFmpegFrameRecorder)map4Middle.get("recorder");
}
map4Middle.put("stop",true);
try{
if(recorder2!=null){
recorder2.stop();
recorder2.release();
}
System.out.println("窗口关闭啦,请做收尾工作");
}
catch (Exception ed){
ed.printStackTrace();
}
e.getWindow().dispose();
// grabber.stop();//停止抓取
System.exit(-1);//退出
return;
}
});
map4Middle.put("stop",false);
for(int i=0;;i++){
ftmp=null;
vc.retrieve(mat);//重新获取mat
if(vc.grab()){//是否采集到摄像头数据
if(vc.read(mat)){//读取一帧mat图像
end=System.currentTimeMillis();
if(mat!=null){
opencv_imgproc.putText(mat,msg+df.format((1000.0/(end-start))),
point, opencv_imgproc.CV_FONT_VECTOR0, 1.2, scalar,
1, 20, false);
}
// opencv_highgui.imshow("eguid", mat);该opencv方法windows下会无响应
ftmp=converter.convert(mat);
// Frame rotatedFrame=converter.convert(grabbedImage);//不知道为什么这里不做转换就不能推到rtmp
if(recorder==null){
recorder=
new FFmpegFrameRecorder(outputFilePath,
ftmp.imageWidth,ftmp.imageHeight);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264,编码
// recorder.setFormat("flv");
recorder.setFormat("flv");//封装格式,如果是推送到rtmp就必须是flv封装格式
recorder.setPixelFormat(0);
recorder.setFrameRate(frameRate);
recorder.setVideoOption("preset", "ultrafast");
recorder.setVideoOption("tune", "zerolatency");
recorder.setVideoOption("fflags", "nobuffer");
recorder.setVideoOption("analyzeduration", "0");
// recorder.setVideoOption("preset","ultrafast");
// recorder.setVideoOption("tune", "zerolatency");
try {
recorder.start();
map4Middle.put("recorder",recorder);
}
catch (Exception ed){
ed.printStackTrace();
}
}
cFrame.showImage(ftmp);
if(recorder.isCloseOutputStream()){
return;
}
/***计算帧的时间**/
if (startTime == 0) {
startTime = System.currentTimeMillis();
}
videoTS = 1000 * (System.currentTimeMillis() - startTime);
Boolean isStop=false;
isStop=(Boolean)map4Middle.get("stop");
if(isStop){
return;
}
recorder.setTimestamp(videoTS);
recorder.record(ftmp);
System.err.println(i);
start=end;
}
mat.release();//释放mat
if(ftmp!=null){
//--导出到视频中区。
}
}
}
}
public static void main(String[] args) throws Exception {
Lesson02 test=new Lesson02();
//--普通推送到文件保存。
// test.push("/home/too-white/temp/002_push.flv",25);
final String rtmpUrl="rtmp://localhost/live/livestream";
test.push(rtmpUrl,25);
//--播放地址也是这个啊。。
}
}