9.4 KiB
9.4 KiB
无人机实时视频接口对接说明
概述
本模块实现了无人机实时视频流的获取功能,采用清洁架构设计,支持多种镜头类型切换(广角、变焦、红外),并兼容火山引擎和声网两种RTC SDK。
API 接口
接口地址
POST http://1.95.137.212:59015/iot/UAV/changeLens
请求参数
{
"sn": "1581F8HGX253U00A063U", // 无人机设备序列号(必填)
"lensType": "", // 镜头类型:wide(广角)、zoom(变焦)、ir(红外),可为空
"cameraIndex": "176-0-0", // 摄像头编号(必填)
"qualityType": "adaptive", // 清晰度:adaptive(自适应)、low、medium、high(默认adaptive)
"videoExpire": 720000000 // Token有效期(毫秒,默认720000000)
}
返回数据
{
"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
已注册以下单例:
sl.registerLazySingleton<GetUavVideoStreamUseCase>(
() => GetUavVideoStreamUseCase(sl()),
);
sl.registerFactory<DroneStationBloc>(
() => DroneStationBloc(sl(), sl(), sl(), sl()),
);
使用方式
方式一:直接使用示例页面
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. 导入必要的类
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
late DroneStationBloc _bloc;
@override
void initState() {
super.initState();
_bloc = sl<DroneStationBloc>();
// 加载视频流
_loadVideoStream(UavLensType.wide);
}
@override
void dispose() {
_bloc.close();
super.dispose();
}
3. 加载视频流
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. 监听状态变化
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. 切换镜头类型
// 切换到广角镜头
_loadVideoStream(UavLensType.wide);
// 切换到变焦镜头
_loadVideoStream(UavLensType.zoom);
// 切换到红外镜头
_loadVideoStream(UavLensType.ir);
RTC 集成
获取到视频流后,需要根据 urlType 选择对应的 RTC SDK:
火山引擎 (volc)
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)
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(...),
);
注意事项
-
可扩展性: 本模块采用清洁架构设计,所有业务逻辑与UI分离,便于在其他页面复用。
-
错误处理: 使用
Either<Failure, T>模式统一处理错误,确保异常不会直接抛出。 -
日志记录: 数据源层包含详细的日志输出,方便调试和问题排查。
-
默认值:
lensType可为空,后端会根据实际情况选择默认镜头qualityType默认为adaptive(自适应)videoExpire默认为720000000毫秒
-
Token 有效期:
videoExpire参数单位为毫秒,建议设置较长的有效期以避免频繁刷新。 -
多镜头支持: 通过
UavLensType枚举可以轻松扩展更多镜头类型。
后续工作
- 集成 RTC SDK 显示实际视频画面
- 添加视频录制功能
- 添加截图功能
- 优化视频加载超时处理
- 添加视频质量切换功能
- 支持多路视频同时观看
相关文件清单
新增文件
lib/features/v2/device_list/domain/entities/uav_video_stream_entity.dartlib/features/v2/device_list/domain/usecases/get_uav_video_stream_usecase.dartlib/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- 注册依赖