Diagnostic admin : chronométrer l'ouverture d'une chaîne chez le panneau

~4,3 s des ~4,6 s d'un zap se passent avant le premier octet du panneau.
Le compte autorise aussi le HLS (allowed_output_formats : m3u8, ts) ;
GET /api/admin/upstream-probe?stream=<id> mesure, pour .ts et .m3u8,
chaque redirection, les en-têtes, le premier octet et le premier segment,
pour décider du format à utiliser. Admin uniquement ; seuls l'hôte et les
durées sont rendus, jamais les identifiants ni les jetons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Opus 5.5 committed 2026-10-10 22:56:34 +02:00
1 parent 584068b45b
commit a3640a6b5f
3 files changed
+219

No files matched your search

+24
View File
@@ -28,6 +28,7 @@ import 'middleware/security_middleware.dart';
import 'services/cleanup_service.dart';
import 'services/recording_scheduler.dart';
import 'utils/asset_versioning.dart';
import 'api/upstream_probe.dart';
void main(List<String> args) async {
// Parse command line arguments
@@ -269,6 +270,29 @@ void main(List<String> args) async {
);
});
// GET /api/admin/upstream-probe?stream=<id> : chronomètre l'ouverture
// d'une chaîne chez le fournisseur en .ts et en .m3u8 (diagnostic du
// délai de zap ; aucun identifiant dans la réponse).
router.get('/upstream-probe', (Request req) async {
final user = req.context['user'] as User?;
if (user == null || !user.isAdmin) {
return Response.forbidden(
jsonEncode({'error': 'Admin access required'}),
);
}
final streamId = req.url.queryParameters['stream'] ?? '';
if (!RegExp(r'^[0-9]+$').hasMatch(streamId)) {
return Response.badRequest(body: 'stream=<id numérique> requis');
}
final playlist = await getPlaylist(req);
if (playlist == null) return Response.forbidden('No playlist');
final result = await probeUpstream(playlist, streamId);
return Response.ok(
jsonEncode(result),
headers: {'content-type': 'application/json'},
);
});
return router(request);
}),
);