当前位置: 代码迷 >> 综合 >> javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG、javaCV-openCV)
  详细解决方案

javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG、javaCV-openCV)

热度:105   发布时间:2023-11-25 03:15:57.0


转自:http://blog.csdn.net/eguid_1/article/details/51659578

本章将在上一章的基础上,增加视频推流到流媒体服务器和视频录制的功能;

功能:实现边播放边录制/推流,停止预览即停止录制/推流

提示:

1、本章代码从发布至今测试运行正常,如遇到错误请自觉检查环境配置和jar包问题

2、到目前为止大家遇到的问题100%都是jar包问题,那么如果遇到各种异常和报错,请参照第一条,谢谢

一、开发所依赖的包

javacv.jar,javacpp.jar,ffmpeg.jar,ffmpeg-系统平台.jar,OpenCV.jar,opencv-系统平台.jar。

其中ffmpeg-系统平台.jar,opencv-系统平台.jar中的系统平台根据开发环境或者测试部署环境自行更改为对应的jar包,比如windows7 64位系统替换为ffmpeg-x86-x64.jar

为什么要这样做:因为ffmpeg-系统平台.jar中存放的是c/c++本地so/dll库,而ffmpeg.jar就是使用javacpp封装的对应本地库Java接口的实现,而javacpp就是基于jni的一个功能性封装包,方便实现jni,javacv.jar就是对9个视觉库进行了二次封装,但是实现的功能有限,所以建议新手先熟悉openCV和ffmpeg这两个C/C++库的API后再来看javaCV思路就会很清晰了。

二、代码实现

本功能采用按帧录制/推流,通过关闭播放窗口停止视频录制/推流

注:长时间运行该代码会导致内存溢出的原因是没有及时释放IplImage资源(由于javacv是jni方式调用C,部分对象需要手动释放资源,以防止内存溢出错误)

[java] view plaincopy
print?

      1. /** 
      2.      * 按帧录制本机摄像头视频(边预览边录制,停止预览即停止录制) 
      3.      *  
      4.      * @author eguid 
      5.      * @param outputFile -录制的文件路径,也可以是rtsp或者rtmp等流媒体服务器发布地址 
      6.      * @param frameRate - 视频帧率 
      7.      * @throws Exception 
      8.      * @throws InterruptedException 
      9.      * @throws org.bytedeco.javacv.FrameRecorder.Exception 
      10.      */  
      11.     public static void recordCamera(String outputFile, double frameRate)  
      12.             throws Exception, InterruptedException, org.bytedeco.javacv.FrameRecorder.Exception {  
      13.         Loader.load(opencv_objdetect.class);  
      14.         FrameGrabber grabber = FrameGrabber.createDefault(0);//本机摄像头默认0,这里使用javacv的抓取器,至于使用的是ffmpeg还是opencv,请自行查看源码  
      15.         grabber.start();//开启抓取器  
      16.   
      17.         OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();//转换器  
      18.         IplImage grabbedImage = converter.convert(grabber.grab());//抓取一帧视频并将其转换为图像,至于用这个图像用来做什么?加水印,人脸识别等等自行添加  
      19.         int width = grabbedImage.width();  
      20.         int height = grabbedImage.height();  
      21.       
      22.         FrameRecorder recorder = FrameRecorder.createDefault(outputFile, width, height);  
      23.         recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264,编码  
      24.         recorder.setFormat("flv");//封装格式,如果是推送到rtmp就必须是flv封装格式  
      25.         recorder.setFrameRate(frameRate);  
      26.           
      27.         recorder.start();//开启录制器  
      28.         long startTime=0;  
      29.         long videoTS=0;  
      30.         CanvasFrame frame = new CanvasFrame("camera", CanvasFrame.getDefaultGamma() / grabber.getGamma());  
      31.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
      32.         frame.setAlwaysOnTop(true);  
      33.         Frame rotatedFrame=converter.convert(grabbedImage);//不知道为什么这里不做转换就不能推到rtmp  
      34.         while (frame.isVisible() && (grabbedImage = converter.convert(grabber.grab())) != null) {  
      35.             rotatedFrame = converter.convert(grabbedImage);  
      36.             frame.showImage(rotatedFrame);  
      37.             if (startTime == 0) {  
      38.                 startTime = System.currentTimeMillis();  
      39.             }  
      40.             videoTS = 1000 * (System.currentTimeMillis() - startTime);  
      41.             recorder.setTimestamp(videoTS);  
      42.             recorder.record(rotatedFrame);  
      43.             Thread.sleep(40);  
      44.         }  
      45.         frame.dispose();  
      46.         recorder.stop();  
      47.         recorder.release();  
      48.         grabber.stop();  
      49.       
      50.     }  
总的来说,我们已经实现了基本的推流器功能,那么需要注意的就是转换那里,不清楚为什么不做转换就不能推送到rtmp流媒体服务器,如果哪位有更好的方案希望可以联系博主,感谢!

3、测试录制功能和推流功能

[java] view plaincopy
print?

      1. public static void main(String[] args) throws Exception, InterruptedException, org.bytedeco.javacv.FrameRecorder.Exception {  
      2.         recordCamera("output.mp4",25);  
      3.     }  
[java] view plaincopy
print?
      1. public static void main(String[] args) throws Exception, InterruptedException, org.bytedeco.javacv.FrameRecorder.Exception {  
      2.         recordCamera("rtmp://192.168.30.21/live/record1",25);  
      3.     }  


看到了摄像头窗口就说明已经开始录制,点击右上角关闭按钮即停止录制视频,在录制的时候刷新项目目录发现新生成了一个output.mp4文件,可以正常播放这个视频文件

到这章我们已经实现了录制本地摄像头视频和推送摄像头的视频到服务器,小伙伴们已经迫不及待的开始在线直播show了 - -!

既然已经实现了在线直播,那么我们想要保存或者播放别人的在线直播视频怎么办呢?

下一章将会讲解如何录制流媒体服务器的视频到本地文件,当然是可以在线播放的

  相关解决方案