<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>4.4-1.5.5</version>
</dependency>
</dependencies>
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@Service
public class VideoStreamService {
private FFmpegFrameGrabber grabber;
private Java2DFrameConverter converter;
public VideoStreamService() {
this.converter = new Java2DFrameConverter();
}
public void startGrabber(String source) throws FFmpegFrameGrabber.Exception {
grabber = new FFmpegFrameGrabber(source);
grabber.start();
}
public void stopGrabber() throws FFmpegFrameGrabber.Exception {
if (grabber != null) {
grabber.stop();
grabber = null;
}
}
public void streamVideo(OutputStream outputStream) throws IOException, FFmpegFrameGrabber.Exception {
if (grabber == null) {
throw new IllegalStateException("Grabber is not started");
}
Frame frame;
while ((frame = grabber.grab()) != null) {
BufferedImage bufferedImage = converter.convert(frame);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", baos);
byte[] imageBytes = baos.toByteArray();
// Write the MJPEG frame
outputStream.write(("--myboundary\r\n" +
"Content-Type: image/jpeg\r\n" +
"Content-Length: " + imageBytes.length + "\r\n\r\n").getBytes());
outputStream.write(imageBytes);
outputStream.write("\r\n".getBytes());
outputStream.flush();
}
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@RestController
@RequestMapping("/api")
public class VideoStreamController {
@Autowired
private VideoStreamService videoStreamService;
@GetMapping(value = "/video", produces = "multipart/x-mixed-replace; boundary=myboundary")
public void streamVideo(HttpServletResponse response) throws IOException {
response.setContentType("multipart/x-mixed-replace; boundary=myboundary");
try {
videoStreamService.startGrabber("path/to/your/video.mp4"); // 替换为你的视频源
videoStreamService.streamVideo(response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
videoStreamService.stopGrabber();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Video Stream</title>
</head>
<body>
<h1>Video Stream</h1>
<img id="videoStream" src="/api/video" alt="Video Stream">
</body>
</html>