Files
flutterApp/docs/UAV_VIDEO_INTEGRATION_GUIDE.md

324 lines
9.4 KiB
Markdown
Raw Normal View History

2026-08-07 08:49:29 +08:00
# 无人机实时视频接口对接说明
## 概述
本模块实现了无人机实时视频流的获取功能,采用清洁架构设计,支持多种镜头类型切换(广角、变焦、红外),并兼容火山引擎和声网两种RTC SDK。
## API 接口
### 接口地址
```
POST http://1.95.137.212:59015/iot/UAV/changeLens
```
### 请求参数
```json
{
"sn": "1581F8HGX253U00A063U", // 无人机设备序列号(必填)
"lensType": "", // 镜头类型:wide(广角)、zoom(变焦)、ir(红外),可为空
"cameraIndex": "176-0-0", // 摄像头编号(必填)
"qualityType": "adaptive", // 清晰度:adaptive(自适应)、low、medium、high(默认adaptive)
"videoExpire": 720000000 // Token有效期(毫秒,默认720000000)
}
```
### 返回数据
```json
{
"msg": "操作成功",
"code": 200,
"data": {
"sn": "1581F8HGX253U00A063U",
"camera_index": "176-0-0",
"url": "app_id=xxx&expire_time=xxx&room_id=xxx&token=xxx&user_id=xxx",
"expire_ts": 1781155234,
"url_type": "volc" // volc(火山引擎) 或 agora(声网)
}
}
```
## 架构设计
### 目录结构
```
lib/features/v2/device_list/
├── domain/
│ ├── entities/
│ │ └── uav_video_stream_entity.dart # 实体类
│ ├── repositories/
│ │ ── drone_station_repository.dart # 仓库接口
│ └── usecases/
│ └── get_uav_video_stream_usecase.dart # 用例
├── data/
│ ├── datasources/
│ │ ├── drone_station_datasource.dart # 数据源接口
│ │ └── drone_station_datasource_impl.dart # 数据源实现
│ └── repositories/
│ └── drone_station_repository_impl.dart # 仓库实现
── presentation/
├── bloc/
│ ├── drone_station_bloc.dart # BLoC状态管理
│ ├── drone_station_event.dart # 事件定义
│ └── drone_station_state.dart # 状态定义
└── pages/
── uav_live_video_page.dart # 示例页面
```
### 核心组件
#### 1. 实体类 (Entity)
**文件**: `domain/entities/uav_video_stream_entity.dart`
定义了枚举类型和实体类:
- `UavLensType`: 镜头类型枚举(wide、zoom、ir)
- `VideoQualityType`: 视频质量枚举(adaptive、low、medium、high)
- `UavVideoStreamEntity`: 视频流实体,包含解析RTC参数的方法
#### 2. 数据源 (DataSource)
**文件**: `data/datasources/drone_station_datasource_impl.dart`
实现了API调用逻辑:
- 发送POST请求到 `/iot/UAV/changeLens`
- 处理响应并转换为实体对象
- 包含详细的日志输出用于调试
#### 3. 仓库 (Repository)
**文件**: `data/repositories/drone_station_repository_impl.dart`
使用 `fpdart` 的 `Either` 类型处理错误:
- 成功时返回 `Right(UavVideoStreamEntity)`
- 失败时返回 `Left(Failure)`
#### 4. 用例 (UseCase)
**文件**: `domain/usecases/get_uav_video_stream_usecase.dart`
封装业务逻辑,供BLoC调用。
#### 5. BLoC 状态管理
**文件**: `presentation/bloc/drone_station_bloc.dart`
新增事件和状态:
- **事件**: `UavVideoStreamLoad` - 加载视频流
- **状态**:
- `UavVideoStreamLoading` - 加载中
- `UavVideoStreamLoaded` - 加载成功
- `UavVideoStreamError` - 加载失败
#### 6. 依赖注入
**文件**: `core/di/injection.dart`
已注册以下单例:
```dart
sl.registerLazySingleton<GetUavVideoStreamUseCase>(
() => GetUavVideoStreamUseCase(sl()),
);
sl.registerFactory<DroneStationBloc>(
() => DroneStationBloc(sl(), sl(), sl(), sl()),
);
```
## 使用方式
### 方式一:直接使用示例页面
```dart
import 'package:maibu_satabot_v2/features/v2/device_list/presentation/pages/uav_live_video_page.dart';
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UavLiveVideoPage(
droneSn: '1581F8HGX253U00A063U',
cameraIndex: '176-0-0',
),
),
);
```
### 方式二:在现有页面中使用
#### 1. 导入必要的类
```dart
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../core/di/injection.dart';
import '../../domain/entities/uav_video_stream_entity.dart';
import '../bloc/drone_station_bloc.dart';
import '../bloc/drone_station_event.dart';
import '../bloc/drone_station_state.dart';
```
#### 2. 初始化 BLoC
```dart
late DroneStationBloc _bloc;
@override
void initState() {
super.initState();
_bloc = sl<DroneStationBloc>();
// 加载视频流
_loadVideoStream(UavLensType.wide);
}
@override
void dispose() {
_bloc.close();
super.dispose();
}
```
#### 3. 加载视频流
```dart
void _loadVideoStream(UavLensType lensType) {
setState(() {
_isLoading = true;
_errorMessage = null;
});
_bloc.add(
UavVideoStreamLoad(
sn: widget.droneSn,
cameraIndex: widget.cameraIndex,
lensType: lensType,
qualityType: VideoQualityType.adaptive,
videoExpire: 720000000,
),
);
}
```
#### 4. 监听状态变化
```dart
BlocConsumer<DroneStationBloc, DroneStationState>(
listener: (context, state) {
if (state is UavVideoStreamLoaded) {
final videoStream = state.videoStream;
debugPrint('URL Type: ${videoStream.urlType}');
debugPrint('AppId: ${videoStream.appId}');
debugPrint('RoomId: ${videoStream.roomId}');
debugPrint('UserId: ${videoStream.userId}');
// TODO: 根据 urlType 初始化对应的 RTC 引擎
if (videoStream.urlType.toLowerCase() == 'volc') {
// 使用火山引擎 RTC SDK
} else if (videoStream.urlType.toLowerCase() == 'agora') {
// 使用声网 RTC SDK
}
} else if (state is UavVideoStreamError) {
setState(() {
_errorMessage = state.message;
});
}
},
builder: (context, state) {
// 根据状态渲染UI
if (state is UavVideoStreamLoading) {
return const CircularProgressIndicator();
}
if (state is UavVideoStreamLoaded) {
// 显示视频画面
return Container();
}
if (state is UavVideoStreamError) {
return Text('错误: ${state.message}');
}
return Container();
},
)
```
#### 5. 切换镜头类型
```dart
// 切换到广角镜头
_loadVideoStream(UavLensType.wide);
// 切换到变焦镜头
_loadVideoStream(UavLensType.zoom);
// 切换到红外镜头
_loadVideoStream(UavLensType.ir);
```
## RTC 集成
获取到视频流后,需要根据 `urlType` 选择对应的 RTC SDK:
### 火山引擎 (volc)
```dart
final appId = videoStream.appId;
final roomId = videoStream.roomId;
final token = videoStream.token;
final userId = videoStream.userId;
// 使用 volc_engine_rtc SDK
final engine = await RTCEngine.createRTCEngine(
RTCVideoContext(appId: appId, eventHandler: handler),
);
final room = await engine.createRTCRoom(roomId);
await room.joinRoom(token: token, userId: userId);
```
### 声网 (agora)
```dart
final appId = videoStream.appId;
final channelId = videoStream.roomId;
final token = videoStream.token;
final uid = int.tryParse(videoStream.userId) ?? 0;
// 使用 agora_rtc_engine SDK
final engine = createAgoraRtcEngine();
await engine.initialize(RtcEngineContext(appId: appId));
await engine.joinChannel(
token: token,
channelId: channelId,
uid: uid,
options: ChannelMediaOptions(...),
);
```
## 注意事项
1. **可扩展性**: 本模块采用清洁架构设计,所有业务逻辑与UI分离,便于在其他页面复用。
2. **错误处理**: 使用 `Either<Failure, T>` 模式统一处理错误,确保异常不会直接抛出。
3. **日志记录**: 数据源层包含详细的日志输出,方便调试和问题排查。
4. **默认值**:
- `lensType` 可为空,后端会根据实际情况选择默认镜头
- `qualityType` 默认为 `adaptive`(自适应)
- `videoExpire` 默认为 `720000000` 毫秒
5. **Token 有效期**: `videoExpire` 参数单位为毫秒,建议设置较长的有效期以避免频繁刷新。
6. **多镜头支持**: 通过 `UavLensType` 枚举可以轻松扩展更多镜头类型。
## 后续工作
1. [ ] 集成 RTC SDK 显示实际视频画面
2. [ ] 添加视频录制功能
3. [ ] 添加截图功能
4. [ ] 优化视频加载超时处理
5. [ ] 添加视频质量切换功能
6. [ ] 支持多路视频同时观看
## 相关文件清单
### 新增文件
- `lib/features/v2/device_list/domain/entities/uav_video_stream_entity.dart`
- `lib/features/v2/device_list/domain/usecases/get_uav_video_stream_usecase.dart`
- `lib/features/v2/device_list/presentation/pages/uav_live_video_page.dart`
### 修改文件
- `lib/core/consts/http_api_consts.dart` - 添加 API 常量
- `lib/features/v2/device_list/data/datasources/drone_station_datasource.dart` - 添加接口方法
- `lib/features/v2/device_list/data/datasources/drone_station_datasource_impl.dart` - 实现接口
- `lib/features/v2/device_list/data/repositories/drone_station_repository_impl.dart` - 实现仓库
- `lib/features/v2/device_list/domain/repositories/drone_station_repository.dart` - 添加仓库接口
- `lib/features/v2/device_list/presentation/bloc/drone_station_event.dart` - 添加事件
- `lib/features/v2/device_list/presentation/bloc/drone_station_state.dart` - 添加状态
- `lib/features/v2/device_list/presentation/bloc/drone_station_bloc.dart` - 添加事件处理
- `lib/core/di/injection.dart` - 注册依赖