diff --git a/.htaccess b/.htaccess index 8fc5b69..8ccd69c 100644 --- a/.htaccess +++ b/.htaccess @@ -24,4 +24,4 @@ RewriteRule ^ index.php [QSA,L] Redirect permanent /api.php /video Redirect permanent /extractors.php /extractors -AddOutputFilterByType DEFLATE text/css text/html application/javascript +AddOutputFilterByType DEFLATE text/css text/html application/javascript font/truetype diff --git a/FAQ.md b/FAQ.md index 52c7ed6..1bfb336 100644 --- a/FAQ.md +++ b/FAQ.md @@ -1,12 +1,17 @@ # Frequently asked questions + + ## My browser plays the video. How do I download it? + Most recent browsers automatically play a video if it is a format they know how to play. You can ususally download the video by doing *File > Save to* or *ctrl + S*. ## How do I change config parameters? + You need to create a YAML file called `config.yml` at the root of your project. Here are the parameters that you can set: + * youtubedl: path to your youtube-dl binary * python: path to your python binary * params: an array of parameters to pass to youtube-dl @@ -18,12 +23,35 @@ Here are the parameters that you can set: See [config.example.yml](config.example.yml) for default values. ## How do I enable audio conversion? + In order to enable audio conversion, you need to add this to your `config.yml` file: + ```yaml convert: true avconv: path/to/avconv ``` + You will also need to install `avconv` and `curl` on your server: + ```bash sudo apt-get install libav-tools curl ``` + +## How do I deploy Alltube on Heroku? + +Create a dyno with the following buildpacks: + +* `heroku/php` +* `https://github.com/heroku/heroku-buildpack-nodejs` + +Then push the code to Heroku and it should work out of the box. + +## Why can't I download videos from some websites (e.g. Dailymotion) + +Some websites generate an unique video URL for each IP address. When using Alltube, the URL is generated for our server's IP address and your computer is not allowed to use it. + +There are two known workarounds: + +* You can run Alltube locally on your computer. +* You can use the experimental `feature/stream` branch which streams the video through the server in order to bypass IP restrictions. + Please note that this can use a lot of resources on the server (which is why we won't enable it on alltubedownload.net). diff --git a/README.md b/README.md index 483b269..63fea97 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,21 @@ -Alltube Download -======= +# Alltube Download -HTML GUI for youtube-dl (http://alltubedownload.net/) +HTML GUI for youtube-dl ([alltubedownload.net](http://alltubedownload.net/)) ![Screenshot](img/screenshot.png "Alltube GUI screenshot") ## Setup ### From a release package + You can download the latest release package [here](https://github.com/Rudloff/alltube/releases). You just have to unzip it on your server and it should be ready to use. ### From Git + In order to get AllTube working, you need to use [npm](https://www.npmjs.com/) and [Composer](https://getcomposer.org/): + ```bash npm install composer install @@ -24,6 +26,7 @@ This will download all the required dependencies. (Note that it will download the ffmpeg binary for 64-bits Linux. If you are on another platform, you might want to specify the path to avconv/ffmpeg in your config file.) You should also ensure that the *templates_c* folder has the right permissions: + ```bash chmod 777 templates_c/ ``` @@ -33,19 +36,33 @@ If your web server is Apache, you need to set the `AllowOverride` setting to `Al ## Config If you want to use a custom config, you need to create a config file: + ```bash cp config.example.yml config.yml ``` +## PHP requirements + +You will need PHP 5.5 (or higher) and the following PHP modules: + +* fileinfo +* intl +* mbstring +* curl + ## Web server configuration + ### Apache + You will need the following modules: * mod_mime * mod_rewrite ### Nginx + Here is an exemple Nginx configuration: + ```nginx server { server_name localhost; @@ -94,16 +111,24 @@ server { ``` ## License + This software is available under the [GNU General Public License](http://www.gnu.org/licenses/gpl.html). -__Please use a different name and logo if you run it on a public server.__ +Please __use a different name and logo__ if you run it on a public server. ## Other dependencies + You need [avconv](https://libav.org/avconv.html), [rtmpdump](http://rtmpdump.mplayerhq.hu/) and [curl](https://curl.haxx.se/) in order to enable conversions. -If you don't want to enable conversions, you can disable it in *config.yml*. +If you don't want to enable conversions, you can disable it in `config.yml`. On Debian-based systems: + ```bash sudo apt-get install libav-tools rtmpdump curl ``` -You also probably need to edit the *avconv* variable in *config.yml* so that it points to your ffmpeg/avconv binary (*/usr/bin/avconv* on Debian/Ubuntu). + +You also probably need to edit the `avconv` variable in `config.yml` so that it points to your ffmpeg/avconv binary (`/usr/bin/avconv` on Debian/Ubuntu). + +## FAQ + +Please read the [FAQ](FAQ.md) before reporting any issue. diff --git a/classes/Config.php b/classes/Config.php index 208e85b..674717b 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -100,7 +100,7 @@ class Config } } if (getenv('CONVERT')) { - $this->convert = getenv('CONVERT'); + $this->convert = (bool) getenv('CONVERT'); } } diff --git a/classes/VideoDownload.php b/classes/VideoDownload.php index e497113..39fa401 100644 --- a/classes/VideoDownload.php +++ b/classes/VideoDownload.php @@ -12,6 +12,9 @@ use Symfony\Component\Process\ProcessBuilder; */ class VideoDownload { + private $config; + private $procBuilder; + /** * VideoDownload constructor. */ @@ -45,47 +48,11 @@ class VideoDownload return explode(PHP_EOL, trim($process->getOutput())); } - /** - * Get all information about a video. - * - * @param string $url URL of page - * @param string $format Format to use for the video - * - * @return object Decoded JSON - * */ - public function getJSON($url, $format = null) + private function getProp($url, $format = null, $prop = 'dump-json') { $this->procBuilder->setArguments( [ - '--dump-json', - $url, - ] - ); - if (isset($format)) { - $this->procBuilder->add('-f '.$format); - } - $process = $this->procBuilder->getProcess(); - $process->run(); - if (!$process->isSuccessful()) { - throw new \Exception($process->getErrorOutput()); - } else { - return json_decode($process->getOutput()); - } - } - - /** - * Get URL of video from URL of page. - * - * @param string $url URL of page - * @param string $format Format to use for the video - * - * @return string URL of video - * */ - public function getURL($url, $format = null) - { - $this->procBuilder->setArguments( - [ - '--get-url', + '--'.$prop, $url, ] ); @@ -101,6 +68,32 @@ class VideoDownload } } + /** + * Get all information about a video. + * + * @param string $url URL of page + * @param string $format Format to use for the video + * + * @return object Decoded JSON + * */ + public function getJSON($url, $format = null) + { + return json_decode($this->getProp($url, $format, 'dump-json')); + } + + /** + * Get URL of video from URL of page. + * + * @param string $url URL of page + * @param string $format Format to use for the video + * + * @return string URL of video + * */ + public function getURL($url, $format = null) + { + return $this->getProp($url, $format, 'get-url'); + } + /** * Get filename of video file from URL of page. * @@ -111,22 +104,7 @@ class VideoDownload * */ public function getFilename($url, $format = null) { - $this->procBuilder->setArguments( - [ - '--get-filename', - $url, - ] - ); - if (isset($format)) { - $this->procBuilder->add('-f '.$format); - } - $process = $this->procBuilder->getProcess(); - $process->run(); - if (!$process->isSuccessful()) { - throw new \Exception($process->getErrorOutput()); - } else { - return trim($process->getOutput()); - } + return trim($this->getProp($url, $format, 'get-filename')); } /** diff --git a/composer.json b/composer.json index 5b7d99f..d8bb080 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ }, "require-dev": { "symfony/var-dumper": "~3.1.0", - "squizlabs/php_codesniffer": "~2.6.2", + "squizlabs/php_codesniffer": "~2.7.0", "phpunit/phpunit": "~5.5.2" }, "extra": { diff --git a/composer.lock b/composer.lock index 6e7e42d..fbba819 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "086ca596eeeb4c2a0e5d27976b21e4d2", - "content-hash": "ec541955f4eb561e1b37b3bbb081af09", + "hash": "619ed10d49b90725061dfd851d994432", + "content-hash": "dac044b232222cd1af6f62f3ad24d231", "packages": [ { "name": "container-interop/container-interop", @@ -50,16 +50,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "6.2.1", + "version": "6.2.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" + "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", - "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ebf29dee597f02f09f4d5bbecc68230ea9b08f60", + "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60", "shasum": "" }, "require": { @@ -108,7 +108,7 @@ "rest", "web service" ], - "time": "2016-07-15 17:22:37" + "time": "2016-10-08 15:01:37" }, { "name": "guzzlehttp/promises", @@ -776,16 +776,16 @@ }, { "name": "symfony/process", - "version": "v3.1.4", + "version": "v3.1.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "e64e93041c80e77197ace5ab9385dedb5a143697" + "reference": "66de154ae86b1a07001da9fbffd620206e4faf94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/e64e93041c80e77197ace5ab9385dedb5a143697", - "reference": "e64e93041c80e77197ace5ab9385dedb5a143697", + "url": "https://api.github.com/repos/symfony/process/zipball/66de154ae86b1a07001da9fbffd620206e4faf94", + "reference": "66de154ae86b1a07001da9fbffd620206e4faf94", "shasum": "" }, "require": { @@ -821,20 +821,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-08-16 14:58:24" + "time": "2016-09-29 14:13:09" }, { "name": "symfony/yaml", - "version": "v3.1.4", + "version": "v3.1.5", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "f291ed25eb1435bddbe8a96caaef16469c2a092d" + "reference": "368b9738d4033c8b93454cb0dbd45d305135a6d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/f291ed25eb1435bddbe8a96caaef16469c2a092d", - "reference": "f291ed25eb1435bddbe8a96caaef16469c2a092d", + "url": "https://api.github.com/repos/symfony/yaml/zipball/368b9738d4033c8b93454cb0dbd45d305135a6d3", + "reference": "368b9738d4033c8b93454cb0dbd45d305135a6d3", "shasum": "" }, "require": { @@ -870,7 +870,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-09-02 02:12:52" + "time": "2016-09-25 08:27:07" } ], "packages-dev": [ @@ -930,16 +930,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.5.2", + "version": "1.5.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "da8529775f14f4fdae33f916eb0cf65f6afbddbc" + "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/da8529775f14f4fdae33f916eb0cf65f6afbddbc", - "reference": "da8529775f14f4fdae33f916eb0cf65f6afbddbc", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/ea74994a3dc7f8d2f65a06009348f2d63c81e61f", + "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f", "shasum": "" }, "require": { @@ -968,7 +968,7 @@ "object", "object graph" ], - "time": "2016-09-06 16:07:05" + "time": "2016-09-16 13:37:59" }, { "name": "phpdocumentor/reflection-common", @@ -1026,16 +1026,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.1.0", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "9270140b940ff02e58ec577c237274e92cd40cdd" + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9270140b940ff02e58ec577c237274e92cd40cdd", - "reference": "9270140b940ff02e58ec577c237274e92cd40cdd", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", "shasum": "" }, "require": { @@ -1067,7 +1067,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-06-10 09:48:41" + "time": "2016-09-30 07:12:33" }, { "name": "phpdocumentor/type-resolver", @@ -1424,24 +1424,24 @@ }, { "name": "phpunit/phpunit", - "version": "5.5.4", + "version": "5.5.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3e6e88e56c912133de6e99b87728cca7ed70c5f5" + "reference": "3f67cee782c9abfaee5e32fd2f57cdd54bc257ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6e88e56c912133de6e99b87728cca7ed70c5f5", - "reference": "3e6e88e56c912133de6e99b87728cca7ed70c5f5", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3f67cee782c9abfaee5e32fd2f57cdd54bc257ba", + "reference": "3f67cee782c9abfaee5e32fd2f57cdd54bc257ba", "shasum": "" }, "require": { "ext-dom": "*", "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", "myclabs/deep-copy": "~1.3", "php": "^5.6 || ^7.0", "phpspec/prophecy": "^1.3.1", @@ -1463,7 +1463,12 @@ "conflict": { "phpdocumentor/reflection-docblock": "3.0.2" }, + "require-dev": { + "ext-pdo": "*" + }, "suggest": { + "ext-tidy": "*", + "ext-xdebug": "*", "phpunit/php-invoker": "~1.1" }, "bin": [ @@ -1498,20 +1503,20 @@ "testing", "xunit" ], - "time": "2016-08-26 07:11:44" + "time": "2016-10-03 13:04:15" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.2.7", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "546898a2c0c356ef2891b39dd7d07f5d82c8ed0a" + "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/546898a2c0c356ef2891b39dd7d07f5d82c8ed0a", - "reference": "546898a2c0c356ef2891b39dd7d07f5d82c8ed0a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", + "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", "shasum": "" }, "require": { @@ -1557,7 +1562,7 @@ "mock", "xunit" ], - "time": "2016-09-06 16:07:45" + "time": "2016-10-09 07:01:45" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -2074,16 +2079,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "2.6.2", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "4edb770cb853def6e60c93abb088ad5ac2010c83" + "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4edb770cb853def6e60c93abb088ad5ac2010c83", - "reference": "4edb770cb853def6e60c93abb088ad5ac2010c83", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", + "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", "shasum": "" }, "require": { @@ -2148,7 +2153,7 @@ "phpcs", "standards" ], - "time": "2016-07-13 23:29:13" + "time": "2016-09-01 23:53:02" }, { "name": "symfony/polyfill-mbstring", @@ -2211,16 +2216,16 @@ }, { "name": "symfony/var-dumper", - "version": "v3.1.4", + "version": "v3.1.5", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "62ee73706c421654a4c840028954510277f7dfc8" + "reference": "70bfe927b86ba9999aeebd829715b0bb2cd39a10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/62ee73706c421654a4c840028954510277f7dfc8", - "reference": "62ee73706c421654a4c840028954510277f7dfc8", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/70bfe927b86ba9999aeebd829715b0bb2cd39a10", + "reference": "70bfe927b86ba9999aeebd829715b0bb2cd39a10", "shasum": "" }, "require": { @@ -2270,7 +2275,7 @@ "debug", "dump" ], - "time": "2016-08-31 09:05:42" + "time": "2016-09-29 14:13:09" }, { "name": "webmozart/assert", diff --git a/controllers/FrontController.php b/controllers/FrontController.php index 2a4cdf5..a8322ef 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -6,6 +6,7 @@ namespace Alltube\Controller; use Alltube\Config; use Alltube\VideoDownload; +use Interop\Container\ContainerInterface; use Slim\Container; use Slim\Http\Request; use Slim\Http\Response; @@ -33,7 +34,7 @@ class FrontController /** * Slim dependency container. * - * @var Container + * @var ContainerInterface */ private $container; @@ -42,11 +43,13 @@ class FrontController * * @param Container $container Slim dependency container */ - public function __construct(Container $container) + public function __construct(ContainerInterface $container) { $this->config = Config::getInstance(); $this->download = new VideoDownload(); - $this->container = $container; + if ($container instanceof Container) { + $this->container = $container; + } } /** diff --git a/index.php b/index.php index 0653081..f9fdd7d 100644 --- a/index.php +++ b/index.php @@ -13,7 +13,10 @@ $container = $app->getContainer(); $container['view'] = function ($c) { $view = new \Slim\Views\Smarty(__DIR__.'/templates/'); - $view->addSlimPlugins($c['router'], $c['request']->getUri()); + $smartyPlugins = new \Slim\Views\SmartyPlugins($c['router'], $c['request']->getUri()); + $view->registerPlugin('function', 'path_for', [$smartyPlugins, 'pathFor']); + $view->registerPlugin('function', 'base_url', [$smartyPlugins, 'baseUrl']); + $view->registerPlugin('modifier', 'noscheme', 'Smarty_Modifier_noscheme'); diff --git a/package.json b/package.json index fcaf214..eb8b13b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "alltube", "description": "HTML GUI for youtube-dl", - "version": "0.5.0", + "version": "0.5.2", "author": "Pierre Rudloff", "bugs": "https://github.com/Rudloff/alltube/issues", "dependencies": { @@ -22,6 +22,9 @@ "grunt-phpdocumentor": "~0.4.1", "grunt-phpunit": "~0.3.6" }, + "engines": { + "npm": "~3" + }, "homepage": "https://www.alltubedownload.net/", "keywords": [ "alltube", diff --git a/templates/inc/footer.tpl b/templates/inc/footer.tpl index cdbb327..222dc1d 100644 --- a/templates/inc/footer.tpl +++ b/templates/inc/footer.tpl @@ -14,7 +14,6 @@ Get the code · Based on youtube-dl - ·