download method
Implementation
Stream download({
required Directory directoryDownload,
required Directory directoryTemporary,
required String youtubeUrl,
required String? output,
required bool isAudioOnly,
required YoutubeVideoDownloadDetail youtubeVideoDownloadDetail,
}) async* {
final video = await youtubeExplode.videos.get(youtubeUrl);
final streamManifest = youtubeVideoDownloadDetail.streamManifest;
final fileName = '${video.title}'
.replaceAll(r'\', '')
.replaceAll('/', '')
.replaceAll('*', '')
.replaceAll('?', '')
.replaceAll('"', '')
.replaceAll('<', '')
.replaceAll('>', '')
.replaceAll(':', '')
.replaceAll('|', '');
final File fileOutput = File(path.join(
directoryDownload.path,
(output ??
"${((isAudioOnly == true) ? "${video.author}-${fileName}.mp3" : "${fileName}.mp4")}")
.replaceAll(RegExp("([ ]+)"), "_"),
));
final List<File> files = [];
if (isAudioOnly == false) {
{
final streams = streamManifest.videoOnly;
final videoStreamInfo = streams.withHighestBitrate();
final videoStream =
youtubeExplode.videos.streamsClient.get(videoStreamInfo);
final file = File(path.join(directoryTemporary.path,
'${fileName}.video.${videoStreamInfo.container.name}'));
// Track the file download status.
final len = videoStreamInfo.size.totalBytes;
if (file.statSync().size != len) {
if (file.existsSync()) {
file.deleteSync(recursive: true);
}
await file.create(recursive: true);
// Open the file in writeAppend.
final output = file.openWrite(mode: FileMode.writeOnlyAppend);
int count = file.statSync().size;
// Create the message and set the cursor position.
final msg =
'Downloading ${video.title}.${videoStreamInfo.container.name}';
stdout.writeln(msg);
// Listen for data received.
await for (final data in videoStream) {
// Keep track of the current downloaded data.
count += data.length;
// Calculate the current progress.
final progress = ((count / len) * 100).ceil();
print(progress.toStringAsFixed(2));
// Write to file.
output.add(data);
}
await output.close();
}
files.add(file);
}
}
{
final streams = streamManifest.audioOnly;
// Get the audio track with the highest bitrate.
final audio = streams.withHighestBitrate();
final audioStream = youtubeExplode.videos.streamsClient.get(audio);
final file = File(path.join(directoryTemporary.path,
'${fileName}.audio.${audio.container.name}'));
// Track the file download status.
final len = audio.size.totalBytes;
if (file.statSync().size != len) {
await file.create(recursive: true);
// Open the file in writeAppend.
final output = file.openWrite(mode: FileMode.writeOnlyAppend);
var count = file.statSync().size;
// Create the message and set the cursor position.
final msg = 'Downloading ${video.title}.${audio.container.name}';
stdout.writeln(msg);
// Listen for data received.
await for (final data in audioStream) {
// Keep track of the current downloaded data.
count += data.length;
// Calculate the current progress.
final progress = ((count / len) * 100).ceil();
print(progress.toStringAsFixed(2));
// Write to file.
output.add(data);
}
await output.close();
}
files.add(file);
}
final Process process = await Process.start(
"ffmpeg",
[
if (isAudioOnly) ...[
"-i",
files.first.path,
"-vn",
"-ar",
"44100",
"-ac",
"2",
"-b:a",
"192k",
fileOutput.path,
] else ...[
"-i",
files.first.path,
"-i",
files.last.path,
"-c:v",
"copy",
"-c:a",
"aac",
"-map",
"0:v:0",
"-map",
"1:a:0",
fileOutput.path,
],
],
);
process.stdout.listen(stdout.add);
process.stderr.listen(stderr.add);
final exitCode = await process.exitCode;
if (exitCode == 0) {
for (final file in files) {
await file.delete(recursive: true);
}
}
return;
}