Files
flutterApp/lib/features/remote_control/presentation/widgets/my_video_player.dart
2026-01-19 18:24:24 +08:00

105 lines
3.1 KiB
Dart

import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:maibu_satabot_v2/core/domain/entities/user_entity.dart';
import 'package:maibu_satabot_v2/features/devices/domain/entities/device_entity.dart';
class MyVideoPlayer extends StatefulWidget {
final String deviceIp;
final DeviceEntity device;
final UserEntity user;
const MyVideoPlayer({
Key? key,
required this.deviceIp,
required this.device,
required this.user,
}) : super(key: key);
@override
State<MyVideoPlayer> createState() => _MyVideoPlayerState();
}
class _MyVideoPlayerState extends State<MyVideoPlayer> {
InAppLocalhostServer? _localServer;
InAppWebViewController? _webViewController;
bool _isServerRunning = false;
int? actualPort;
@override
void initState() {
super.initState();
_startServer();
}
Future<void> _startServer() async {
int availablePort = 0;
try {
var socket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
availablePort = socket.port;
await socket.close();
} catch (e) {
availablePort = 8080;
}
_localServer = InAppLocalhostServer(port: availablePort);
await _localServer!.start();
actualPort = availablePort;
if (mounted) {
setState(() {
_isServerRunning = true;
});
}
}
@override
void dispose() {
_localServer?.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
// 防止父级因其他状态 setState 导致视频闪烁
if (!_isServerRunning) {
return const Center(child: CircularProgressIndicator(color: Colors.white));
}
// [性能关键] RepaintBoundary 必须包裹渲染密集型的 WebView
return RepaintBoundary(
child: InAppWebView(
initialUrlRequest: URLRequest(
url: WebUri("http://localhost:$actualPort/assets/www/webrtc/playwebrtc.html"),
),
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
mediaPlaybackRequiresUserGesture: false,
allowsInlineMediaPlayback: true,
preferredContentMode: UserPreferredContentMode.MOBILE,
// 优化性能:禁用滚动,开启硬件加速
supportZoom: false,
disableHorizontalScroll: true,
disableVerticalScroll: true,
hardwareAcceleration: true,
),
onWebViewCreated: (controller) => _webViewController = controller,
onPermissionRequest: (controller, request) async {
return PermissionResponse(
resources: request.resources,
action: PermissionResponseAction.GRANT,
);
},
onLoadStop: (controller, url) {
_initWebRTC(widget.deviceIp, widget.device.deviceName, widget.user.token);
},
),
);
}
void _initWebRTC(String deviceIp, String deviceId, String token) {
final streamUrl = "webrtc://$deviceIp/live/livestream/$deviceId?token=$token";
_webViewController?.evaluateJavascript(source: "setStreamUrl('$streamUrl')");
}
}