海康威視rtsp轉rtmp(java穩定版)

1、測試的目標

將海康威視攝像頭產生的rtsp視頻流,通過java代碼轉換後,以rtmp的形式推送到nginx服務器,實現遠程訪問。推流程序需要和設備在同一個局域網下(否則獲取不到視頻流),nginx可以在本地服務器,也可以是雲服務器。

2、工具和環境

eclipse、maven、jdk1.8、javacv-1.5.1、nginx1.17.1、VLC media player、iVMS-4200客戶端

3、相關說明

(1)不同版本的javacv的包,有些類的位置有不同,下面是我用的包的maven地址

		<dependency>
		    <groupId>org.bytedeco</groupId>
		    <artifactId>javacv-platform</artifactId>
		    <version>1.5.1</version>
		</dependency>

(2)iVMS-4200客戶端是用來設置攝像頭IP的,設備的賬號密碼等信息,由設備廠家提供,攝像頭的rtsp地址:

rtsp://{username}:{password}@{ip}/h264/1/main/av_stream

(3)nginx在window上部署可以直接下載到包含rtmp的包,linux上需要下載插件包自行編譯,需要的可以給我留言

(4)VLC media player是用來預覽rtmp視頻流的,也可以用web頁面訪問,參考代碼(ezuikit.js官方demo中有):

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta charset="UTF-8">
</head>
<script src="jquery-1.11.3.min.js"></script>
<script src="ezuikit.js"></script>
<script>
$(function () {
	var player08 = new EZUIPlayer('myPlayer08');
	player08.play();
})
</script>

<body>
	<div style="border:1px solid red">
		<div>
		  <video id="myPlayer08" controls playsInline webkit-playsinline width="800" height="600">
		    <source src="rtmp://{ip}:{port}/{name}" type="rtmp/flv" />
		  </video>
		</div>
	</div>
</body>

<style>
div{
	display:inline-block;
	padding:0;
	margin:0;
}
</style>
</html>

4、Java代碼

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

public class TestClass {
    public static void main(String[] args) throws Exception{
    	final int captureWidth = 1280;
        final int captureHeight = 720;
        final FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("{rtspUrl}");
        grabber.setImageWidth(captureWidth);
        grabber.setImageHeight(captureHeight);
        // rtsp格式一定要添加這個參數,否則丟幀會比較嚴重
        grabber.setOption("rtsp_transport", "tcp");
        grabber.start();
        // 最後一個參數是AudioChannels,建議通過grabber獲取
        final FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("{rtmpUrl}", captureWidth, captureHeight, 1);
        recorder.setInterleaved(true);
        // 降低編碼延時
        recorder.setVideoOption("tune", "zerolatency");
        // 提升編碼速度
        recorder.setVideoOption("preset", "ultrafast");
        // 視頻質量參數(詳見 https://trac.ffmpeg.org/wiki/Encode/H.264)
        recorder.setVideoOption("crf", "28");
        // 分辨率
        recorder.setVideoBitrate(2000000);
        // 視頻編碼格式
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        // 視頻格式
        recorder.setFormat("flv");
        // 視頻幀率
        recorder.setFrameRate(15);
        recorder.setGopSize(60);
        recorder.setAudioOption("crf", "0");
        recorder.setAudioQuality(0);
        recorder.setAudioBitrate(192000);
        recorder.setSampleRate(44100);
        // 建議從grabber獲取AudioChannels
        recorder.setAudioChannels(1);
        recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
        recorder.start();
        // 用來測試的frame窗口
        final CanvasFrame cFrame = new CanvasFrame("frame");
        Frame capturedFrame = null;
        while ((capturedFrame = grabber.grab()) != null) {
        	if (cFrame.isVisible()){
        		cFrame.showImage(capturedFrame);
        	}
        	System.out.println(grabber.getFrameNumber()+ "--" +capturedFrame.timestamp);
        	recorder.setTimestamp(capturedFrame.timestamp);
        	recorder.record(capturedFrame);
        }
		cFrame.dispose();
		recorder.close();
		grabber.close();
    }
}

5、補充

(1)recorder的參數,有些需要根據設備和實際需求變化一下

(2)之前多次測試 recorder.setTimestamp(capturedFrame.timestamp); 這個地方的參數都使用了recorder.setTimestamp(grabber.getTimestamp()),但是執行一段時間之後就會報 -10054的錯誤,後來改成這個之後,比較穩定了

(3)爲了偷懶,這裏直接將異常拋出了,所以有時候程序出錯,也沒有退出,實際使用中需進行修改

(4)如果有什麼建議或者問題,可以給我留言

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章