推送本機視頻流到流媒體服務器


前言:

上一章簡單的介紹了javacv並且演示了如何獲取本機攝像頭: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,通過這種方式創建的資源無法通過虛擬機的GC來清理內存,需要手動進行釋放資源,以防止內存溢出錯誤)

 

    /**
         * 按幀錄制本機攝像頭視頻(邊預覽邊錄制,停止預覽即停止錄制)
         *
         * @author eguid
         * @param outputFile -錄制的文件路徑,也可以是rtsp或者rtmp等流媒體服務器發布地址
         * @param frameRate - 視頻幀率
         * @throws Exception
         * @throws InterruptedException
         * @throws org.bytedeco.javacv.FrameRecorder.Exception
         */
        public static void recordCamera(String outputFile, double frameRate)
                throws Exception, InterruptedException, org.bytedeco.javacv.FrameRecorder.Exception {
            Loader.load(opencv_objdetect.class);
            FrameGrabber grabber = FrameGrabber.createDefault(0);//本機攝像頭默認0,這里使用javacv的抓取器,至於使用的是ffmpeg還是opencv,請自行查看源碼
            grabber.start();//開啟抓取器
     
            OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();//轉換器
            IplImage grabbedImage = converter.convert(grabber.grab());//抓取一幀視頻並將其轉換為圖像,至於用這個圖像用來做什么?加水印,人臉識別等等自行添加
            int width = grabbedImage.width();
            int height = grabbedImage.height();
        
            FrameRecorder recorder = FrameRecorder.createDefault(outputFile, width, height);
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264,編碼
            recorder.setFormat("flv");//封裝格式,如果是推送到rtmp就必須是flv封裝格式
            recorder.setFrameRate(frameRate);
            
            recorder.start();//開啟錄制器
            long startTime=0;
            long videoTS=0;
            CanvasFrame frame = new CanvasFrame("camera", CanvasFrame.getDefaultGamma() / grabber.getGamma());
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setAlwaysOnTop(true);
            Frame rotatedFrame=converter.convert(grabbedImage);//不知道為什么這里不做轉換就不能推到rtmp
            while (frame.isVisible() && (grabbedImage = converter.convert(grabber.grab())) != null) {
                rotatedFrame = converter.convert(grabbedImage);
                frame.showImage(rotatedFrame);
                if (startTime == 0) {
                    startTime = System.currentTimeMillis();
                }
                videoTS = 1000 * (System.currentTimeMillis() - startTime);
                recorder.setTimestamp(videoTS);
                recorder.record(rotatedFrame);
                Thread.sleep(40);
            }
            frame.dispose();
            recorder.stop();
            recorder.release();
            grabber.stop();
        
        }

總的來說,我們已經實現了基本的推流器功能,那么需要注意的就是轉換那里,不清楚為什么不做轉換就不能推送到rtmp流媒體服務器,如果哪位有更好的方案希望可以聯系博主,感謝!
3、測試錄制功能和推流功能

 

    public static void main(String[] args) throws Exception, InterruptedException, org.bytedeco.javacv.FrameRecorder.Exception {
            recordCamera("output.mp4",25);
        }

    public static void main(String[] args) throws Exception, InterruptedException, org.bytedeco.javacv.FrameRecorder.Exception {
            recordCamera("rtmp://192.168.30.21/live/record1",25);
        }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM