java+vue推rtsp流实现视频播放(由javacv+ffmpg转为vlcj)

发布时间:2026/7/31 18:53:38

java+vue推rtsp流实现视频播放(由javacv+ffmpg转为vlcj) 一、vlcjvlcj是一个强大的Java框架专为VLC媒体播放器设计让开发者能够轻松地在Java应用中集成专业的媒体播放功能。无论是构建简单的音频播放器还是复杂的视频处理应用vlcj都提供了丰富的API和工具帮助你快速实现各种媒体播放需求二、为什么替换掉javacvffmpeg1、起因开发过程中的需求需要调用海康isc平台海康硬盘录像机、宇视平台、宇视硬盘录像机的接口获取其返回的rtsp流地址然后在播放出来这个回放流。2、难点查阅资料后发现需要本地搭建一个流媒体服务器然后给流媒体暴露出一个端口通过websocketrtsp播放地址实现画面播放但是整理的各种流媒体播放类以及接口比较多需要安装ffmpeg环境依赖服务搭建完成后发现本地确实可以运行但是放到线上后因为现场环境和本地环境差异效果很差有很多流播放不了。而且还需要适配各种因播放流格式为h264,或h265转换如果分辨率不同还是需要再次适配不同的分辨率比较繁琐现场也因为环境问题不能升级ffmpeg所以还是只能用ffmpeg4.x的版本bug还是比较多的。然后才想换一种方式三、实现步骤1、引入vlcj和jna依赖dependency groupIduk.co.caprica/groupId artifactIdvlcj/artifactId version3.12.1/version /dependency dependency groupIdnet.java.dev.jna/groupId artifactIdjna/artifactId version5.12.1/version /dependency注意使用vlcj依赖为3.x的版本对应服务器安装的vlc也要是3.x的版本2、安装vlc2.1 windows安装官网地址进入下载如下页面点击下载安装即可像安装普通软件一样2.2Linux下载如果是有桌面操作系统那么就和windows无异如果是无桌面版本需要执行命令以Ubuntu为例sudo apt update sudo apt install vlc vlc-plugin-base vlc-plugin-video-output libvlc-dev -y安装完成输入命令查看版本vlc --version如图就是安装好了注意如果是root用户因为vlc权限问题是执行不了的建议不要用root用户3、代码集成3.1创建VlcjRtspServicepackage com.ruoyi.web.controller.util; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import uk.co.caprica.vlcj.discovery.NativeDiscovery; import uk.co.caprica.vlcj.player.MediaPlayerFactory; import uk.co.caprica.vlcj.player.headless.HeadlessMediaPlayer; import javax.annotation.PreDestroy; import java.util.concurrent.ConcurrentHashMap; Slf4j Component public class VlcjRtspService { static { // 自动发现 VLC 安装路径 //new NativeDiscovery().discover(); // 可选手动指定 VLC 路径如果自动发现失败 System.setProperty(jna.library.path, C:\\Program Files\\VideoLAN\\VLC); //System.setProperty(jna.library.path, /usr/lib64/vlc); } private final ConcurrentHashMapString, HeadlessMediaPlayer activePlayers new ConcurrentHashMap(); private final ConcurrentHashMapString, MediaPlayerFactory activeFactories new ConcurrentHashMap(); /** * 启动 RTSP 推流 */ public boolean startStream(String streamId, String rtspUrl, int flvPort, String flvPath) { if (activePlayers.containsKey(streamId)) { log.warn(流 {} 已在运行, streamId); return false; } try { // 3.x 版本直接 new MediaPlayerFactory() MediaPlayerFactory factory new MediaPlayerFactory(); activeFactories.put(streamId, factory); // 3.x 版本直接 newHeadlessMediaPlayer() HeadlessMediaPlayer mediaPlayer factory.newHeadlessMediaPlayer(); activePlayers.put(streamId, mediaPlayer); // 转推选项添加 keyint25, bframes0 强制 I 帧间隔和禁用 B 帧 String sout String.format( :sout#transcode{vcodech264,acodecnone,noaudio,keyint25,bframes0}:http{muxflv,dst0.0.0.0:%d%s}, flvPort, flvPath ); // 播放选项 String[] options { --live-caching0, --network-caching300, --clock-synchro0, --no-audio, --vout, dummy, --demuxffmpeg, --codecavcodec, --avcodec-threads2, --avcodec-hwnone, --input-repeat65535, --rtsp-tcp, --rtsp-timeout30, --sout-keep, --sout-mux-caching10000, // 增加缓存 --fflagsgenpts, // 强制生成 PTS --use-wallclock-as-timestamps, // 使用系统时间作为时间戳 --no-clock, // 禁用内部时钟同步 --verbose2, sout }; log.info(启动 VLCJ 推流: {} - http://10.30.127.93:{}{}, rtspUrl, flvPort, flvPath); // 3.x 版本playMedia 方法签名 mediaPlayer.playMedia(rtspUrl, options); // 等待启动 Thread.sleep(2000); if (!mediaPlayer.isPlaying()) { log.error(推流启动失败: {}, streamId); stopStream(streamId); return false; } log.info(推流启动成功: {}, streamId); return true; } catch (Exception e) { log.error(启动推流失败: {}, e.getMessage(), e); stopStream(streamId); return false; } } public void stopStream(String streamId) { HeadlessMediaPlayer player activePlayers.remove(streamId); MediaPlayerFactory factory activeFactories.remove(streamId); if (player ! null) { player.stop(); player.release(); log.info(停止推流: {}, streamId); } if (factory ! null) { factory.release(); } } PreDestroy public void destroy() { for (String streamId : activePlayers.keySet()) { stopStream(streamId); } } }可以直接复制粘贴使用注意下图这个是vlc安装路径所在我的是国产统信息UOS操作系统所以和Ubuntu存在地址还是不太一样输入命令查看安装所在地址whereis vlc输入这个地址就行了3.2调用方法GetMapping(getVlcFlv) public AjaxResult getVlcFlv(String rtspUrl) { // 生成唯一流ID String streamId UUID.randomUUID().toString().replace(-, ); //String flvPath / streamId .flv; String flvPath /1.flv; int flvPort 8088; // 从配置读取 //String rtspUrl rtsp://admin:abcd1234192.168.10.xx:554/Streaming/Channels/101; // 启动 VLCJ 拉流 boolean started vlcjRtspService.startStream(1, rtspUrl, flvPort, flvPath); if (!started) { return AjaxResult.error(启动回放流失败); } // 返回 HTTP-FLV 地址 String flvUrl http://localhost: flvPort flvPath; return AjaxResult.success(flvUrl); }我写了一个测试方法直接传入rtsp地址然后可以推流就行了。使用uuid做流地址的一部分是因为摄像仪可能比较多流也比较多用来做区分停止推流的时候制醋要传入已经推来流的uuid就行了例如GetMapping(stopVlcFlv) public AjaxResult stopVlcFlv(String streamId) { // 停止 VLCJ 拉流 vlcjRtspService.stopStream(streamId); return AjaxResult.success(停止回放流成功); }3.3前端页面我这写了一个简单的html页面如果能打开视频就是播放成功了,可以直接复制测试!DOCTYPE html html head meta charsetUTF-8 titleFLV测试/title script srchttps://cdn.bootcdn.net/ajax/libs/flv.js/1.6.2/flv.min.js/script /head body video idvideo controls autoplay stylewidth: 800px;/video script const url http://192.168.10.x/flv/1.flv; if (flvjs.isSupported()) { const player flvjs.createPlayer({ type: flv, url: url }); player.attachMediaElement(document.getElementById(video)); player.load(); player.play(); } else { alert(浏览器不支持flv.js); } /script /body /html四注意项1、跨域如上所述我后端开了一个端口为8088然后用前端html页面测试发现有跨域问题会播放失败例如错误提示3.html:1 Access to fetch at http://10.30.127.93:8088/1.flv from origin null has been blocked by CORS policy: No Access-Control-Allow-Origin header is present on the requested resource. If an opaque response serves your needs, set the requests mode to no-cors to fetch the resource with CORS disabled.2、解决方案使用nginx代理修改nginx配置文件添加以下选项location /flv/ { proxy_pass http://192.168.10.x:8088/; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Credentials true; }所以我在html测试页面才写url http://192.168.10.x/flv/1.flv五、效果点击开始播放后端开始推流推流成功看到画面隐私问题我故意打的马赛克停止推流

相关新闻