下载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('\n');

    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('\n');
  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);
}
posted @ 2020-03-25 09:28  Ajanuw  阅读(1124)  评论(0编辑  收藏  举报