Files

76 lines
1.9 KiB
Dart
Raw Permalink Normal View History

2026-07-14 11:11:36 +08:00
import 'dart:async';
import 'package:fvp/mdk.dart' as mdk;
import '../../shared/utils/app_logger.dart';
import 'media_capability_analyzer.dart';
class MediaProbeService {
static final MediaProbeService instance = MediaProbeService._();
MediaProbeService._();
static const _tag = 'MediaProbe';
final Map<String, ProbeResult> _cache = {};
Future<ProbeResult?> probe(
String url, {
Duration timeout = const Duration(seconds: 5),
}) async {
final cached = _cache[url];
if (cached != null) {
AppLogger.debug(_tag, 'probe: cache hit url=${_truncate(url)}');
return cached;
}
AppLogger.debug(_tag, 'probe: start url=${_truncate(url)}');
mdk.Player? player;
try {
player = mdk.Player()
..setProperty('avio.reconnect', '1')
..setProperty('avformat.extension_picky', '0')
..setProperty('avformat.allowed_segment_extensions', 'ALL');
player.media = url;
final ret = await player.prepare().timeout(timeout, onTimeout: () => -10);
ProbeResult? result;
if (ret >= 0) {
final video = player.mediaInfo.video;
if (video != null && video.isNotEmpty) {
final codec = video.first.codec;
result = ProbeResult(
videoCodec: codec.codec.isNotEmpty ? codec.codec : null,
);
}
} else {
AppLogger.warn(
_tag,
'probe: prepare failed ret=$ret url=${_truncate(url)}',
);
}
if (result != null) {
_cache[url] = result;
AppLogger.debug(
_tag,
'probe: success url=${_truncate(url)} codec=${result.videoCodec}',
);
}
return result;
} catch (e) {
AppLogger.warn(_tag, 'probe: error url=${_truncate(url)}', e);
return null;
} finally {
player?.dispose();
}
}
static String _truncate(String url) {
return url.length > 50 ? '${url.substring(0, 50)}...' : url;
}
}