package com.objecteye.utils; import org.springframework.stereotype.Component; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.concurrent.ConcurrentHashMap; /** * @author 作者 * @version 创建时间:2018年11月14日 下午5:21:18 类说明 */ @Component public class PreviewUtils { /* * rtsp转rtmp指令 */ public static String ffmpegTnstructions; /** * 存放所有rtmp流对应的process进程 key为rtmp流 value为转流进程 */ private static ConcurrentHashMap rtmpAndprocessMaps = new ConcurrentHashMap<>(); /** * 存放用户对应的rtmp流 key为用户名 value为rtmp流 */ private static ConcurrentHashMap userAndrtmpMaps = new ConcurrentHashMap<>(); /** * rtsp转rtmp 得到rtmp流 */ public static String RtspToRtmp(String serverIp, String rtsp, Integer deviceId, String equipmentUserName, String equipmentPassWord, String equipmentIp, String port) throws InterruptedException { // 转流成功的rtmp流地址 String rtmpStr = "rtmp://" + serverIp + ":1935/hls/" + deviceId; boolean rtmpStrIsVaild = true; try { // 先判断rtmp流是否存在 存在拿来直接用 不需要转流 if (rtmpAndprocessMaps.containsKey(rtmpStr)) { // 一个用户只能保存一个rtmp流 /*if (userAndrtmpMaps.containsKey(userName)) { userAndrtmpMaps.remove(userName); } userAndrtmpMaps.put(userName, rtmpStr);*/ } else { Process process = null; if (rtsp.contains("rtsp")) { ffmpegTnstructions = "ffmpeg -re -stream_loop -1 -rtsp_transport tcp -i " + rtsp + " -vcodec copy -acodec copy -f flv -r 15 -s 1280x720 -an -y " + rtmpStr; } else { ffmpegTnstructions = "ffmpeg -re -stream_loop -1 -rtsp_transport tcp -i rtsp://" + equipmentUserName + ":" + equipmentPassWord + "@" + equipmentIp + ":" + port + "/h264/ch1/main/av_stream -vcodec copy -acodec copy -f flv -r 15 -s 1280x720 -an -y rtmp://" + serverIp + ":1935/hls/" + deviceId; } //System.out.println("运行代码:"+ffmpegTnstructions); try { process = Runtime.getRuntime().exec(ffmpegTnstructions); rtmpAndprocessMaps.put(rtmpStr, process); //userAndrtmpMaps.put(userName, rtmpStr); ManageProcess(process); Thread.sleep(100); rtmpStrIsVaild = process.isAlive(); //System.out.println("转流进程是否在运行:" + rtmpStrIsVaild); } catch (IOException e) { e.printStackTrace(); } } // 将没有用户在调用的线程 关闭 /*for (String rtmpString : rtmpAndprocessMaps.keySet()) { if (!userAndrtmpMaps.containsValue(rtmpString)) { System.out.println("当前转流进程未使用,停止rtsp转rtmp"); Process detroyPro = rtmpAndprocessMaps.get(rtmpString); // 先判断进程是否存在 if (detroyPro.isAlive()) { detroyPro.destroy(); } rtmpAndprocessMaps.remove(rtmpString); } }*/ // 输出当前内存存在的process和rtmp /*for (String rtmpString : rtmpAndprocessMaps.keySet()) { System.out.println( "rtmpAndprocessMaps存在的值key为:" + rtmpString + " value为:" + rtmpAndprocessMaps.get(rtmpString)); }*/ // 输出当前内存存在的user和rtmp流 /*for (String userString : userAndrtmpMaps.keySet()) { System.out.println( "userAndrtmpMaps存在的值key为:" + userString + " value为:" + userAndrtmpMaps.get(userString)); }*/ } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } if (rtmpStrIsVaild) { return rtmpStr; } else { return null; } } /* * 输出缓冲流 ----解决一段时间后实时流卡住的问题 */ public static void ManageProcess(Process proc) throws IOException, InterruptedException { try { new Thread(new Runnable() { public void run() { /// 错误输出 BufferedReader br2 = null; InputStreamReader is2 = null; try { br2 = new BufferedReader(new InputStreamReader(proc.getErrorStream())); StringBuilder buf = new StringBuilder(); // 保存输出结果流 String line2 = null; while ((line2 = br2.readLine()) != null) { buf.append(line2); // 循环等待ffmpeg进程结束 } } catch (Exception e) { e.printStackTrace(); } finally { if (br2 != null) { try { br2.close(); } catch (Exception ex) { } } if (is2 != null) { try { is2.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }).start(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }