# Java项目集成RTSPtoWeb指南
本文档说明如何将RTSPtoWeb项目集成到Java项目中,实现摄像头管理和视频流展示功能。
## 集成方案
### 方案一:嵌入式集成(推荐)
将RTSPtoWeb的前端页面嵌入到Java Web项目中,通过iframe或直接集成HTML。
#### 1. 嵌入整个管理界面
```html
```
#### 2. 嵌入特定功能页面
```html
```
### 方案二:API集成
通过REST API调用RTSPtoWeb的功能,在Java项目中实现自定义界面。
#### Java HTTP客户端示例
```java
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
public class RTSPtoWebClient {
private final String baseUrl;
private final HttpClient httpClient;
private final ObjectMapper objectMapper;
public RTSPtoWebClient(String baseUrl) {
this.baseUrl = baseUrl;
this.httpClient = HttpClient.newHttpClient();
this.objectMapper = new ObjectMapper();
}
// 获取所有摄像头
public JsonNode getAllCameras() throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/cameras"))
.GET()
.build();
HttpResponse response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
return objectMapper.readTree(response.body());
} else {
throw new RuntimeException("Failed to get cameras: " + response.statusCode());
}
}
// 根据单位代码获取摄像头
public JsonNode getCamerasByUnitCode(String unitCode) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/cameras/unit/" + unitCode))
.GET()
.build();
HttpResponse response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
return objectMapper.readTree(response.body());
} else {
throw new RuntimeException("Failed to get cameras by unit: " + response.statusCode());
}
}
// 获取特定摄像头信息
public JsonNode getCamera(String cameraId) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/camera/" + cameraId))
.GET()
.build();
HttpResponse response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
return objectMapper.readTree(response.body());
} else {
throw new RuntimeException("Failed to get camera: " + response.statusCode());
}
}
// 添加摄像头
public JsonNode addCamera(CameraData cameraData) throws Exception {
String jsonBody = objectMapper.writeValueAsString(cameraData);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/camera/add"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
HttpResponse response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
return objectMapper.readTree(response.body());
} else {
throw new RuntimeException("Failed to add camera: " + response.statusCode());
}
}
// 更新摄像头
public JsonNode updateCamera(String cameraId, CameraData cameraData) throws Exception {
String jsonBody = objectMapper.writeValueAsString(cameraData);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/camera/" + cameraId))
.header("Content-Type", "application/json")
.PUT(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
HttpResponse response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
return objectMapper.readTree(response.body());
} else {
throw new RuntimeException("Failed to update camera: " + response.statusCode());
}
}
// 删除摄像头
public boolean deleteCamera(String cameraId) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/camera/" + cameraId))
.DELETE()
.build();
HttpResponse response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
return response.statusCode() == 200;
}
// 刷新摄像头状态
public JsonNode refreshCameras() throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/cameras/refresh"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{}"))
.build();
HttpResponse response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
return objectMapper.readTree(response.body());
} else {
throw new RuntimeException("Failed to refresh cameras: " + response.statusCode());
}
}
// 获取视频流列表
public JsonNode getStreams() throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/streams"))
.GET()
.build();
HttpResponse response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
return objectMapper.readTree(response.body());
} else {
throw new RuntimeException("Failed to get streams: " + response.statusCode());
}
}
// 生成播放URL
public String getPlayUrl(String cameraId, int channel, String type) {
switch (type.toLowerCase()) {
case "hls":
return baseUrl + "/stream/" + cameraId + "/channel/" + channel + "/hls/live/index.m3u8";
case "webrtc":
return baseUrl + "/pages/player/webrtc/" + cameraId + "/" + channel;
case "mse":
return baseUrl + "/pages/player/mse/" + cameraId + "/" + channel;
default:
return baseUrl + "/pages/player/all/" + cameraId + "/" + channel;
}
}
}
// 摄像头数据模型
class CameraData {
public String name;
public String ip;
public int port = 554;
public String username;
public String password;
public String rtsp_url;
public String camera_produce;
public String device_type;
public String unit_code;
public String nvr_produce;
public String nvr_path;
public String play_back;
public boolean enabled = true;
public int user_id;
public int dept_id;
// 构造函数、getter和setter方法
public CameraData() {}
public CameraData(String name, String ip, String username, String password, String rtspUrl) {
this.name = name;
this.ip = ip;
this.username = username;
this.password = password;
this.rtsp_url = rtspUrl;
}
}
```
#### Spring Boot Controller示例
```java
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import com.fasterxml.jackson.databind.JsonNode;
@Controller
@RequestMapping("/camera")
public class CameraController {
private final RTSPtoWebClient rtspClient;
public CameraController() {
this.rtspClient = new RTSPtoWebClient("http://localhost:8083");
}
// 摄像头管理页面
@GetMapping("/management")
public String cameraManagement(Model model) {
try {
JsonNode cameras = rtspClient.getAllCameras();
model.addAttribute("cameras", cameras);
} catch (Exception e) {
model.addAttribute("error", "获取摄像头列表失败: " + e.getMessage());
}
return "camera/management";
}
// 根据单位获取摄像头
@GetMapping("/unit/{unitCode}")
@ResponseBody
public JsonNode getCamerasByUnit(@PathVariable String unitCode) {
try {
return rtspClient.getCamerasByUnitCode(unitCode);
} catch (Exception e) {
throw new RuntimeException("获取摄像头失败", e);
}
}
// 视频监控页面
@GetMapping("/monitor")
public String videoMonitor(Model model) {
try {
JsonNode cameras = rtspClient.getAllCameras();
model.addAttribute("cameras", cameras);
} catch (Exception e) {
model.addAttribute("error", "获取摄像头列表失败: " + e.getMessage());
}
return "camera/monitor";
}
// 添加摄像头
@PostMapping("/add")
@ResponseBody
public JsonNode addCamera(@RequestBody CameraData cameraData) {
try {
return rtspClient.addCamera(cameraData);
} catch (Exception e) {
throw new RuntimeException("添加摄像头失败", e);
}
}
// 获取播放URL
@GetMapping("/{cameraId}/play-url")
@ResponseBody
public String getPlayUrl(@PathVariable String cameraId,
@RequestParam(defaultValue = "0") int channel,
@RequestParam(defaultValue = "hls") String type) {
return rtspClient.getPlayUrl(cameraId, channel, type);
}
}
```
### 方案三:前端JavaScript集成
在Java项目的前端页面中直接使用RTSPtoWeb提供的JavaScript API。
```html
视频监控系统
```
## 部署配置
### 1. RTSPtoWeb服务配置
确保RTSPtoWeb服务正常运行:
```bash
# 启动RTSPtoWeb服务
cd RTSPtoWeb
go run . --config config.json
```
### 2. 跨域配置
如果Java项目和RTSPtoWeb运行在不同端口,需要配置CORS:
在RTSPtoWeb的`apiHTTPServer.go`中添加CORS中间件:
```go
func CORSMiddleware() gin.HandlerFunc {
return gin.HandlerFunc(func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Credentials", "true")
c.Header("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
c.Header("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
})
}
```
### 3. 反向代理配置
使用Nginx反向代理统一端口:
```nginx
server {
listen 80;
server_name your-domain.com;
# Java应用
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# RTSPtoWeb API
location /rtsp-api/ {
proxy_pass http://localhost:8083/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# WebSocket支持
location /rtsp-api/stream/ {
proxy_pass http://localhost:8083/stream/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
```
## API接口文档
### 摄像头管理API
| 方法 | 路径 | 描述 |
|------|------|------|
| GET | `/cameras` | 获取所有摄像头列表 |
| GET | `/cameras/unit/{unitcode}` | 根据单位代码获取摄像头 |
| GET | `/camera/{id}` | 获取特定摄像头信息 |
| POST | `/camera/add` | 添加新摄像头 |
| PUT | `/camera/{id}` | 更新摄像头信息 |
| DELETE | `/camera/{id}` | 删除摄像头 |
| POST | `/cameras/refresh` | 刷新摄像头状态 |
### 视频流API
| 方法 | 路径 | 描述 |
|------|------|------|
| GET | `/streams` | 获取所有视频流列表 |
| GET | `/stream/{id}/channel/{channel}/hls/live/index.m3u8` | HLS播放地址 |
| GET | `/pages/player/webrtc/{id}/{channel}` | WebRTC播放页面 |
| GET | `/pages/player/mse/{id}/{channel}` | MSE播放页面 |
| GET | `/pages/player/all/{id}/{channel}` | 通用播放页面 |
## 注意事项
1. **数据库配置**:确保RTSPtoWeb的数据库配置正确,摄像头数据存储在数据库中。
2. **网络配置**:确保Java项目能够访问RTSPtoWeb服务的端口(默认8083)。
3. **安全考虑**:在生产环境中,建议配置认证和授权机制。
4. **性能优化**:对于大量摄像头的场景,建议实现分页和缓存机制。
5. **错误处理**:实现完善的错误处理和重试机制。
6. **监控告警**:建议添加服务健康检查和告警机制。
## 示例项目结构
```
java-rtsp-integration/
├── src/main/java/
│ ├── controller/
│ │ ├── CameraController.java
│ │ └── VideoController.java
│ ├── service/
│ │ ├── RTSPtoWebClient.java
│ │ └── CameraService.java
│ └── model/
│ └── CameraData.java
├── src/main/resources/
│ ├── templates/
│ │ ├── camera/
│ │ │ ├── management.html
│ │ │ └── monitor.html
│ │ └── layout.html
│ └── static/
│ ├── css/
│ └── js/
└── pom.xml
```
通过以上集成方案,可以在Java项目中完整地使用RTSPtoWeb的摄像头管理和视频流功能。