下载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);
}