zoukankan      html  css  js  c++  java
  • 下载m3u8视频

    使用ffmpeg直接下载

    ffmpeg -i "http://host/folder/file.m3u8" -bsf:a aac_adtstoasc -c copy -crf 50 file.mp4
    

    手动解析下载

    有些m3u8可能不一样

    import 'dart:io';
    
    import 'package:process_run/shell.dart';
    import 'package:ajanuw_http/ajanuw_http.dart';
    import 'package:path/path.dart' as path;
    
    var urlBase = 'https://www.gentaji.com/20200205/2J8Ij9tS/index.m3u8';
    
    var __filename = Platform.script.path.replaceFirst('/', '');
    var __dirname = path.dirname(__filename);
    
    var download_path = path.normalize(path.joinAll([__dirname, '..', 'download']));
    
    void download(String url) async {
      // 获取第一层M3U8文件内容
      var all_content = (await url.get()).body;
      if (!all_content.contains('#EXTM3U')) {
        throw ('非M3U8的链接');
      }
    
      if (all_content.contains('EXT-X-STREAM-INF')) {
        var file_line = all_content.split('
    ');
    
        for (var line in file_line) {
          if (line.contains('.m3u8')) {
            url = Uri.parse(url).replace(path: line).toString(); // 拼出第二层m3u8的URL
            all_content = (await url.get()).body;
          }
        }
      }
    
      var file_line = all_content.split('
    ');
      var unknow = true;
    
      var total = file_line.length;
      for (var i = 0; i < total; i++) {
        var line = file_line[i];
        if (line.contains('#EXT-X-KEY')) {
          print('找解密Key');
        }
    
        if (line.contains('EXTINF')) {
          unknow = false;
          var pd_url = file_line[i + 1]; // https://gentaji.com/20200205/2J8Ij9tS/1200kb/hls/0o8RU9r8.ts
          if (pd_url != null && Uri.parse(pd_url).scheme.isNotEmpty) {
            var c_fule_name = '$i-${path.basename(pd_url)}'; // 0o8RU9r8.ts
            var f = File(path.join(download_path, c_fule_name));
            if (!await f.exists()) {
              print('index: $i total: $total');
              var res = await pd_url.get();
              await f.writeAsBytes(res.bodyBytes);
            } else {
              print(f.path + ' 文件已经存在!');
            }
          } else {
            print('下载连接错误: ' + pd_url);
          }
        }
      }
    
      if (unknow) {
        throw '未找到对应的下载链接';
      } else {
        print('下载完成');
      }
    
      merge_file();
    }
    
    void merge_file() async {
      // sh: cd <download_path>
      // 改变工作目录
      Directory.current = Directory(download_path);
      var shell = Shell();
    
      // 将按顺序把每个文件内容push到new.tmp
      // 可能会合并错误
      await shell.run('''copy /b * new.m3u8''');
      // await shell.run('''del /Q *.ts''');
      // await shell.run('''del /Q *.mp4''');
      // await File('new.m3u8').rename('new.mp4');
    
      // 使用ffmpeg工具将合并的ts文件,解码为mp4文件,上面通过直接改变后缀名的方法貌似不行
      await shell.run('''ffmpeg -i new.m3u8 -bsf:a aac_adtstoasc -c copy -crf 50 video.mp4''');
    
      // 和上面的一样
      // await shell.run('''ffmpeg -i new.m3u8 -b:v 0 -crf 25 -f mp4 -vcodec libx264 -pix_fmt yuv420p video.mp4''');
    }
    
    void main() async {
      var dowloadDir = Directory(download_path);
      if (!await dowloadDir.exists()) {
        await dowloadDir.create();
      }
    
      download(urlBase);
    }
    
  • 相关阅读:
    订餐系统
    throw和throws
    CF999E Solution
    CF1142B Solution
    CF965C Solution
    CF963B Solution
    CF999F Solution
    CF975D Solution
    CF997B Solution
    hdu 2553 N皇后
  • 原文地址:https://www.cnblogs.com/ajanuw/p/12564036.html
Copyright © 2011-2022 走看看