环境:Linux(Centos 7.5)
实现方案
1、前期准备
按照功能要求,确定使用ffmpeg命令将rtsp转为hls(.m3u8)
ffmpeg命令实例:ffmpeg -i rtsp://用户名:密码@ip:port/Streaming/Channels/1 -c:v libx264 -preset faster -crf 20 -vprofile main -pix_fmt yuv420p -c:a aac -b:a 64k -y -hls_wrap 10 index.m3u8
—更新优化—————————————————————————————————
补充更新:降低ffmpeg命令CPU占用率 1:rtsp 地址使用子码流 2增加线程设置 (-threads 10)
3防止流转换过程中的丢包问题-rtsp_transport tcp
优化ffmpeg 命令:
ffmpeg -rtsp_transport tcp -threads 10 -re -i rtsp://用户名:密码@ip:port/h264/ch1/sub/av_stream(替换“rtsp://用户名:密码@ip:port/Streaming/Channels/1”) -c:v libx264 -preset faster -crf 20 -vprofile main -pix_fmt yuv420p -c:a aac -b:a 64k -y -hls_wrap 10 index.m3u8
——————————————————————————————————————
2、测试工具
选用VLC播放器,可以直接使用hls地址检查输出结果
3、Java部分
①创建springboot项目,并在启动类中开启异步任务
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableAsync //开启异步任务
public class DemoApplication {
@Bean(name="processExecutor")
public TaskExecutor workExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("Async-");
threadPoolTaskExecutor.setCorePoolSize(10);
threadPoolTaskExecutor.setMaxPoolSize(20);
threadPoolTaskExecutor.setQueueCapacity(600);
threadPoolTaskExecutor.afterPropertiesSet();
return threadPoolTaskExecutor;
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
②实现类
@Service
public class AsyncTask {
//获取摄像头地址列表,按照顺序获取摄像头信息
@Value("#{'${video.list:}'.split(',')}")
private List<String> videoList;
@Async("processExecutor")
public void start(int id) {
//根据编号获取摄像头地址
String rtsp = videoList.get(id-1);
//hls输出地址
String url = "/home/html/hls/live/"+id+"/index.m3u8";
ProcessBuilder builder = new ProcessBuilder(); //创建系统进程
List<String> commend = new ArrayList<>();
//拼接ffmpeg执行命令
//ffmpeg -i rtsp://用户名:密码@ip:port/Streaming/Channels/1 -c:v libx264 -preset faster -crf 20 -vprofile main -pix_fmt yuv420p -c:a aac -b:a 64k -y -hls_wrap 10 index.m3u8
commend.add("ffmpeg");
//-rtsp_transport tcp 防止流转换过程中的丢包问题
commend.add("-rtsp_transport");
commend.add("tcp");
commend.add("-re");
commend.add("-i");
commend.add(rtsp);
//格式转换
commend.add("-c:v");
commend.add("libx264");
commend.add("-preset");
commend.add("faster");
commend.add("-crf");
commend.add("20");
commend.add("-vprofile");
commend.add("main");
commend.add("-pix_fmt");
commend.add("yuv420p");
commend.add("-c:a");
commend.add("aac");
commend.add("-b:a");
commend.add("64k");
commend.add("-y");
//设置切片数量 循环覆盖
commend.add("-hls_wrap");
commend.add("10");
commend.add(url);
builder.command(commend);
builder.redirectErrorStream(true);
try {
Process start = builder.start();//启动进程
InputStream inputStream = start.getInputStream();
InputStreamReader gbk = new InputStreamReader(inputStream);
int len = -1;
char[] c = new char[1024];
StringBuffer outputString = new StringBuffer();
//读取进程输入流中的内容
while ((len = gbk.read(c)) != -1) {
String ss = new String(c, 0, len);
outputString.append(ss);
System.out.print(ss);
}
/*int exitVal = start.waitFor();*/
gbk.close();
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
③异步任务调用
@RestController
public class VideoController implements ApplicationRunner {
@Autowired
private AsyncTask asyncTask;
@Override
public void run(ApplicationArguments args) throws Exception {
int id =3;//直播数量
for (int i = 1; i <= id ; i++) {
asyncTask.start(i);
}
}
}
4、服务器部分
(1)ffmpeg安装
选择已经编译好的Ffmpeg,已编译好的ffmpeg包含大部分编译库、编解码库,且免安装。
下载并解压tar -xvJf ffmpeg-4.2.1-amd64-static.tar.xz
解压后将目录下的可执行文件移动到/usr/local/bin/ 里, 这样不用每次都写完整路径
把当前目录下的ffmpeg 、ffprobe、qt-faststart移动到/usr/local/bin/
mv ffmpeg /usr/local/bin/
此时执行ffmpeg可以查询ffmpeg的基本信息,也可以使用ffmpeg命令进行视频流转换。
下载地址:https://www.johnvansickle.com/ffmpeg/old-releases/
(2)nginx安装
修改配置,在nginx\conf\nginx.conf下。
①vi nginx\conf\nginx.conf增加以下配置:
新增hls流协议:
location /hls {
types{
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root html;
add_header Cache-Control no-cache;
add_header Access-Control-Allow-Origin *;
}
②重启nginx
检查nginx配置是否正确
/usr/local/nginx/sbin/nginx -t
进入nginx可执行目录sbin下,输入命令./nginx -s reload
/usr/local/nginx/sbin/nginx -s reload
配置完成后前端可以通过http://172.20.1.41:57002/hls/1/index.m3u8
播放视频
5、问题汇总
(1)ffmpeg版本选择:根据运行环境选择合适的版本,请优先选择已经编译好的ffmpeg,可以不用自行编译,避免缺少编译库,否则会影响ffmpeg命令的参数使用以及最终运行结果(视频无法播放)。
(2)多视频流的直播无法同时进行,请检查运行环境,选择合适的系统硬件支持。
6、扩展
(1)Ffmpeg卸载
卸载除了删除解压目录还要删除编译过后生成的,
执行whereis ffmpeg
找到生成的路径删除相关的文件
(2)Vlc播放器使用
播放器安装之后,从左上角“媒体”→“打开网络串流”→“网络”,输入
http://172.20.1.41:57002/hls/6/index.m3u8
即可查看直播内容。
参考链接:
参考方案:https://blog.csdn.net/weixin_45848110/article/details/119363602?spm=1001.2014.3001.5501
海康rtsp地址格式:https://blog.csdn.net/haovin/article/details/90649038