mirror of
https://github.com/timendum/Youtube-dl-WebUI.git
synced 2024-09-20 06:46:10 +08:00
Simultaneous downloads !
Better error management Musics are now dissociate from videos
This commit is contained in:
parent
5e17a6e8bf
commit
bdd3bc126c
|
@ -4,13 +4,16 @@
|
|||
![List](https://github.com/p1rox/Youtube-dl-WebUI/raw/master/img/list.png)
|
||||
|
||||
## Description
|
||||
Youtube-dl WebUI is a small web interface for youtube-dl. It allows you to host your own video downloader. After the download you can stream your videos from your web browser or save it on your computer directly from the list page.
|
||||
Youtube-dl WebUI is a small web interface for youtube-dl. It allows you to host your own video downloader.
|
||||
After the download you can stream your videos from your web browser or save it on your computer directly from the list page.
|
||||
It supports simultaneous downloads in background.
|
||||
|
||||
### You can now extract the audio of a video and download multiple videos at the same time !
|
||||
|
||||
## Requirements
|
||||
- A web server (Apache or nginx)
|
||||
- PHP latest version should be fine.
|
||||
- Python 2.7 for Youtube-dl
|
||||
- [Youtube-dl](https://github.com/rg3/youtube-dl)
|
||||
- avconv or other is required for audio extraction (from youtube-dl doc) :
|
||||
`-x, --extract-audio convert video files to audio-only files (requires ffmpeg or avconv and ffprobe or avprobe)`
|
||||
|
|
|
@ -5,6 +5,7 @@ class Downloader
|
|||
private $urls = [];
|
||||
private $config = [];
|
||||
private $audio_only = false;
|
||||
private $errors = [];
|
||||
|
||||
public function __construct($post, $audio_only)
|
||||
{
|
||||
|
@ -13,23 +14,60 @@ class Downloader
|
|||
|
||||
if($this->is_installed() != 0)
|
||||
{
|
||||
die("youtube-dl is not installed !");
|
||||
$errors[] = "Youtube-dl is not installed, see <a>https://rg3.github.io/youtube-dl/download.html</a> !";
|
||||
}
|
||||
|
||||
if(!$this->outuput_folder_exists())
|
||||
{
|
||||
die("Output folder doesn't exist !");
|
||||
$errors[] = "Output folder doesn't exist !";
|
||||
}
|
||||
|
||||
if($this->is_extracter_installed())
|
||||
if($audio_only && $this->is_extracter_installed())
|
||||
{
|
||||
die("Install and configure an extracter !");
|
||||
$errors[] = "Install an audio extracter (ex: avconv) !";
|
||||
}
|
||||
|
||||
if(isset($errors) && count($errors) > 0)
|
||||
{
|
||||
$_SESSION['errors'] = $errors;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->urls = explode(",", $post);
|
||||
|
||||
if($this->config["max_dl"] == 0)
|
||||
{
|
||||
$this->do_download();
|
||||
}
|
||||
elseif($this->config["max_dl"] > 0)
|
||||
{
|
||||
if($this->background_jobs() >= 0 && $this->background_jobs() < $this->config["max_dl"])
|
||||
{
|
||||
$this->do_download();
|
||||
}
|
||||
else
|
||||
{
|
||||
$errors[] = "Simultaneous downloads limit reached !";
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($errors) && count($errors) > 0)
|
||||
{
|
||||
$_SESSION['errors'] = $errors;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static function background_jobs()
|
||||
{
|
||||
return shell_exec("ps aux | grep -v grep | grep youtube-dl | wc -l");
|
||||
}
|
||||
|
||||
public static function max_jobs()
|
||||
{
|
||||
$config = require dirname(__DIR__).'/config/config.php';
|
||||
return $config["max_dl"];
|
||||
}
|
||||
|
||||
private function is_installed()
|
||||
{
|
||||
|
@ -65,23 +103,23 @@ class Downloader
|
|||
private function do_download()
|
||||
{
|
||||
$cmd = "youtube-dl";
|
||||
$cmd .= ' -o '.$this->config["outputFolder"].'/';
|
||||
$cmd .= escapeshellarg('%(title)s-%(uploader)s.%(ext)s');
|
||||
$cmd .= " -o ".$this->config["outputFolder"]."/";
|
||||
$cmd .= escapeshellarg("%(title)s-%(uploader)s.%(ext)s");
|
||||
|
||||
if($this->audio_only)
|
||||
{
|
||||
$cmd .= ' -x ';
|
||||
$cmd .= " -x ";
|
||||
}
|
||||
|
||||
foreach($this->urls as $url)
|
||||
{
|
||||
$cmd .= ' '.$url;
|
||||
$cmd .= " ".$url;
|
||||
}
|
||||
|
||||
$cmd .= ' --restrict-filenames'; // --restrict-filenames is for specials chars
|
||||
$cmd .= ' 2>&1';
|
||||
$cmd .= " --restrict-filenames"; // --restrict-filenames is for specials chars
|
||||
$cmd .= " > /dev/null & echo $!";
|
||||
|
||||
exec($cmd, $out, $ret);
|
||||
shell_exec($cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<?php
|
||||
|
||||
class VideoHandler
|
||||
class FileHandler
|
||||
{
|
||||
private $config = [];
|
||||
private $videos_ext = ".{avi,mp4,flv}";
|
||||
private $musics_ext = ".{mp3,ogg}";
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +20,7 @@ class VideoHandler
|
|||
|
||||
$folder = dirname(__DIR__).'/'.$this->config["outputFolder"].'/';
|
||||
|
||||
foreach(glob($folder.'*') as $file)
|
||||
foreach(glob($folder.'*'.$this->videos_ext, GLOB_BRACE) as $file)
|
||||
{
|
||||
$video = [];
|
||||
$video["name"] = str_replace($folder, "", $file);
|
||||
|
@ -30,12 +32,46 @@ class VideoHandler
|
|||
return $videos;
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
public function listMusics()
|
||||
{
|
||||
$musics = [];
|
||||
|
||||
if(!$this->outuput_folder_exists())
|
||||
return;
|
||||
|
||||
$folder = dirname(__DIR__).'/'.$this->config["outputFolder"].'/';
|
||||
|
||||
foreach(glob($folder.'*'.$this->musics_ext, GLOB_BRACE) as $file)
|
||||
{
|
||||
$music = [];
|
||||
$music["name"] = str_replace($folder, "", $file);
|
||||
$music["size"] = $this->to_human_filesize(filesize($file));
|
||||
|
||||
$musics[] = $music;
|
||||
}
|
||||
|
||||
return $musics;
|
||||
}
|
||||
|
||||
public function delete($id, $type)
|
||||
{
|
||||
$folder = dirname(__DIR__).'/'.$this->config["outputFolder"].'/';
|
||||
$i = 0;
|
||||
|
||||
foreach(glob($folder.'*') as $file)
|
||||
if($type === 'v')
|
||||
{
|
||||
$exts = $this->videos_ext;
|
||||
}
|
||||
elseif($type === 'm')
|
||||
{
|
||||
$exts = $this->musics_ext;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach(glob($folder.'*'.$exts, GLOB_BRACE) as $file)
|
||||
{
|
||||
if($i == $id)
|
||||
{
|
||||
|
@ -71,7 +107,7 @@ class VideoHandler
|
|||
return $this->to_human_filesize(disk_free_space($this->config["outputFolder"]));
|
||||
}
|
||||
|
||||
public function get_video_folder()
|
||||
public function get_downloads_folder()
|
||||
{
|
||||
return $this->config["outputFolder"];
|
||||
}
|
|
@ -5,7 +5,8 @@
|
|||
return array(
|
||||
"security" => true,
|
||||
"password" => "63a9f0ea7bb98050796b649e85481845",
|
||||
"outputFolder" => "videos",
|
||||
"extracter" => "avconv");
|
||||
"outputFolder" => "downloads",
|
||||
"extracter" => "avconv",
|
||||
"max_dl" => 3);
|
||||
|
||||
?>
|
36
index.php
36
index.php
|
@ -1,10 +1,10 @@
|
|||
<?php
|
||||
require 'class/Session.php';
|
||||
require 'class/VideoHandler.php';
|
||||
require 'class/FileHandler.php';
|
||||
require 'class/Downloader.php';
|
||||
|
||||
$session = Session::getInstance();
|
||||
$video = new VideoHandler;
|
||||
$file = new FileHandler;
|
||||
|
||||
if(!$session->is_logged_in())
|
||||
{
|
||||
|
@ -22,14 +22,38 @@
|
|||
}
|
||||
|
||||
$downloader = new Downloader($_POST['urls'], $audio_only);
|
||||
header("Location: list.php");
|
||||
|
||||
if(!isset($_SESSION['errors']))
|
||||
{
|
||||
if($audio_only)
|
||||
{
|
||||
header("Location: list.php?type=m");
|
||||
}
|
||||
else
|
||||
{
|
||||
header("Location: list.php?type=v");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require 'views/header.php';
|
||||
?>
|
||||
<div class="container">
|
||||
<br>
|
||||
<br>
|
||||
<h1>Download</h1>
|
||||
<?php
|
||||
|
||||
if(isset($_SESSION['errors']) && $_SESSION['errors'] > 0)
|
||||
{
|
||||
foreach ($_SESSION['errors'] as $e)
|
||||
{
|
||||
echo "<div class=\"alert alert-warning\" role=\"alert\">$e</div>";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<form id="download-form" class="form-horizontal" action="index.php" method="post">
|
||||
<div class="form-group">
|
||||
<div class="col-md-10">
|
||||
|
@ -51,8 +75,9 @@
|
|||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">Info</h3></div>
|
||||
<div class="panel-body">
|
||||
<p>Free space : <?php echo $video->free_space(); ?></b></p>
|
||||
<p>Download folder : <?php echo $video->get_video_folder(); ?></p>
|
||||
<p><b>Background downloads : <?php echo Downloader::background_jobs()." / ".Downloader::max_jobs() ?> </b></p>
|
||||
<p>Free space : <?php echo $file->free_space(); ?></b></p>
|
||||
<p>Download folder : <?php echo $file->get_downloads_folder(); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -72,5 +97,6 @@
|
|||
</div>
|
||||
</div>
|
||||
<?php
|
||||
unset($_SESSION['errors']);
|
||||
require 'views/footer.php';
|
||||
?>
|
48
list.php
48
list.php
|
@ -1,31 +1,46 @@
|
|||
<?php
|
||||
require 'class/Session.php';
|
||||
require 'class/VideoHandler.php';
|
||||
require 'class/FileHandler.php';
|
||||
|
||||
$session = Session::getInstance();
|
||||
$video = new VideoHandler;
|
||||
$file = new FileHandler;
|
||||
|
||||
if(!$session->is_logged_in())
|
||||
{
|
||||
header("Location: login.php");
|
||||
}
|
||||
|
||||
if(isset($_GET['type']) && !empty($_GET['type']))
|
||||
{
|
||||
$t = $_GET['type'];
|
||||
if($t === 'v')
|
||||
{
|
||||
$type = "videos";
|
||||
$files = $file->listVideos();
|
||||
}
|
||||
elseif($t === 'm')
|
||||
{
|
||||
$type = "musics";
|
||||
$files = $file->listMusics();
|
||||
}
|
||||
}
|
||||
|
||||
if($session->is_logged_in() && isset($_GET["delete"]))
|
||||
{
|
||||
$video->delete($_GET["delete"]);
|
||||
header("Location: list.php");
|
||||
$file->delete($_GET["delete"], $t);
|
||||
header("Location: list.php?type=".$t);
|
||||
}
|
||||
|
||||
require 'views/header.php';
|
||||
?>
|
||||
<div class="container">
|
||||
<h2>List of available videos :</h2>
|
||||
<br>
|
||||
<br>
|
||||
<?php
|
||||
$videos = $video->listVideos();
|
||||
|
||||
if(!empty($videos))
|
||||
if(!empty($files))
|
||||
{
|
||||
?>
|
||||
<h2>List of available <?php echo $type ?> :</h2>
|
||||
<table class="table table-striped table-hover ">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -39,12 +54,12 @@
|
|||
$i = 0;
|
||||
$totalSize = 0;
|
||||
|
||||
foreach($videos as $v)
|
||||
foreach($files as $f)
|
||||
{
|
||||
echo "<tr>";
|
||||
echo "<td><a href=\"".$video->get_video_folder().'/'.$v["name"]."\" download>".$v["name"]."</a></td>";
|
||||
echo "<td>".$v["size"]."</td>";
|
||||
echo "<td><a href=\"./list.php?delete=$i\" class=\"btn btn-danger btn-sm\">Delete</a></td>";
|
||||
echo "<td><a href=\"".$file->get_downloads_folder().'/'.$f["name"]."\" download>".$f["name"]."</a></td>";
|
||||
echo "<td>".$f["size"]."</td>";
|
||||
echo "<td><a href=\"./list.php?delete=$i&type=$t\" class=\"btn btn-danger btn-sm\">Delete</a></td>";
|
||||
echo "</tr>";
|
||||
$i++;
|
||||
}
|
||||
|
@ -55,7 +70,14 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
echo "<br><div class=\"alert alert-warning\" role=\"alert\">No videos !</div>";
|
||||
if(isset($t) && ($t === 'v' || $t === 'm'))
|
||||
{
|
||||
echo "<br><div class=\"alert alert-warning\" role=\"alert\">No $type !</div>";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<br><div class=\"alert alert-warning\" role=\"alert\">No such type !</div>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
<br/>
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
<div class="navbar-collapse collapse navbar-responsive-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="./">Download</a></li>
|
||||
<li><a href="./list.php">List of videos</a></li>
|
||||
<li><a href="./list.php?type=v">List of videos</a></li>
|
||||
<li><a href="./list.php?type=m">List of musics</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<?php
|
||||
|
|
Loading…
Reference in a new issue