溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

使用javaCV怎么實現(xiàn)一個推流器和錄制器

發(fā)布時間:2021-05-08 16:27:56 來源:億速云 閱讀:556 作者:Leah 欄目:開發(fā)技術(shù)

這篇文章給大家介紹使用javaCV怎么實現(xiàn)一個推流器和錄制器,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

功能

實現(xiàn)邊播放邊錄制/推流,停止預(yù)覽即停止錄制/推流

開發(fā)所依賴的包

javacv.jar,javacpp.jar,ffmpeg.jar,ffmpeg-系統(tǒng)平臺.jar,opencv.jar,opencv-系統(tǒng)平臺.jar。

其中ffmpeg-系統(tǒng)平臺.jar,opencv-系統(tǒng)平臺.jar中的系統(tǒng)平臺根據(jù)開發(fā)環(huán)境或者測試部署環(huán)境自行更改為對應(yīng)的jar包,比如windows7 64位系統(tǒng)替換為ffmpeg-x86-x64.jar

為什么要這樣做:因為ffmpeg-系統(tǒng)平臺.jar中存放的是c/c++本地so/dll庫,而ffmpeg.jar就是使用javacpp封裝的對應(yīng)本地庫java接口的實現(xiàn),而javacpp就是基于jni的一個功能性封裝包,方便實現(xiàn)jni,javacv.jar就是對9個視覺庫進(jìn)行了二次封裝,但是實現(xiàn)的功能有限,所以建議新手先熟悉openCV和ffmpeg這兩個C/C++庫的API后再來看javaCV思路就會很清晰了。

代碼實現(xiàn)

本功能采用按幀錄制/推流,通過關(guān)閉播放窗口停止視頻錄制/推流。

注:本章代碼中的opencv轉(zhuǎn)換器是未來方便演示如何獲取圖片,長時間運(yùn)行該代碼會導(dǎo)致內(nèi)存溢出的原因是沒有及時釋放IplImage資源,所以大家推流時應(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抓取器方式獲取攝像頭請參考第一章,F(xiàn)rameGrabber會自己去找可以打開的攝像頭的抓取器。
	FrameGrabber grabber = FrameGrabber.createDefault(0);//本機(jī)攝像頭默認(rèn)0
	grabber.start();//開啟抓取器

	OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();//轉(zhuǎn)換器
	IplImage grabbedImage = converter.convert(grabber.grab());//抓取一幀視頻并將其轉(zhuǎn)換為圖像,至于用這個圖像用來做什么?加水印,人臉識別等等自行添加
	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);//不知道為什么這里不做轉(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)閉抓取器

}

總的來說,我們已經(jīng)實現(xiàn)了基本的推流器功能

測試錄制功能和推流功能

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);
}

關(guān)于使用javaCV怎么實現(xiàn)一個推流器和錄制器就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI