springboot+vue+ffmpeg实现视频监控的直播拉流播放

 更新时间:2026年07月08日 08:44:24   作者:每日技术  
想实时看监控画面,别再被RTSP/RTMP卡住了,这套SpringBoot+Vue+FFmpeg方案,轻松将RTSP转HLS或HTTP-FLV,延迟低至1-3秒,点击即得完整项目模板与代码,从FFmpeg命令到前端播放组件一步到位,让你快速实现低延迟视频流播放

浏览器无法直接播放监控摄像头的 RTSP/RTMP 流,标准做法是 Spring Boot 调用服务器端 FFmpeg 将 RTSP 转成 HLS(.m3u8) 或推送 RTMP→HTTP-FLV,再由 Vue 前端用 video.js / flv.js / hls.js 播放。下面给你一套较常用的 RTSP → HLS + Spring Boot 管理 + Vue 播放​ 方案,以及低延迟的 HTTP-FLV 备选方案。

一、整体架构(推荐 HLS 方案)

IPC摄像头(RTSP) 
   → FFmpeg 拉流转 HLS(.m3u8 + .ts 切片) 输出到目录
   → Nginx/Spring Boot 静态资源暴露 http://ip/hls/xxx.m3u8
   → Vue + video.js / hls.js 播放
        ↑
   Spring Boot 用 ProcessBuilder 启停 FFmpeg 进程

生产环境建议用 Nginx 托管 HLS 目录(配 CORS),Spring Boot 只负责启停 FFmpeg 和管理接口。

二、服务端 — Spring Boot 调用 FFmpeg

1. FFmpeg 转 HLS 命令

ffmpeg -rtsp_transport tcp \
  -i "rtsp://admin:password@192.168.1.100:554/Streaming/Channels/101" \
  -c:v libx264 -preset ultrafast -tune zerolatency \
  -c:a aac \
  -f hls \
  -hls_time 2 \
  -hls_list_size 5 \
  -hls_flags delete_segments \
  -hls_segment_filename "/opt/hls/cam1_%03d.ts" \
  /opt/hls/cam1.m3u8

参数说明:

  • -rtsp_transport tcp:比 UDP 稳定,减少花屏
  • -hls_time 2:每片 2 秒,延迟约 4~8 秒
  • delete_segments:自动删旧切片防磁盘爆满

2. Spring Boot 启停 FFmpeg 进程

@Service
@Slf4j
public class FfmpegService {

    private final Map<String, Process> processMap = new ConcurrentHashMap<>();

    public void startStream(String camId, String rtspUrl, String outM3u8) throws IOException {
        if (processMap.containsKey(camId)) return;

        List<String> cmd = Arrays.asList(
                "ffmpeg",
                "-rtsp_transport", "tcp",
                "-i", rtspUrl,
                "-c:v", "libx264", "-preset", "ultrafast", "-tune", "zerolatency",
                "-c:a", "aac",
                "-f", "hls",
                "-hls_time", "2",
                "-hls_list_size", "5",
                "-hls_flags", "delete_segments",
                outM3u8
        );

        ProcessBuilder pb = new ProcessBuilder(cmd);
        pb.redirectErrorStream(true);
        Process process = pb.start();
        processMap.put(camId, process);
        log.info("FFmpeg started for camera: {}", camId);
    }

    public void stopStream(String camId) {
        Process p = processMap.remove(camId);
        if (p != null) {
            p.destroy();
            log.info("FFmpeg stopped for camera: {}", camId);
        }
    }
}

3. Controller 示例

@RestController
@RequestMapping("/api/stream")
public class StreamController {
    @Autowired
    private FfmpegService ffmpegService;

    @PostMapping("/start/{camId}")
    public String start(@PathVariable String camId, @RequestParam String rtsp) throws IOException {
        ffmpegService.startStream(camId, rtsp, "/opt/hls/" + camId + ".m3u8");
        return "started";
    }

    @PostMapping("/stop/{camId}")
    public String stop(@PathVariable String camId) {
        ffmpegService.stopStream(camId);
        return "stopped";
    }
}

4. 静态资源映射(开发测试用)

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/hls/**")
                .addResourceLocations("file:/opt/hls/");
    }
}

正式环境推荐用 Nginx 托管 /opt/hls,加跨域头:

location /hls {
    types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; }
    root /opt/hls;
    add_header Cache-Control no-cache;
    add_header Access-Control-Allow-Origin *;
}

三、前端 — Vue 播放 HLS 流

安装依赖

npm install video.js videojs-contrib-hls

Vue3 组件示例

<template>
  <video ref="videoEl" class="video-js vjs-big-play-centered" style="width:640px"></video>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import videojs from 'video.js'
import 'video.js/dist/video-js.css'
const videoEl = ref(null)
let player = null
onMounted(() => {
  player = videojs(videoEl.value, {
    controls: true,
    autoplay: true,
    preload: 'auto',
    sources: [{
      type: 'application/x-mpegURL',
      src: 'http://你的IP/hls/cam1.m3u8'
    }]
  })
})
onBeforeUnmount(() => {
  player?.dispose()
})
</script>

播放地址即:http://ip/hls/cam1.m3u8

四、低延迟方案 — RTSP→RTMP→HTTP-FLV(可选)

若 HLS 延迟(5~10s)不满足,可用 Nginx + nginx-http-flv-module

  • FFmpeg 把 RTSP 推 RTMP:ffmpeg -rtsp_transport tcp -i rtsp://... -c copy -f flv rtmp://localhost/live/cam1
  • Nginx http-flv 分发:http://ip/live?port=1935&app=live&stream=cam1
  • Vue 用 flv.js​ 播放:if (flvjs.isSupported()) { const player = flvjs.createPlayer({ type: 'flv', url: 'http://ip/live?port=1935&app=live&stream=cam1' }) player.attachMediaElement(document.getElementById('video')) player.load() player.play() }

延迟一般可压到 1~3 秒。

五、常见问题与建议

问题解决思路
播放无画面确认 FFmpeg 已生成 .m3u8 文件;先用 VLC 测试 RTSP 流是否正常
跨域报错Nginx 添加 Access-Control-Allow-Origin * 响应头
磁盘满务必添加 -hls_flags delete_segments 参数,启用切片自动删除
多路并发不要全走 Spring Boot 代理;建议用 Nginx/SRS/ZLMediaKit 做流媒体分发层
超低延迟(<500ms)考虑 WebRTC 方案,搭配 ZLMediaKit 或 webrtc-streamer

六、项目结构

video-stream-demo/
├── backend/
│   └── src/main/java/com/demo/videostream/
│       ├── VideoStreamApplication.java
│       ├── config/WebMvcConfig.java
│       ├── service/FfmpegService.java
│       └── controller/StreamController.java
│   └── pom.xml
└── frontend/
    └── src/
        ├── components/LivePlayer.vue
        ├── App.vue
        └── main.js
    ├── package.json
    └── vite.config.js

七、完整代码

后端 — Spring Boot

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.demo</groupId>
    <artifactId>video-stream-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

VideoStreamApplication.java

package com.demo.videostream;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class VideoStreamApplication {
    public static void main(String[] args) {
        SpringApplication.run(VideoStreamApplication.class, args);
    }
}

FfmpegService.java(核心:ProcessBuilder 启停 FFmpeg)

package com.demo.videostream.service;

import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class FfmpegService {

    private final Map<String, Process> processMap = new ConcurrentHashMap<>();

    public synchronized void start(String camId, String rtspUrl, String outM3u8) throws IOException {
        if (processMap.containsKey(camId)) return;

        ProcessBuilder pb = new ProcessBuilder(
                "ffmpeg",
                "-rtsp_transport", "tcp",
                "-i", rtspUrl,
                "-c:v", "libx264", "-preset", "ultrafast", "-tune", "zerolatency",
                "-c:a", "aac",
                "-f", "hls",
                "-hls_time", "2",
                "-hls_list_size", "5",
                "-hls_flags", "delete_segments",
                outM3u8
        );
        Process p = pb.start();
        processMap.put(camId, p);
    }

    public synchronized void stop(String camId) {
        Process p = processMap.remove(camId);
        if (p != null) p.destroy();
    }
}

StreamController.java

package com.demo.videostream.controller;

import com.demo.videostream.service.FfmpegService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/stream")
@CrossOrigin
public class StreamController {

    @Autowired
    private FfmpegService ffmpegService;

    // POST /api/stream/start/cam1?rtsp=rtsp://admin:123@192.168.1.100:554/Streaming/Channels/101
    @PostMapping("/start/{camId}")
    public String start(@PathVariable String camId, @RequestParam String rtsp) throws Exception {
        ffmpegService.start(camId, rtsp, "/opt/hls/" + camId + ".m3u8");
        return "started -> http://localhost:8080/hls/" + camId + ".m3u8";
    }

    @PostMapping("/stop/{camId}")
    public String stop(@PathVariable String camId) {
        ffmpegService.stop(camId);
        return "stopped";
    }
}

WebMvcConfig.java(静态资源暴露 HLS 目录)

package com.demo.videostream.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/hls/**")
                .addResourceLocations("file:/opt/hls/");
    }
}

服务器需提前建 /opt/hls目录,且安装 ffmpeg 并在 PATH 中。

前端 — Vue3 + video.js

package.json

{
  "name": "frontend",
  "dependencies": {
    "vue": "^3.4.0",
    "video.js": "^7.21.5"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.0.0",
    "vite": "^5.0.0"
  }
}

LivePlayer.vue

<template>
  <video ref="videoEl" class="video-js vjs-big-play-centered" style="width:100%;max-width:720px"></video>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import videojs from 'video.js'
import 'video.js/dist/video-js.css'
const props = defineProps({
  src: { type: String, default: 'http://localhost:8080/hls/cam1.m3u8' }
})
const videoEl = ref(null)
let player = null
onMounted(() => {
  player = videojs(videoEl.value, {
    controls: true,
    autoplay: true,
    preload: 'auto',
    sources: [{ type: 'application/x-mpegURL', src: props.src }]
  })
})
onBeforeUnmount(() => player?.dispose())
</script>

App.vue

<template>
  <div style="padding:20px">
    <h3>监控直播 — HLS 播放</h3>
    <LivePlayer src="http://localhost:8080/hls/cam1.m3u8" />
  </div>
</template>
<script setup>
import LivePlayer from './components/LivePlayer.vue'
</script>

main.js

import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')

运行步骤

  1. 服务器:安装 ffmpeg,建目录 mkdir -p /opt/hls
  2. 启动后端mvn spring-boot:run(端口 8080)
  3. 启流POST /api/stream/start/cam1?rtsp=你的RTSP地址
  4. 启动前端npm install && npm run dev
  5. 浏览器打开前端即可看到监控画面

以上就是springboot+vue+ffmpeg实现视频监控的直播拉流播放的详细内容,更多关于springboot vue视频播放的资料请关注脚本之家其它相关文章!

相关文章

  • 数组重排序(如何将所有奇数都放在所有偶数前面)的深入分析

    数组重排序(如何将所有奇数都放在所有偶数前面)的深入分析

    本篇文章是对数组重排序(如何将所有奇数都放在所有偶数前面)的方法进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • springboot CompletableFuture并行计算及使用方法

    springboot CompletableFuture并行计算及使用方法

    CompletableFuture基于 Future 和 CompletionStage 接口,利用线程池、回调函数、异常处理、组合操作等机制,提供了强大而灵活的异步编程功能,这篇文章主要介绍了springboot CompletableFuture并行计算及使用方法,需要的朋友可以参考下
    2024-05-05
  • Spring Cloud Sleuth 和 Zipkin 进行分布式跟踪使用小结

    Spring Cloud Sleuth 和 Zipkin 进行分布式跟踪使用小结

    分布式跟踪是一种机制,我们可以使用它跟踪整个分布式系统中的特定请求,分布式跟踪允许您跟踪分布式系统中的请求,本文给大家介绍Spring Cloud Sleuth 和 Zipkin 进行分布式跟踪使用小结,感兴趣的朋友一起看看吧
    2022-03-03
  • 解决springcloud启动时报错Connection refused:connect问题

    解决springcloud启动时报错Connection refused:connect问题

    这篇文章主要介绍了解决springcloud启动时报错Connection refused:connect问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • 深入理解Java设计模式之桥接模式

    深入理解Java设计模式之桥接模式

    这篇文章主要介绍了JAVA设计模式之桥接模式的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下
    2021-11-11
  • java编写Http服务器下载工具

    java编写Http服务器下载工具

    这篇文章主要介绍了java编写Http服务器下载工具的方法,工具很简单,功能也很简单,代码就更简洁了,却非常实用,有需要的小伙伴参考下吧。
    2015-03-03
  • Spring security基于数据库中账户密码认证

    Spring security基于数据库中账户密码认证

    这篇文章主要介绍了Spring security基于数据库中账户密码认证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • 详解如何自定义parallelStream线程池

    详解如何自定义parallelStream线程池

    这篇文章主要为大家介绍了如何自定义parallelStream的线程池实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • Java中的增强for使用及说明

    Java中的增强for使用及说明

    增强for循环是一种简化遍历数组和集合元素的语法结构,适用于只需要访问元素而不需要索引或迭代器的情况,它提供了一种简洁而直观的方式来遍历数组或集合中的元素,但不能用于修改元素
    2025-11-11
  • Spring Boot 4.0 新特性实战全解析

    Spring Boot 4.0 新特性实战全解析

    SpringBoot4.0带来了多项重大升级,包括GraalVM原生镜像支持、自动配置优化、Web层升级(HTTP/3和MVC响应式支持)以及Testcontainers集成简化,本文详细介绍了每个特性的实操步骤,并提供迁移避坑指南,帮助开发者顺利升级到SpringBoot4.0,感兴趣的朋友跟随小编一起看看吧
    2026-01-01

最新评论