Flutter hls offline video download

690 Views Asked by At

How to download hls videos and make it available offline. I tried flutter downloader . But it can't download hls video.

I tried using hls parser but don't know how to extract a downloadable url from that.

2

There are 2 best solutions below

1
werux On

you can use https://pub.dev/packages/better_player better player, it can play and cache hls videos.

0
Fozle Rabbi On

Download hls video your need 3 packages-

  • dio: ^5.3.3
  • path_provider: ^2.1.1
  • flutter_hls_parser: ^2.0.1

Future<void> downloadFile(BuildContext context, String url, String name, String folderName) async {
    final dio = Dio();
    //configure video file name
    name = "$name.m3u8";
    ///get playList or get regulation form video
    Response playListResponse = await dio.get(url);
    log('get playlist ${playListResponse.data}');
    ///remove /playlist.m3u8 from main video url
    String baseUrl = url.replaceAll('/playlist.m3u8', '');
    ///
    ///then will concatenation base to highest regulation from videoPlay playList response
    ///use regular expression
    ///Like us: $baseUrl/1280x720/video.m3u8
    ///
    String playListDownloadUrl = '$baseUrl/${getHighestRegulation('${playListResponse.data}')}';
    log('log main video - playListDownloadUrl  $playListDownloadUrl');

    final appStorage = await getApplicationDocumentsDirectory();
    await Directory('${appStorage.path}/$folderName').create();

    // Download the playlist file.
    final playlistFile = File("${appStorage.path}/$folderName/$name");
    await dio.download(playListDownloadUrl, playlistFile.path,
        options: Options(
          responseType: ResponseType.bytes,
        ));
    log('download saved path: ${playlistFile.path}');
    // Parse the playlist file.
    final playList = await HlsPlaylistParser.create().parseString(playlistFile.uri, await playlistFile.readAsString());
    playList as HlsMediaPlaylist;
    ///then need video base url
    String videoBaseUrl = playListDownloadUrl.replaceAll('/video.m3u8', '');
    log('log videoBaseUrl replace url $videoBaseUrl');

    // Download the video segments or .ts file in parallel.
    final futures = <Future<void>>[];
    for (var segment in playList.segments) {
      final segmentFile = File('${appStorage.path}/$folderName/${segment.url}');
      log('log ts url $videoBaseUrl/${segment.url}');
      futures.add(dio.download('$videoBaseUrl/${segment.url}', segmentFile.path,
          options: Options(
            responseType: ResponseType.bytes,
          )));
    }

    // Wait for all of the downloads to complete.ß
    await Future.wait(futures);

    // Show a snack-bar message to indicate that the download is complete.

  }

  String getHighestRegulation(String text){
    RegExp exp = RegExp(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+');
    Iterable<RegExpMatch> matches = exp.allMatches(text);
    String lastMatch = text.substring(matches.last.start, matches.last.end);
    return lastMatch;
  }

But this code only work on android platform!