javaCV開(kāi)發(fā)詳解之推流器和錄制器的實(shí)現(xiàn)
功能
實(shí)現(xiàn)邊播放邊錄制/推流,停止預(yù)覽即停止錄制/推流
開(kāi)發(fā)所依賴(lài)的包
javacv.jar,javacpp.jar,ffmpeg.jar,ffmpeg-系統(tǒng)平臺(tái).jar,opencv.jar,opencv-系統(tǒng)平臺(tái).jar。
其中ffmpeg-系統(tǒng)平臺(tái).jar,opencv-系統(tǒng)平臺(tái).jar中的系統(tǒng)平臺(tái)根據(jù)開(kāi)發(fā)環(huán)境或者測(cè)試部署環(huán)境自行更改為對(duì)應(yīng)的jar包,比如windows7 64位系統(tǒng)替換為ffmpeg-x86-x64.jar
為什么要這樣做:因?yàn)閒fmpeg-系統(tǒng)平臺(tái).jar中存放的是c/c++本地so/dll庫(kù),而ffmpeg.jar就是使用javacpp封裝的對(duì)應(yīng)本地庫(kù)java接口的實(shí)現(xiàn),而javacpp就是基于jni的一個(gè)功能性封裝包,方便實(shí)現(xiàn)jni,javacv.jar就是對(duì)9個(gè)視覺(jué)庫(kù)進(jìn)行了二次封裝,但是實(shí)現(xiàn)的功能有限,所以建議新手先熟悉openCV和ffmpeg這兩個(gè)C/C++庫(kù)的API后再來(lái)看javaCV思路就會(huì)很清晰了。
代碼實(shí)現(xiàn)
本功能采用按幀錄制/推流,通過(guò)關(guān)閉播放窗口停止視頻錄制/推流。
注:本章代碼中的opencv轉(zhuǎn)換器是未來(lái)方便演示如何獲取圖片,長(zhǎng)時(shí)間運(yùn)行該代碼會(huì)導(dǎo)致內(nèi)存溢出的原因是沒(méi)有及時(shí)釋放IplImage資源,所以大家推流時(shí)應(yīng)當(dāng)去除轉(zhuǎn)換代碼,直接推流即可。
/** * 按幀錄制本機(jī)攝像頭視頻(邊預(yù)覽邊錄制,停止預(yù)覽即停止錄制) * * @author eguid * @param outputFile -錄制的文件路徑,也可以是rtsp或者rtmp等流媒體服務(wù)器發(fā)布地址 * @param frameRate - 視頻幀率 * @throws Exception * @throws InterruptedException * @throws org.bytedeco.javacv.FrameRecorder.Exception */ public static void recordCamera(String outputFile, double frameRate){ //另一種方式獲取攝像頭,opencv抓取器方式獲取攝像頭請(qǐng)參考第一章,F(xiàn)rameGrabber會(huì)自己去找可以打開(kāi)的攝像頭的抓取器。 FrameGrabber grabber = FrameGrabber.createDefault(0);//本機(jī)攝像頭默認(rèn)0 grabber.start();//開(kāi)啟抓取器 OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();//轉(zhuǎn)換器 IplImage grabbedImage = converter.convert(grabber.grab());//抓取一幀視頻并將其轉(zhuǎn)換為圖像,至于用這個(gè)圖像用來(lái)做什么?加水印,人臉識(shí)別等等自行添加 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();//開(kāi)啟錄制器 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);//不知道為什么這里不做轉(zhuǎn)換就不能推到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();//關(guān)閉窗口 recorder.close();//關(guān)閉推流錄制器,close包含release和stop操作 grabber.close();//關(guān)閉抓取器 }
總的來(lái)說(shuō),我們已經(jīng)實(shí)現(xiàn)了基本的推流器功能
測(cè)試錄制功能和推流功能
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); }
看到了攝像頭窗口就說(shuō)明已經(jīng)開(kāi)始錄制,點(diǎn)擊右上角關(guān)閉按鈕即停止錄制視頻,在錄制的時(shí)候刷新項(xiàng)目目錄發(fā)現(xiàn)新生成了一個(gè)output.mp4文件,可以正常播放這個(gè)視頻文件
到這章我們已經(jīng)實(shí)現(xiàn)了錄制本地?cái)z像頭視頻和推送攝像頭的視頻到服務(wù)器
以上就是javaCV開(kāi)發(fā)詳解之推流器和錄制器的實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于javaCV的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 詳解Java 微服務(wù)架構(gòu)
- 了解java架構(gòu)之微服務(wù)架構(gòu)—雪崩效應(yīng)
- java各種類(lèi)型對(duì)象占用內(nèi)存情況分析
- Java基于IDEA實(shí)現(xiàn)http編程的示例代碼
- 教你用Java驗(yàn)證服務(wù)器登錄系統(tǒng)
- Java中用POI實(shí)現(xiàn)將數(shù)據(jù)導(dǎo)出到Excel
- javaCV開(kāi)發(fā)詳解之收流器實(shí)現(xiàn)
- javacv開(kāi)發(fā)詳解之調(diào)用本機(jī)攝像頭視頻
- JavaWeb實(shí)戰(zhàn)之開(kāi)發(fā)網(wǎng)上購(gòu)物系統(tǒng)(超詳細(xì))
- JavaAgent的簡(jiǎn)單例子
- JAVA后端應(yīng)該學(xué)什么技術(shù)
- Java從單體架構(gòu)升級(jí)到微服務(wù)要注意的一些問(wèn)題
相關(guān)文章
如何使用IntelliJ IDEA搭建MyBatis-Plus框架并連接MySQL數(shù)據(jù)庫(kù)
這篇文章主要介紹了如何使用IntelliJ IDEA搭建MyBatis-Plus框架并連接MySQL數(shù)據(jù)庫(kù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-11-11Java實(shí)現(xiàn)對(duì)一行英文進(jìn)行單詞提取功能示例
這篇文章主要介紹了Java實(shí)現(xiàn)對(duì)一行英文進(jìn)行單詞提取功能,結(jié)合實(shí)例形式分析了java基于StringTokenizer類(lèi)進(jìn)行字符串分割的相關(guān)操作技巧,需要的朋友可以參考下2017-10-10MybatisPlus 插入或更新數(shù)據(jù)時(shí)自動(dòng)填充更新數(shù)據(jù)解決方案
本文主要介紹了MybatisPlus 插入或更新數(shù)據(jù)時(shí)自動(dòng)填充更新數(shù)據(jù)解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09MyBatis-Flex實(shí)現(xiàn)多表聯(lián)查(自動(dòng)映射)
我們可以輕松的使用 Mybaits-Flex 鏈接任何數(shù)據(jù)庫(kù),本文主要介紹了MyBatis-Flex實(shí)現(xiàn)多表聯(lián)查(自動(dòng)映射),具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06springboot集成nacos報(bào)錯(cuò):get data from Nacos
這篇文章給大家介紹了springboot集成nacos報(bào)錯(cuò):get data from Nacos error,dataId:null.yaml的原因及解決方法,如果又遇到相同問(wèn)題的朋友可以參考閱讀本文2023-10-10解決springboot啟動(dòng)Logback報(bào)錯(cuò)ERROR in ch.qos.logback.cla
這篇文章主要介紹了解決springboot啟動(dòng)Logback報(bào)錯(cuò)ERROR in ch.qos.logback.classic.joran.action.ContextNameAction - Failed to rena問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04Java實(shí)現(xiàn)學(xué)生管理系統(tǒng)詳解流程
這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言實(shí)現(xiàn)學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06Spring Security OAuth2 實(shí)現(xiàn)登錄互踢的示例代碼
這篇文章主要介紹了Spring Security OAuth2實(shí)現(xiàn)登錄互踢的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04