采用JavaCv + Nginx + maven + Idea + JDK1.8 + VLC播放器
通过java代码的方式实现实时直播 通过获取RTSP协议转码为RTMP协议,通过设置对应的RTMP输出地址为推流地址,
@PostMapping("/v1/trans-Coding")
public Object transCoding(String link, String linkName) throws Exception {
// 读取RTSP视频资源 传入Rtsp连接
final FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(link);
// 设置分辨率宽度
int captureWidth = 1280;
grabber.setImageWidth(captureWidth);
// 设置分辨率高度
int captureHeight = 720;
grabber.setImageHeight(captureHeight);
// rtsp格式一般添加TCP配置,否则丢帧会比较严重
// 该参数改成udp可以解决部分电脑出现的下列报警,但是丢帧比较严重 不采用
// av_interleaved_write_frame() error -22 while writing interleaved video packet.
grabber.setOption("rtsp_transport", "tcp");
grabber.start();
// 流媒体输出地址,最后一个参数是"音频AudioChannels 0:不录制,1:录制",建议通过grabber获取
// 地址格式为 rtmp:rtmp://{ip}:{nginx端口}/{该name为传过来的任意值}
final FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("rtmp://127.0.0.1:8012/hls/"+linkName, captureWidth, captureHeight, grabber.getAudioChannels());
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(grabber.getAudioChannels());
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 (grabber.grab() != null) {
capturedFrame = grabber.grab();
// if (cFrame.isVisible()) {
// 设置图像
// cFrame.showImage(capturedFrame);
// } else {
// 获取每帧的编号 -- 时间戳
System.out.println(grabber.getFrameNumber() + "--" + capturedFrame.timestamp);
recorder.setTimestamp(capturedFrame.timestamp);
recorder.record(capturedFrame);
// }
}
// cFrame.dispose();
recorder.close();
grabber.close();
return CommSuccessNullResp.create();
}
maven地址
<!--javaCV-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.1</version>
</dependency>
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 E:\RTMP\hls; #看这里用了绝对路径 可改为服务器地址 记得要与下面对应
hls_fragment 1s;
hls_playlist_length 3s; #m3u8和ts在hls文件夹下的保存时间
}
}
}
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 { #这个hls和推流命令对应
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
alias E:\RTMP\hls; #还有这里
expires -1;
}
}
}
Nginx下载可在网上搜索 nginx-1.7.11.3-Gryphon该版本进行下载,因为这个版本中自带的有rtmp模块
链接:https://pan.baidu.com/s/1-E8t8uegcL3HFG4IBbJafA
提取码:asdf
启动命令: nginx.exe -c conf\nginx-win-rtmp.conf
rtsp测试地址 : rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov
rtmp地址格式 : rtmp://{本机ip或服务器ip}:{nginx端口}/{为代码中设置的值}
通过上面的rtmp格式可在VLC播放器中查看推流视频信息