一、所需文件

1.1ffmpeg:核心文件,用于负责转换视频流;

1.2Nginx:代理服务器,用于将转换后的视频流转发到其他地址。

1.3vlc播放器:播放器/转换器,用于在测试时将mp4视频文件转换成rtsp流。

1.4Video相关CSS、JS:用于在浏览器端播放。

二、相关文件下载

2.1ffmpeg下载:

ffmpeg地址:Download FFmpeg

2.1.1Linux系统

2.1.2Windows系统

2.1.3MAC系统(略)

2.2Nginx

rtmp转换流使用到的Nginx与之前的Nginx是有区别,下载地址:GitHub - illuspas/nginx-rtmp-win32: Nginx-rtmp-module Windows builds.或者使用自己的nginx-1.8.1(推荐)。

注意Nginx所在目录不要有中文!

2.3vlc播放器

2.4Video相关CSS、JS

三、配置

3.1ffmpeg:无改变,解压后存放的目录不要有中文!

3.2rtmp使用到的Nginx:

可能集成了 Rtmp、openssl、pcre、zlib,具体还没看,主要是拿来使用。

nginx.conf里的配置:

worker_processes  1;

error_log  logs/error.log debug;

events {
    worker_connections  1024;
}

rtmp {
    server {
        listen 1935;

        application live {
            live on;
        }
		
        application hls {
            live on;
            hls on;  
            hls_path temp/hls;  
            hls_fragment 8s;  
        }
    }
}

3.3vlc播放器:

3.4Video相关CSS、JS:

参考2.4Video相关CSS、JS的链接里的代码,里面的视频地址是rtmp流。

四:使用【CMD命令行】

4.1开启Nginx服务;

4.2使用VLC转换MP4视频为rtsp流;

4.3在CMD命令窗口执行,使用ffmpeg.exe将rtsp视频转为rtmp流:

ffmpeg -i rtsp://192.168.1.121:8554/test -vcodec copy -acodec copy -f flv rtmp://127.0.0.1:1935/live/play1

注意

1、rtsp://192.168.1.121:8554/test

这是VLC播放器转换后的rtsp流地址。

2、rtmp://127.0.0.1:1935/live/play1

①端口要与Nginx的监听的rtmp端口一致。

②端口后面的live是必须要与Nginx里监听的一致,如下图:

③live后面的地址任意,每一个地址代表一个rmtp流,即一个视频。

五:使用【Java核心代码】

