首先,说一下ffmpeg实现rtsp转rtmp需要的条件:
(1)ffmpeg包:https://github.com/xueying123-cat/ffmpeg
(2)nginx-rtmp:https://github.com/xueying123-cat/nginx-rtmp.git
(3)转码服务,https://github.com/xueying123-cat/camera.git,这个代码对于多个转流同时执行可能存在线程不能正常结束的问题,大家有好的建议可以留言赐教
思路:转码服务将SVR中的rtsp流通过ffmpeg包转化为rtmp包,然后nginx-rtmp支持rtmp流播放。
ffmpeg转流命令:
ffmpeg -re -rtsp_transport tcp -i "rtsp://username:password@serverIp/id=chnid" -f flv -vcodec copy -acodec copy -f flv -s 1280x720 -q 10 "rtmp://nginx_rtmp_ip:nginx_rtmp_ip/live/test"
nginx-rtmp的nginx-conf配置:
worker_processes 1;
error_log logs/error.log info;
events {
worker_connections 1024;
}
rtmp {
server {
listen 1935;
chunk_size 4096; #//数据传输块的大小
application live {
live on;
}
application vod {
play D:\lib; #//视频文件存放位置。
}
application hls {
live on;
hls on;
hls_path D:\lib;
hls_fragment 8s;
}
}
}
http {
server {
listen 8083;
···
}
}
现在说一下转码服务如何实现将rtsp流转化为rtmp流
//(1)获取当前转流命令,配置在常量类里
String command = ffmpegCommand.RTSP_TO_RTMP.getValue()
.replace("rtspUrl", rtsp)
.replace("rtmpUrl", rtmp);
//(2)执行cmd转流命令
Runtime.getRuntime().exec(commond)
//(3)将当前转流功能线程里执行,维护当前转流功能不被其他请求打扰
private static ThreadLocal<BufferedReader> br = ThreadLocal.<BufferedReader>withInitial(() -> null);
private static ThreadLocal<String> threadId = ThreadLocal.<String>withInitial(() -> null); //定义线程内变量
private static ThreadLocal<Boolean> cameraStatus = ThreadLocal.<Boolean>withInitial(() -> false);
//在本机创建一个进程
Process process = Runtime.getRuntime().exec(command);
new Thread(() -> {
cameraStatus.set(true);
InputStream is = process.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
br.set(reader);
threadId.set(id);
while (cameraStatus.get()) {
//对流操作
···
if (Thread.currentThread().isInterrupted()) {
cameraStatus.set(false);
closeResources(is, reader);
}
}
}
//(4)结束转流时,中断线程,并向当前线程中发送ffmpeg的停止命令q指令终止process的进程,停止当前线程
thread.interrupt();
OutputStream out = process.getOutputStream();
Writer w = new OutputStreamWriter(out);
try {
w.write("q");
w.flush();
} catch (IOException e) {
throw new CameraException("IOException==stop=>", e.getMessage());
} finally {
try {
if (w != null) {
w.close();
}
} catch (IOException e) {
throw new CameraException("IOException==closew=>", e.getMessage());
}
}
测试结果:
图像:
写的比较粗糙,如果哪里有不明白,欢迎留言