76 lines
1.9 KiB
Dart
76 lines
1.9 KiB
Dart
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;
|
|
}
|
|
}
|