PreviewUtils.java 5.74 KB
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<String, Process> rtmpAndprocessMaps = new ConcurrentHashMap<>();
    /**
     * 存放用户对应的rtmp流 key为用户名 value为rtmp流
     */
    private static ConcurrentHashMap<String, String> 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();
        }
    }
}