海康威视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地址


    org.bytedeco
    javacv-platform
    1.5.1

(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中有):




	






	

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格式一般添加TCP配置,否则丢帧会比较严重
        // Brick在测试过程发现,该参数改成udp可以解决部分电脑出现的下列报警,但是丢帧比较严重
        // av_interleaved_write_frame() error -22 while writing interleaved video packet.
        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();

        // 解决音视频同步导致的延时问题
        Field field = recorder.getClass().getDeclaredField("oc");
        field.setAccessible(true);
        AVFormatContext oc = (AVFormatContext)field.get(recorder);
        oc.max_interleave_delta(100);

        // 用来测试的frame窗口
        final CanvasFrame cFrame = new CanvasFrame("frame");
        Frame capturedFrame = null;

        // 有些时候,程序执行回报下列错误,添加一行代码解决此问题
        // av_interleaved_write_frame() error -22 while writing interleaved video packet.
        grabber.flush();
        
        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、rtsp视频流地址(地址正确可以在vlc中播放)

    rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream

    username: 用户名;password: 密码;ip: 设备IP;port:设备端口,默认554时可略; codec:h264等;channel: 通道号;

    subtype: 码流类型,主码流为main,辅码流为sub

    例(DS-IPC-E22H-1W型) rtsp://admin:[email protected]/h264/1/main/av_stream

    补充:地址也可以是rtsp://[username]:[password]@[ip]:[port]/live.sdp

    例(DS-IPC-E22H-1W型) rtsp://admin:[email protected]/live.sdp

6、rtmp视频流地址(地址正确可以在vlc中播放)

    rtmp://[ip]:[port]/[rtmp-addr]/[camera-name]

    ip: nginx服务器IP;port:nginx的rtmp端口;rtmp-addr:配置的rtmp地址;camera-name:推流摄像头地址名称

    例 rtmp://192.168.100.10:1935/hls/test01

7、附上测试时候用的nginx的配置文件

worker_processes  1;

error_log  logs/error.log  notice;

events {
    worker_connections  1024;
}

rtmp {  
    server {
        listen 8012;
        application myapp {
            live on;  
       }  
        application hls {  
            live on;  
            hls on;  
            hls_path /usr/local/nginx/temp/hls;   
            hls_fragment 1s;
            hls_playlist_length 3s;  
       }  
    } 
}

http {
    server {
        listen 8011;
        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
		location /hls {
			types {
				application/vnd.apple.mpegurl m3u8;
				video/mp2t ts;
			}
			alias /usr/local/nginx/temp/hls;
			expires -1;
		}
	}
}

8、补充

(1)recorder的参数,有些需要根据设备和实际需求变化一下

(2)使用recorder.setTimestamp(grabber.getTimestamp())执行一段时间之后就会报 -10054的错误

(3)实际使用中要关闭grabber和recorder,先使用release,再使用close,否则会导致服务停止

(4)最终测试结果:使用vlc播放有5-8s延时,使用web播放延时仅为1s左右

(5)如果有什么建议或者问题,可以给我留言(微信yl4757)

你可能感兴趣的:(海康威视rtsp转rtmp(java稳定版))