extractAudioAndVideoTs method

Future<String> extractAudioAndVideoTs(
  1. String m3u8, {
  2. String initialSubtitle = "",
  3. String formatter(
    1. String quality
    )?,
  4. bool descending = true,
})

Implementation

Future<String> extractAudioAndVideoTs(
  String m3u8, {
  String initialSubtitle = "",
  String Function(String quality)? formatter,
  bool descending = true,
}) async {
  Dio dio = Dio();
  (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
      (HttpClient client) {
    client.badCertificateCallback =
        (X509Certificate cert, String host, int port) => true;
    return client;
  };
  dio.options.connectTimeout = 5 * 1000;

  dio.interceptors.add(RetryInterceptor(
    dio: dio,
    logPrint: print, // specify log function (optional)
    retries: 10, // retry count (optional)
    retryDelays: const [
      // set delays between retries (optional)
      Duration(seconds: 1), // wait 1 sec before first retry
      Duration(seconds: 2), // wait 2 sec before second retry
      Duration(seconds: 3), // wait 3 sec before third retry
    ],
  ));

//REGULAR EXPRESIONS//
  final RegExp netRegxUrl = RegExp(r'^(http|https):\/\/([\w.]+\/?)\S*');
  final RegExp netRegx2 = RegExp(r'(.*)\r?\/');
  final RegExp regExpPlaylist = RegExp(
    r"#EXT-X-STREAM-INF:(?:.*,RESOLUTION=(\d+x\d+))?,?(.*)\r?\n(.*)",
    caseSensitive: false,
    multiLine: true,
  );
  final RegExp regExpAudio = RegExp(
    r"""^#EXT-X-MEDIA:TYPE=AUDIO(?:.*,URI="(.*m3u8.*)")""",
    caseSensitive: false,
    multiLine: true,
  );
  final RegExp regExpListOfLinks =
      RegExp("#EXTINF:.+?\n+(.+)", multiLine: true, caseSensitive: false);
  Response res = await dio.get(m3u8);
  //GET m3u8 file
  String content = "";
  if (res.statusCode == 200) {
    content = res.data;

//Find matches
    List<RegExpMatch> playlistMatches =
        regExpPlaylist.allMatches(content).toList();
    List<RegExpMatch> audioMatches = regExpAudio.allMatches(content).toList();
    //List<RegExpMatch> ListOfLinks = regExpListOfLinks.allMatches(content).toList();
    Map<String, List<String?>> downloadLinks = {};
    Map<String, String> sourceUrls = {};

    final List<String> audioUrls = [];

    for (final RegExpMatch playlistMatch in playlistMatches) {
      final RegExpMatch? playlist = netRegx2.firstMatch(m3u8);
      final String sourceURL = (playlistMatch.group(3)).toString();
      final String quality = (playlistMatch.group(1)).toString();
      final bool isNetwork = netRegxUrl.hasMatch(sourceURL);
      String playlistUrl = sourceURL;

      if (!isNetwork) {
        final String? dataURL = playlist!.group(0);
        playlistUrl = "$dataURL$sourceURL";
      }

      //Find audio url
      for (final RegExpMatch audioMatch in audioMatches) {
        final String audio = (audioMatch.group(1)).toString();
        final bool isNetwork = netRegxUrl.hasMatch(audio);
        final RegExpMatch? match = netRegx2.firstMatch(playlistUrl);
        String audioUrl = audio;

        if (!isNetwork && match != null) {
          audioUrl = "${match.group(0)}$audio";
        }
        audioUrls.add(audioUrl);
      }

      sourceUrls[quality] = playlistUrl;
    }
    //print("here");
    List<String> qualityKeys = sourceUrls.keys.toList();
    qualityKeys.sort((a, b) {
      try {
        return int.parse(a.split("x")[0])
            .compareTo(int.parse(b.split("x")[0]));
      } catch (_) {
        print("error comparing qualities hls,$_");
        return -1;
      }
    });
    if (sourceUrls.isEmpty) {
      //input was playlist
      List<RegExpMatch> ListOfLinks =
          regExpListOfLinks.allMatches(content).toList();
      String baseUrl = m3u8;
      ListOfLinks.forEach((element) {
        final bool isNetwork = netRegxUrl.hasMatch(element.group(1) ?? "");
        if (!isNetwork) {
          content.replaceAll(
              element.group(1) ?? "",
              baseUrl.substring(0, baseUrl.lastIndexOf('/')) +
                  "/" +
                  (element.group(1) ?? ""));
        }
      });
      return content;
    }

    //print(downloadLinks);
    return "";
  } else {
    return "";
  }
}