5.1启动Nginx、停止Nginx

    /**
     * 启动Nginx、停止Nginx
     */
    public static void startNginx(){
        if(!StringUtils.isEmpty(Nginx)){
            return;
        }
        //启动nginx
        String nginxStart = "cmd /c cd E:\\Others\\VideoConvertTest\\nginx-1.8.1 && start nginx";
        //关闭nginx
        String nginxStop ="cmd /c cd E:\\Others\\VideoConvertTest\\nginx-1.8.1 && nginx.exe -s stop";
        Runtime run = Runtime.getRuntime();
        Nginx = "startNginx";
        try {
            Process stop = run.exec(nginxStop);
            Process start = run.exec(nginxStart);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

5.2rtsp转为rtmp

    /**
     * rtsp转为rtmp
     * @param videoPort
     * @param videoName
     * @return
     */
    public static void convert(String videoPort,String videoName){
        String videoId = videoPort + videoName;
        if(rtspList.contains(videoId)){
            return;
        }
        rtspList.add(videoId);
//        String convertVideo = "cmd /c start E:\\Others\\VideoConvertTest\\ffmpeg\\bin\\ffmpeg.exe -i \"rtsp://192.168.1.121:" + videoPort + "/test\" -vcodec copy -acodec copy -f flv \"rtmp://127.0.0.1:1935/live/" + videoName + "\"";
        String convertVideo = "cmd /c start E:\\Others\\VideoConvertTest\\ffmpeg2020\\bin\\ffmpeg.exe -i \"rtsp://192.168.1.121:" + videoPort + "/test\" -vcodec copy -acodec copy -f flv \"rtmp://127.0.0.1:1935/live/" + videoName + "\"";
        String line = null;
        StringBuilder sb = new StringBuilder();
        Runtime runtime = Runtime.getRuntime();

        try {
            Process process = runtime.exec(convertVideo);
//            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
//            while((line = bufferedReader.readLine()) != null) {
//                sb.append(line + "\n");
//                System.out.println("line------" + line);
//                process.destroy();
//            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

5.3完整代码

package video.player.utils;

import org.thymeleaf.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class RtspToRtmpUtil {

    /**
     * 记录Nginx是否已启动
     */
    public static String Nginx = "";

    /**
     * 记录rtsp流是否已启动转换
     */
    public static List<String> rtspList = new ArrayList<>();

    /**
     * 启动Nginx、停止Nginx
     */
    public static void startNginx(){
        if(!StringUtils.isEmpty(Nginx)){
            return;
        }
        //启动nginx
        String nginxStart = "cmd /c cd E:\\Others\\VideoConvertTest\\nginx-1.8.1 && start nginx";
        //关闭nginx
        String nginxStop ="cmd /c cd E:\\Others\\VideoConvertTest\\nginx-1.8.1 && nginx.exe -s stop";
        Runtime run = Runtime.getRuntime();
        Nginx = "startNginx";
        try {
            Process stop = run.exec(nginxStop);
            Process start = run.exec(nginxStart);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * rtsp转为rtmp
     * @param videoPort
     * @param videoName
     * @return
     */
    public static void convert(String videoPort,String videoName){
        String videoId = videoPort + videoName;
        if(rtspList.contains(videoId)){
            return;
        }
        rtspList.add(videoId);
//        String convertVideo = "cmd /c start E:\\Others\\VideoConvertTest\\ffmpeg\\bin\\ffmpeg.exe -i \"rtsp://192.168.1.121:" + videoPort + "/test\" -vcodec copy -acodec copy -f flv \"rtmp://127.0.0.1:1935/live/" + videoName + "\"";
        String convertVideo = "cmd /c start E:\\Others\\VideoConvertTest\\ffmpeg2020\\bin\\ffmpeg.exe -i \"rtsp://192.168.1.121:" + videoPort + "/test\" -vcodec copy -acodec copy -f flv \"rtmp://127.0.0.1:1935/live/" + videoName + "\"";
        String line = null;
        StringBuilder sb = new StringBuilder();
        Runtime runtime = Runtime.getRuntime();

        try {
            Process process = runtime.exec(convertVideo);
//            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
//            while((line = bufferedReader.readLine()) != null) {
//                sb.append(line + "\n");
//                System.out.println("line------" + line);
//                process.destroy();
//            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

}

5.4 需要异步开启转换,所以要用到多线程

    @GetMapping("/convert")
    @ResponseBody
    public String convert(@RequestParam(value = "videoPort") String videoPort, @RequestParam(value = "videoName") String videoName){
        //启动新的线程
        new Thread() {
            public void run() {
                RtspToRtmpUtil.startNginx();
                RtspToRtmpUtil.convert(videoPort, videoName);
            }
        }.start();
        return "rtmp://127.0.0.1:1935/live/" + videoName + "/";
    }

完整代码:

package video.player.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import video.player.utils.RtspToRtmpUtil;

@Controller
public class VideoPlayerController {

    @GetMapping("/player")
    public String player(){
        return "video/player.html";
    }

    @GetMapping("/rtmp")
    public String rtmp(){
        return "video/rtmp.html";
    }

    @GetMapping("/rtmp2")
    public String rtmp2(){
        return "video/rtmp2.html";
    }

    @GetMapping("/convert")
    @ResponseBody
    public String convert(@RequestParam(value = "videoPort") String videoPort, @RequestParam(value = "videoName") String videoName){
        //启动新的线程
        new Thread() {
            public void run() {
                RtspToRtmpUtil.startNginx();
                RtspToRtmpUtil.convert(videoPort, videoName);
            }
        }.start();
        return "rtmp://127.0.0.1:1935/live/" + videoName + "/";
    }

}
六、其他

6.1其他参考地址

6.2完整代码及工具包地址:https://gitee.com/XiMuQi/RtspToRtmp

​​​​​​​