import 'dart:convert'; import 'package:http/http.dart' as http; class VimeoService { Future getVideoUrl(String vimeoUrl) async { final videoId = _extractVideoId(vimeoUrl); if (videoId == null) { throw Exception('Invalid Vimeo URL'); } final html = await _fetchHtml(videoId); final config = _extractConfig(html); if (config == null) { throw Exception('Failed to extract Vimeo config'); } return _extractHlsUrl(config); } Future _fetchHtml(String videoId) async { final response = await http.get( Uri.parse('https://player.vimeo.com/video/$videoId'), headers: { 'Origin': 'https://vimeo.com', 'Referer': 'https://vimeo.com/', 'Accept': 'text/html,application/xhtml+xml', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', }, ); return response.body; } static Map? _extractConfig(String html) { final regex = RegExp( r'window\.playerConfig\s*=\s*({.*?})\s*', dotAll: true, ); final match = regex.firstMatch(html); if (match == null) return null; final jsonString = match.group(1); if (jsonString == null) return null; return jsonDecode(jsonString); } String? _extractHlsUrl(Map config) { try { final files = config['request']?['files']; final hls = files?['hls']; if (hls == null) return null; final cdns = hls['cdns'] as Map; // Prefer fastly_skyfire or fallback to first CDN final cdn = cdns['fastly_skyfire'] ?? cdns.values.first; return cdn['url']; } catch (_) { return null; } } String? _extractVideoId(String url) { try { final uri = Uri.parse(url); if (uri.pathSegments.isNotEmpty) { return uri.pathSegments.last; } return null; } catch (_) { return null; } } }