1. 安装ffmpeg
linux系统直接运行命令
ubuntu:
sudo apt install ffmpeg
centos:
sudo yum install ffmpeg
windows系统下载包+配置环境变量
https://github.com/BtbN/FFmpeg-Builds/releaseshttps://github.com/BtbN/FFmpeg-Builds/releases
环境变量配置就在path中加一个你下载下来的包解压后的一直到bin目录的路径地址
2. 配置Nginx
1.1 配置 rtmp
需要与http同级
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
}
}
}
- listen:指定 rtmp 服务监听端口
- chunk_size:设置 rtmp 流的分块大小
- application live:定义一个 rtmp应用程序
- live on:启用实时流媒体功能
- record off:禁用录制功能(如需录制可以设为 record all)
- 这样就可以让 ffmpeg 将 rtsp 转为 rtmp 到 rtmp://your_server_ip/live/stream_key 地址上
1.2 配置hls
添加在http内部
server {
listen 1234;
server_name localhost;
location /hls/ {
alias /home/xxx/hls/;
add_header Cache-Control no-cache;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
}
}
- 使用 ffmpeg 将 rtsp 转为 hls 时需要一个文件夹来存储,这里的 /home/xxx/hls/ 就是你选择用来存储的文件夹
- 下面的 add_header 等,是为了解决前端请求流地址跨域问题的
- 这样前端就可以通过 http://your_server_ip:1234/hls/stream_key.m3u8 来访问流
3. 编写Java代码
import java.io.File;
import java.io.IOException;
public class RTSPConverter {
private Process ffmpegProcess;
private Thread processMonitorThread;
private String ffmpegPath = "ffmpeg";
private String outputDir = "/home/xxx/hls";
public int startRTMPStreaming(String rtspUrl, String rtmpUrl) {
// FFmpeg 命令
String[] command = {
ffmpegPath,
"-i", rtspUrl,
"-c:v", "copy",
"-c:a", "aac",
"-f", "flv",
rtmpUrl
};
return startStreaming(command);
}
public int startHLSStreaming(String rtspUrl) {
// 确保输出目录存在
File outputDirFile = new File(outputDir);
if (!outputDirFile.exists()) {
outputDirFile.mkdirs();
}
// FFmpeg 命令
String[] command = {
ffmpegPath,
"-i", rtspUrl, // 输入 RTSP 流
"-c:v", "copy", // 视频流直接复制
"-c:a", "aac", // 音频流重新编码为 AAC
"-f", "hls", // 输出格式为 HLS
"-hls_time", "10", // 每个 TS 文件的时长(秒)
"-hls_list_size", "6", // HLS 播放列表中保留的 TS 文件数量
"-hls_flags", "delete_segments", // 自动删除旧的 TS 文件
outputDir + "/" + "hlsStream" + ".m3u8"
};
return startStreaming(command);
}
private int startStreaming(String[] command) {
try {
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.inheritIO();
// 启动FFmpeg进程
ffmpegProcess = processBuilder.start();
// 创建监控线程处理进程结束
processMonitorThread = new Thread(() -> {
try {
ffmpegProcess.waitFor();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
processMonitorThread.start();
return 1;
} catch (IOException e) {
e.printStackTrace();
return 0;
}
}
public int stopStreaming() {
if (ffmpegProcess != null && ffmpegProcess.isAlive()) {
// 销毁FFmpeg进程
ffmpegProcess.destroy();
try {
// 等待监控线程结束
if (processMonitorThread != null) {
processMonitorThread.join(5000); // 最多等待5秒
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return 0;
}
}
return 1;
}
}
- startRTMPStreaming:拼装 ffmpeg 将 rtsp 转 rtmp 的命令
- startHLSStreaming:拼装 ffmpeg 将 rtsp 转 rtmp 的命令
- startStreaming:开始运行 ffmpeg 执行命令
- stopStreaming:停止运行 ffmpeg
- 其中 "-c:v", "copy", 如果你要编码为 h.264 则需要将 copy 改为 libx264(下面音频相同)