Stabilizza live YouTube/RTMP e fix crash rotazione mobile.
Pipeline YouTube con relay, overlay e publisher sync lato backend; fix GL pauseGlDuringRotation su Android per evitare crash in rotazione durante lo streaming Flutter. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,12 +2,14 @@ import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../app/theme.dart';
|
||||
import '../../providers/score_provider.dart';
|
||||
import '../../providers/score_sync_provider.dart';
|
||||
import '../../providers/session_provider.dart';
|
||||
import '../../shared/api_client.dart';
|
||||
import '../../shared/models/match.dart';
|
||||
@@ -74,9 +76,9 @@ class _StepNetworkTestState extends ConsumerState<StepNetworkTest> {
|
||||
|
||||
_youtubePoll?.cancel();
|
||||
var attempts = 0;
|
||||
_youtubePoll = Timer.periodic(const Duration(seconds: 2), (_) async {
|
||||
_youtubePoll = Timer.periodic(const Duration(seconds: 3), (_) async {
|
||||
attempts++;
|
||||
if (!mounted || attempts > 30) {
|
||||
if (!mounted || attempts > 60) {
|
||||
_youtubePoll?.cancel();
|
||||
return;
|
||||
}
|
||||
@@ -150,14 +152,10 @@ class _StepNetworkTestState extends ConsumerState<StepNetworkTest> {
|
||||
if (session.score != null) {
|
||||
ref.read(scoreProvider.notifier).reset(session.score!);
|
||||
}
|
||||
// Tabellone via HTTP; WebSocket solo dalla camera (evita doppio connect controller/camera).
|
||||
try {
|
||||
await ref.read(websocketServiceProvider).connect(
|
||||
sessionId: session.id,
|
||||
deviceRole: 'controller',
|
||||
);
|
||||
} catch (_) {
|
||||
// Tabellone locale; sync quando la camera si connette.
|
||||
}
|
||||
await ref.read(scoreSyncProvider).pullFromServer();
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
String _connectivityLabel(List<ConnectivityResult> results) {
|
||||
@@ -184,18 +182,22 @@ class _StepNetworkTestState extends ConsumerState<StepNetworkTest> {
|
||||
ref.read(scoreProvider.notifier).reset(const ScoreState());
|
||||
}
|
||||
|
||||
if (!mounted) return;
|
||||
await ref.read(websocketServiceProvider).disconnect();
|
||||
if (!mounted) return;
|
||||
context.go('/session/${started.id}/camera');
|
||||
|
||||
try {
|
||||
final ws = ref.read(websocketServiceProvider);
|
||||
await ws.connect(sessionId: started.id, deviceRole: 'controller');
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Diretta avviata ma sync limitata: $e')),
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
if (mounted) {
|
||||
final msg = e.response?.data is Map
|
||||
? (e.response!.data['error'] ?? e.response!.data['message'])?.toString()
|
||||
: null;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
msg?.isNotEmpty == true ? 'Errore avvio diretta: $msg' : 'Errore avvio diretta: ${e.message}',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
|
||||
@@ -270,7 +270,7 @@ class _StepTransmissionState extends ConsumerState<StepTransmission> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('720p · 30fps · 2.5 Mbps', style: theme.textTheme.titleMedium),
|
||||
Text('720p · 30fps · 3 Mbps', style: theme.textTheme.titleMedium),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Bitrate fisso consigliato per reti instabili',
|
||||
|
||||
Reference in New Issue
Block a user