[archi] base archi dl

This commit is contained in:
jscampucci 2024-06-14 10:41:27 +02:00
parent 080488c8a2
commit 709eb82fe4
5 changed files with 177 additions and 33 deletions

1
.gitignore vendored
View File

@ -30,6 +30,7 @@ migrate_working_dir/
.pub-cache/
.pub/
/build/
temp/
# Symbolication related
app.*.symbols

25
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,25 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "notube",
"request": "launch",
"type": "dart"
},
{
"name": "notube (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "notube (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release"
}
]
}

32
lib/models/Video.dart Normal file
View File

@ -0,0 +1,32 @@
import 'dart:developer' as developer;
class Video {
String id;
String title;
String thumbnail;
String description;
String duration;
String uploader;
String uploadDate;
Video({
required this.id,
required this.title,
this.thumbnail = '',
this.description = '',
this.duration = '0:00',
required this.uploader,
required this.uploadDate,
});
factory Video.fromJson(Map<String, dynamic> json) {
return Video(
id: json['id'],
title: json['title'],
thumbnail: json['thumbnails']![0]['url'],
description: json['description'] ?? '',
duration: json['duration_string'] ?? '0:00',
uploader: json['uploader'] ?? '',
uploadDate: json['upload_date'] ?? '');
}
}

112
lib/services/download.dart Normal file
View File

@ -0,0 +1,112 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:notube/models/Video.dart';
import 'package:notube/states/dlFormState.dart';
import 'package:path_provider/path_provider.dart';
import 'package:process_run/shell.dart';
import 'package:provider/provider.dart';
import 'dart:developer';
class DLServices {
late Directory tempDir;
late String assetName;
late String ytDlpPath;
String extractor = '';
String url = '';
bool isPlaylist = false;
String playlistTitle = '';
List<Video> videos = [];
DLServices._();
static Future<DLServices> init() async {
debugPrint('Initializing DLServices');
var dlService = DLServices._();
await dlService._init();
return dlService;
}
Future<void> _init() async {
tempDir = await getTemporaryDirectory();
assetName = 'yt-dlp.exe';
await copyExecutable();
}
Future<void> copyExecutable() async {
File tempFile = File('${tempDir.path}/$assetName');
ByteData data = await rootBundle.load('assets/executable/$assetName');
await tempFile.exists().then((value) {
if (!value) {
debugPrint('Copying $assetName to ${tempFile.path}');
tempFile.writeAsBytes(
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
});
ytDlpPath = tempFile.path;
}
Future<void> downloadFile(String url, String format) async {
debugPrint('Downloading $url in $format format');
/*
https://youtu.be/playlist?list=PLk1fi9OrZmvGBdh9BdWIhZImGVDUqls1X
*/
var command =
'${url.trim()} --sub-langs "all,-live_chat" --embed-subs --embed-thumbnail --embed-metadata --windows-filenames --progress -o "temp/%(playlist)s/%(title)s"';
var shellLinesController = ShellLinesController();
var shell = Shell(stdout: shellLinesController.sink);
shellLinesController.stream.listen((line) {
if (line.contains('[download]')) {
debugPrint('___Download___');
debugPrint('%=${line.split('[download]')[1].split(' of')[0].trim()}');
debugPrint('______');
}
debugPrint(line);
});
debugPrint('Running $ytDlpPath $command');
await shell.run('''
$ytDlpPath $command
''');
}
Future<void> analyseUrl(String url) async {
debugPrint('Analyse $url');
var command = '${url.trim()} -q --flat-playlist -J';
var shellLinesController = ShellLinesController();
var shell = Shell(stdout: shellLinesController.sink);
shellLinesController.stream.listen((line) {
if (line[0] == '{') {
var dataInfos = jsonDecode(line);
extractor = dataInfos['extractor_key'];
isPlaylist = dataInfos['_type'] == 'playlist';
if (isPlaylist) {
playlistTitle = dataInfos['title'];
for (var video in dataInfos['entries']) {
videos.add(Video.fromJson(video));
}
} else {
videos.add(Video.fromJson(dataInfos));
}
}
});
await shell.run('''
$ytDlpPath $command
''');
}
}

View File

@ -1,14 +1,13 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:process_run/shell.dart';
import 'package:notube/services/download.dart';
class DlFormState extends ChangeNotifier {
String url = '';
String url =
'https://youtu.be/playlist?list=PLk1fi9OrZmvGBdh9BdWIhZImGVDUqls1X';
String format = 'MP3';
late DLServices dlService;
void setUrl(String newUrl) {
url = newUrl;
notifyListeners();
@ -20,32 +19,7 @@ class DlFormState extends ChangeNotifier {
}
Future<void> download() async {
debugPrint('Downloading $url in $format format');
Directory tempDir = await getTemporaryDirectory();
String assetName = 'yt-dlp.exe';
File tempFile = File('${tempDir.path}/$assetName');
ByteData data = await rootBundle.load('assets/executable/$assetName');
await tempFile.exists().then((value) {
if (!value) {
debugPrint('Copying $assetName to ${tempFile.path}');
tempFile.writeAsBytes(
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
});
var ytDlpPath = tempFile.path;
var command =
'${url.trim()} --sub-langs "all,-live_chat" --embed-subs --embed-thumbnail --embed-metadata --output temp.mp4';
var shell = Shell();
debugPrint('Running $ytDlpPath $command');
var results = await shell.run('''
dir
$ytDlpPath $command
''');
dlService = await DLServices.init();
await dlService.analyseUrl(url);
}
}