From df9f60339d6d1b6363cce1114903e39073dd887e Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Thu, 7 Apr 2016 02:09:34 +0200 Subject: [PATCH 01/19] WIP stream --- composer.json | 3 +- composer.lock | 175 +++++++++++++++++++++++++++++++- controllers/FrontController.php | 32 ++++-- index.php | 4 +- templates/video.tpl | 37 ++++--- 5 files changed, 216 insertions(+), 35 deletions(-) diff --git a/composer.json b/composer.json index 86c5e22..9401c8d 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,8 @@ "symfony/yaml": "~3.0.0", "symfony/process": "~3.0.0", "ffmpeg/ffmpeg": "~2.8.2", - "rudloff/smarty-plugin-noscheme": "~0.1.0" + "rudloff/smarty-plugin-noscheme": "~0.1.0", + "guzzlehttp/guzzle": "~6.2.0" }, "require-dev": { "symfony/var-dumper": "~3.0.0" diff --git a/composer.lock b/composer.lock index e589dc2..9c2c859 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": "829ac07cae5bc43ef0ad3f5e5be618c5", - "content-hash": "a7131399bb03f78ba0dcfd8ab7e98d59", + "hash": "6ef0d5dc0640824fef3033cba540c6fb", + "content-hash": "dd3d8be96114267b553f77632c326e2c", "packages": [ { "name": "container-interop/container-interop", @@ -48,6 +48,177 @@ ], "type": "library" }, + { + "name": "guzzlehttp/guzzle", + "version": "6.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "d094e337976dff9d8e2424e8485872194e768662" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d094e337976dff9d8e2424e8485872194e768662", + "reference": "d094e337976dff9d8e2424e8485872194e768662", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "~1.0", + "guzzlehttp/psr7": "~1.1", + "php": ">=5.5.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "~4.0", + "psr/log": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.2-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2016-03-21 20:02:09" + }, + { + "name": "guzzlehttp/promises", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "bb9024c526b22f3fe6ae55a561fd70653d470aa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bb9024c526b22f3fe6ae55a561fd70653d470aa8", + "reference": "bb9024c526b22f3fe6ae55a561fd70653d470aa8", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-03-08 01:15:46" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/2e89629ff057ebb49492ba08e6995d3a6a80021b", + "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "PSR-7 message implementation", + "keywords": [ + "http", + "message", + "stream", + "uri" + ], + "time": "2016-02-18 21:54:00" + }, { "name": "jeremykendall/php-domain-parser", "version": "3.0.0", diff --git a/controllers/FrontController.php b/controllers/FrontController.php index 06f8188..6e734cd 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -103,11 +103,12 @@ class FrontController public static function video($request, $response) { global $container; + $params = $request->getQueryParams(); $config = Config::getInstance(); - if (isset($_GET["url"])) { - if (isset($_GET['audio'])) { + if (isset($params["url"])) { + if (isset($params['audio'])) { try { - $video = VideoDownload::getJSON($_GET["url"]); + $video = VideoDownload::getJSON($params["url"]); //Vimeo needs a correct user-agent $UA = VideoDownload::getUA(); @@ -168,7 +169,7 @@ class FrontController } } else { try { - $video = VideoDownload::getJSON($_GET["url"]); + $video = VideoDownload::getJSON($params["url"]); $container->view->render( $response, 'head.tpl', @@ -219,12 +220,22 @@ class FrontController public static function redirect($request, $response) { global $app; - if (isset($_GET["url"])) { + $params = $request->getQueryParams(); + if (isset($params["url"])) { try { - $video = VideoDownload::getURL($_GET["url"]); - return $response->withRedirect($video['url']); + $format = isset($params["format"]) ? $params["format"] : 'best'; + $video = VideoDownload::getJSON($params["url"], $format); + $client = new \GuzzleHttp\Client(); + $stream = $client->request('GET', $video->url, array('stream'=>true)); + $response = $response->withHeader('Content-Disposition', 'inline; filename="'.$video->_filename.'"'); + $response = $response->withHeader('Content-Type', $stream->getHeader('Content-Type')); + $response = $response->withHeader('Content-Length', $stream->getHeader('Content-Length')); + if ($request->isGet()) { + $response = $response->withBody($stream->getBody()); + } + return $response; } catch (\Exception $e) { - echo $e->getMessage().PHP_EOL; + $response->getBody()->write($e->getMessage().PHP_EOL); return $response->withHeader('Content-Type', 'text/plain'); } } @@ -241,9 +252,10 @@ class FrontController public static function json($request, $response) { global $app; - if (isset($_GET["url"])) { + $params = $request->getQueryParams(); + if (isset($params["url"])) { try { - $video = VideoDownload::getJSON($_GET["url"]); + $video = VideoDownload::getJSON($params["url"]); return $response->withJson($video); } catch (\Exception $e) { return $response->withJson( diff --git a/index.php b/index.php index 468a685..c26d743 100644 --- a/index.php +++ b/index.php @@ -22,7 +22,7 @@ $container['view'] = function ($c) { $view = new \Slim\Views\Smarty(__DIR__.'/templates/'); $view->addSlimPlugins($c['router'], $c['request']->getUri()); - $view->registerPlugin('modifier', 'noscheme', 'Smarty_Modifier_noscheme'); + $view->registerPlugin('modifier', 'noscheme', 'Smarty_Modifier_noscheme'); return $view; @@ -43,7 +43,7 @@ $app->get( $app->get( '/redirect', array('Alltube\Controller\FrontController', 'redirect') -); +)->setName('redirect'); $app->get( '/json', array('Alltube\Controller\FrontController', 'json') diff --git a/templates/video.tpl b/templates/video.tpl index b6a1231..31c0b10 100644 --- a/templates/video.tpl +++ b/templates/video.tpl @@ -22,27 +22,24 @@ {/if}
- {if isset($video->formats)} -

Available formats:

-

(You might have to do a Right click > Save as)

-

+

+
+ +

+
+
{else} Date: Fri, 8 Apr 2016 22:58:42 +0200 Subject: [PATCH 02/19] Use smaller chunks (see https://github.com/slimphp/Slim/issues/1836) --- index.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index de9387b..b7230d9 100644 --- a/index.php +++ b/index.php @@ -17,7 +17,13 @@ require_once __DIR__.'/vendor/rudloff/smarty-plugin-noscheme/modifier.noscheme.p use Alltube\VideoDownload; use Alltube\Controller\FrontController; -$app = new \Slim\App(); +$app = new \Slim\App( + array( + 'settings'=>array( + 'responseChunkSize'=>1024 + ) + ) +); $container = $app->getContainer(); $container['view'] = function ($c) { $view = new \Slim\Views\Smarty(__DIR__.'/templates/'); From 9354174b77375859ac02f3fd2d6cc9cdc9c7ab3f Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Fri, 8 Apr 2016 23:01:07 +0200 Subject: [PATCH 03/19] Use bestaudio format if available --- controllers/FrontController.php | 125 +++++++++++++++++--------------- 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/controllers/FrontController.php b/controllers/FrontController.php index aba76f5..663f255 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -115,58 +115,58 @@ class FrontController $video = $this->download->getJSON($params["url"]); //Vimeo needs a correct user-agent - $UA = $this->download->getUA(); ini_set( 'user_agent', - $UA + $video->http_headers->{'User-Agent'} ); $url_info = parse_url($video->url); - if ($url_info['scheme'] == 'rtmp') { - ob_end_flush(); - header( - 'Content-Disposition: attachment; filename="'. - html_entity_decode( - pathinfo( - $this->download->getFilename( - $video->webpage_url - ), - PATHINFO_FILENAME - ).'.mp3', - ENT_COMPAT, - 'ISO-8859-1' - ).'"' - ); - header("Content-Type: audio/mpeg"); - passthru( - '/usr/bin/rtmpdump -q -r '.escapeshellarg($video->url). - ' | '.$this->config->avconv. - ' -v quiet -i - -f mp3 -vn pipe:1' - ); - exit; - } else { - ob_end_flush(); - header( - 'Content-Disposition: attachment; filename="'. - html_entity_decode( - pathinfo( - $this->download->getFilename( - $video->webpage_url - ), - PATHINFO_FILENAME - ).'.mp3', - ENT_COMPAT, - 'ISO-8859-1' - ).'"' - ); - header("Content-Type: audio/mpeg"); - passthru( - 'curl '.$this->config->curl_params. - ' --user-agent '.escapeshellarg($UA). - ' '.escapeshellarg($video->url). - ' | '.$this->config->avconv. - ' -v quiet -i - -f mp3 -vn pipe:1' - ); - exit; + + try { + return $this->getStream($params["url"], 'bestaudio', $response, $request); + } catch (\Exception $e) { + if ($url_info['scheme'] == 'rtmp') { + ob_end_flush(); + header( + 'Content-Disposition: attachment; filename="'. + html_entity_decode( + pathinfo( + $video->_filename, + PATHINFO_FILENAME + ).'.mp3', + ENT_COMPAT, + 'ISO-8859-1' + ).'"' + ); + header("Content-Type: audio/mpeg"); + passthru( + '/usr/bin/rtmpdump -q -r '.escapeshellarg($video->url). + ' | '.$this->config->avconv. + ' -v quiet -i - -f mp3 -vn pipe:1' + ); + exit; + } else { + ob_end_flush(); + header( + 'Content-Disposition: attachment; filename="'. + html_entity_decode( + pathinfo( + $video->_filename, + PATHINFO_FILENAME + ).'.mp3', + ENT_COMPAT, + 'ISO-8859-1' + ).'"' + ); + header("Content-Type: audio/mpeg"); + passthru( + 'curl '.$this->config->curl_params. + ' --user-agent '.escapeshellarg($video->http_headers->{'User-Agent'}). + ' '.escapeshellarg($video->url). + ' | '.$this->config->avconv. + ' -v quiet -i - -f mp3 -vn pipe:1' + ); + exit; + } } } catch (\Exception $e) { $error = $e->getMessage(); @@ -213,6 +213,23 @@ class FrontController } } + private function getStream($url, $format, $response, $request) + { + if (!isset($format)) { + $format = 'best'; + } + $video = $this->download->getJSON($url, $format); + $client = new \GuzzleHttp\Client(); + $stream = $client->request('GET', $video->url, array('stream'=>true)); + $response = $response->withHeader('Content-Disposition', 'inline; filename="'.$video->_filename.'"'); + $response = $response->withHeader('Content-Type', $stream->getHeader('Content-Type')); + $response = $response->withHeader('Content-Length', $stream->getHeader('Content-Length')); + if ($request->isGet()) { + $response = $response->withBody($stream->getBody()); + } + return $response; + } + /** * Redirect to video file * @@ -227,17 +244,7 @@ class FrontController $params = $request->getQueryParams(); if (isset($params["url"])) { try { - $format = isset($params["format"]) ? $params["format"] : 'best'; - $video = $this->download->getJSON($params["url"], $format); - $client = new \GuzzleHttp\Client(); - $stream = $client->request('GET', $video->url, array('stream'=>true)); - $response = $response->withHeader('Content-Disposition', 'inline; filename="'.$video->_filename.'"'); - $response = $response->withHeader('Content-Type', $stream->getHeader('Content-Type')); - $response = $response->withHeader('Content-Length', $stream->getHeader('Content-Length')); - if ($request->isGet()) { - $response = $response->withBody($stream->getBody()); - } - return $response; + return $this->getStream($params["url"], $params["format"], $response, $request); } catch (\Exception $e) { $response->getBody()->write($e->getMessage().PHP_EOL); return $response->withHeader('Content-Type', 'text/plain'); From 734271c67c471807fab2fb7c8745b7438d7c61bc Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Fri, 8 Apr 2016 23:48:48 +0200 Subject: [PATCH 04/19] Download worst format --- templates/video.tpl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/templates/video.tpl b/templates/video.tpl index 31c0b10..e8291cc 100644 --- a/templates/video.tpl +++ b/templates/video.tpl @@ -30,7 +30,10 @@ - + + {foreach $video->formats as $format} Download
{/if} diff --git a/tests/VideoDownloadTest.php b/tests/VideoDownloadTest.php index c1053bd..bd5ebe7 100644 --- a/tests/VideoDownloadTest.php +++ b/tests/VideoDownloadTest.php @@ -176,6 +176,13 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase 'edgefcs.net', 'GRIP sucht den Sommerkönig-folge-203-0.mp3', ], + [ + //Only works on the feature/stream branch + 'https://twitter.com/verge/status/813055465324056576/video/1', null, + 'The Verge - This tiny origami robot can self-fold and complete tasks-813055465324056576.mp4', + 'video.twimg.com', + 'The Verge - This tiny origami robot can self-fold and complete tasks-813055465324056576.mp3', + ] ]; } From 3f96adb255ccc464af1f1073ed6fab18c6171051 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 26 Dec 2016 15:53:03 +0100 Subject: [PATCH 13/19] Lint --- classes/Config.php | 2 +- tests/VideoDownloadTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/Config.php b/classes/Config.php index 14c42c0..5921a61 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -42,7 +42,7 @@ class Config '--no-playlist', '--no-warnings', //We can allow non-HTTP URLs on the feature/stream branch '-f best', - '--playlist-end', 1 + '--playlist-end', 1, ]; /** diff --git a/tests/VideoDownloadTest.php b/tests/VideoDownloadTest.php index bd5ebe7..a95a636 100644 --- a/tests/VideoDownloadTest.php +++ b/tests/VideoDownloadTest.php @@ -182,7 +182,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase 'The Verge - This tiny origami robot can self-fold and complete tasks-813055465324056576.mp4', 'video.twimg.com', 'The Verge - This tiny origami robot can self-fold and complete tasks-813055465324056576.mp3', - ] + ], ]; } From 20820d90f0e001701f8294809e0be79f36771c4d Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 26 Dec 2016 15:58:07 +0100 Subject: [PATCH 14/19] Missing doc --- classes/VideoDownload.php | 9 +++++++-- controllers/FrontController.php | 9 +++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/classes/VideoDownload.php b/classes/VideoDownload.php index 18de6d5..d94dd85 100644 --- a/classes/VideoDownload.php +++ b/classes/VideoDownload.php @@ -293,6 +293,13 @@ class VideoDownload return popen($chain->getProcess()->getCommandLine(), 'r'); } + /** + * Get video stream from an M3U playlist. + * + * @param \stdClass $video Video object returned by getJSON + * + * @return resource popen stream + */ public function getM3uStream(\stdClass $video) { if (!shell_exec('which '.$this->config->avconv)) { @@ -312,8 +319,6 @@ class VideoDownload ] ); - //dump($procBuilder->getProcess()->getCommandLine()); die; - return popen($procBuilder->getProcess()->getCommandLine(), 'r'); } } diff --git a/controllers/FrontController.php b/controllers/FrontController.php index 5f7ef09..b357d7d 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -217,6 +217,15 @@ class FrontController return $response->withStatus(500); } + /** + * Get a video/audio stream piped through the server. + * @param string $url URL of the video + * @param string $format Requested format + * @param Response $response PSR-7 response + * @param Request $request PSR-7 request + * @param string $password Video password + * @return Response + */ private function getStream($url, $format, $response, $request, $password = null) { if (!isset($format)) { From 0967bd6853901ecf5b6b4b5346a48269ef301c2e Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 26 Dec 2016 15:59:16 +0100 Subject: [PATCH 15/19] Lint --- controllers/FrontController.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/controllers/FrontController.php b/controllers/FrontController.php index b357d7d..4c88bd1 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -219,11 +219,13 @@ class FrontController /** * Get a video/audio stream piped through the server. - * @param string $url URL of the video - * @param string $format Requested format - * @param Response $response PSR-7 response - * @param Request $request PSR-7 request - * @param string $password Video password + * + * @param string $url URL of the video + * @param string $format Requested format + * @param Response $response PSR-7 response + * @param Request $request PSR-7 request + * @param string $password Video password + * * @return Response */ private function getStream($url, $format, $response, $request, $password = null) From b730b51b21651acd387a4e0393d0071047098457 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Tue, 27 Dec 2016 00:10:18 +0100 Subject: [PATCH 16/19] Fix M3U test --- tests/VideoDownloadTest.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/VideoDownloadTest.php b/tests/VideoDownloadTest.php index 1481793..5bb6af2 100644 --- a/tests/VideoDownloadTest.php +++ b/tests/VideoDownloadTest.php @@ -176,8 +176,18 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase 'edgefcs.net', 'GRIP sucht den Sommerkönig-folge-203-0.mp3', ], + ]; + } + + /** + * Provides M3U8 URLs for tests. + * + * @return array[] + */ + public function M3uUrlProvider() + { + return [ [ - //Only works on the feature/stream branch 'https://twitter.com/verge/status/813055465324056576/video/1', null, 'The Verge - This tiny origami robot can self-fold and complete tasks-813055465324056576.mp4', 'video.twimg.com', @@ -206,6 +216,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase * * @return void * @dataProvider URLProvider + * @dataProvider M3uUrlProvider */ public function testGetJSON($url, $format) { @@ -241,6 +252,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase * * @return void * @dataProvider urlProvider + * @dataProvider M3uUrlProvider */ public function testGetFilename($url, $format, $filename) { @@ -273,6 +285,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase * * @return void * @dataProvider urlProvider + * @dataProvider M3uUrlProvider */ public function testGetAudioFilename($url, $format, $filename, $domain, $audioFilename) { From ef366dc6d101edc8b5435b67c10ccbf0f2ef8e80 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Tue, 27 Dec 2016 00:36:30 +0100 Subject: [PATCH 17/19] Add tests for getM3uStream() --- tests/VideoDownloadTest.php | 43 +++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/tests/VideoDownloadTest.php b/tests/VideoDownloadTest.php index 5bb6af2..4cd580d 100644 --- a/tests/VideoDownloadTest.php +++ b/tests/VideoDownloadTest.php @@ -347,11 +347,50 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase /** * Test getAudioStream function with a M3U8 file. * + * @param string $url URL + * @param string $format Format + * * @return void * @expectedException Exception + * @dataProvider M3uUrlProvider */ - public function testGetAudioStreamM3uError() + public function testGetAudioStreamM3uError($url, $format) { - $this->download->getAudioStream('https://twitter.com/verge/status/813055465324056576/video/1', 'best'); + $this->download->getAudioStream($url, $format); + } + + /** + * Test getM3uStream function. + * + * @param string $url URL + * @param string $format Format + * + * @return void + * @dataProvider M3uUrlProvider + */ + public function testGetM3uStream($url, $format) + { + $video = $this->download->getJSON($url, $format); + $stream = $this->download->getM3uStream($video); + $this->assertInternalType('resource', $stream); + $this->assertFalse(feof($stream)); + } + + /** + * Test getM3uStream function without avconv. + * + * @param string $url URL + * @param string $format Format + * + * @return void + * @expectedException Exception + * @dataProvider M3uUrlProvider + */ + public function testGetM3uStreamAvconvError($url, $format) + { + $config = \Alltube\Config::getInstance(); + $config->avconv = 'foobar'; + $video = $this->download->getJSON($url, $format); + $this->download->getM3uStream($video); } } From d96a1e48673122aec860d137fb37d24ab4240f38 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 16 Jan 2017 11:23:47 +0100 Subject: [PATCH 18/19] Fix M3U tests --- tests/VideoDownloadTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/VideoDownloadTest.php b/tests/VideoDownloadTest.php index cdec782..3c5d760 100644 --- a/tests/VideoDownloadTest.php +++ b/tests/VideoDownloadTest.php @@ -189,9 +189,9 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase return [ [ 'https://twitter.com/verge/status/813055465324056576/video/1', null, - 'The Verge - This tiny origami robot can self-fold and complete tasks-813055465324056576.mp4', + 'The Verge - This tiny origami robot can self-fold and complete tasks-813055465324056576', + 'mp4', 'video.twimg.com', - 'The Verge - This tiny origami robot can self-fold and complete tasks-813055465324056576.mp3', ], ]; } From 4e1c1ca9532b28b20ddcf55290d5d17532b700cd Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 16 Jan 2017 11:29:56 +0100 Subject: [PATCH 19/19] Add a stream parameter in config (fixes #24 and #39) --- classes/Config.php | 13 +++++----- config.example.yml | 2 +- controllers/FrontController.php | 46 ++++++++++++++++++++++++++------- templates/video.tpl | 8 +++--- tests/VideoDownloadTest.php | 11 ++++---- 5 files changed, 56 insertions(+), 24 deletions(-) diff --git a/classes/Config.php b/classes/Config.php index 0482e36..72779b8 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -38,12 +38,7 @@ class Config * * @var array */ - public $params = [ - '--no-playlist', '--no-warnings', - //We can allow non-HTTP URLs on the feature/stream branch - '-f best', - '--playlist-end', 1, - ]; + public $params = ['--no-playlist', '--no-warnings', '--playlist-end', 1]; /** * Enable audio conversion. @@ -87,6 +82,12 @@ class Config */ public $uglyUrls = false; + /** + * Stream downloaded files trough server? + * @var boolean + */ + public $stream = false; + /** * YAML config file path. * diff --git a/config.example.yml b/config.example.yml index 7fb80ef..6bb93e4 100644 --- a/config.example.yml +++ b/config.example.yml @@ -3,7 +3,6 @@ python: /usr/bin/python params: - --no-playlist - --no-warnings - - -f best[protocol^=http] - --playlist-end - 1 curl_params: @@ -12,3 +11,4 @@ avconv: vendor/bin/ffmpeg rtmpdump: vendor/bin/rtmpdump curl: /usr/bin/curl uglyUrls: false +stream: false diff --git a/controllers/FrontController.php b/controllers/FrontController.php index cc71335..0c101b8 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -68,6 +68,11 @@ class FrontController $session_factory = new \Aura\Session\SessionFactory(); $session = $session_factory->newInstance($_COOKIE); $this->sessionSegment = $session->getSegment('Alltube\Controller\FrontController'); + if ($this->config->stream) { + $this->defaultFormat = 'best'; + } else { + $this->defaultFormat = 'best[protocol^=http]'; + } } /** @@ -156,7 +161,13 @@ class FrontController } if (isset($params['audio'])) { try { - return $this->getStream($params['url'], 'mp3', $response, $request, $password); + if ($this->config->stream) { + return $this->getStream($params['url'], 'mp3', $response, $request, $password); + } else { + $url = $this->download->getURL($params['url'], 'mp3[protocol^=http]', $password); + + return $response->withRedirect($url); + } } catch (PasswordException $e) { return $this->password($request, $response); } catch (\Exception $e) { @@ -176,10 +187,15 @@ class FrontController } } else { try { - $video = $this->download->getJSON($params['url'], null, $password); + $video = $this->download->getJSON($params['url'], $this->defaultFormat, $password); } catch (PasswordException $e) { return $this->password($request, $response); } + if ($this->config->stream) { + $protocol = ''; + } else { + $protocol = '[protocol^=http]'; + } $this->view->render( $response, 'video.tpl', @@ -188,6 +204,8 @@ class FrontController 'class' => 'video', 'title' => $video->title, 'description' => 'Download "'.$video->title.'" from '.$video->extractor_key, + 'protocol' => $protocol, + 'config' => $this->config, ] ); } @@ -270,13 +288,23 @@ class FrontController $params = $request->getQueryParams(); if (isset($params['url'])) { try { - return $this->getStream( - $params['url'], - $request->getParam('format'), - $response, - $request, - $this->sessionSegment->getFlash($params['url']) - ); + if ($this->config->stream) { + return $this->getStream( + $params['url'], + $request->getParam('format'), + $response, + $request, + $this->sessionSegment->getFlash($params['url']) + ); + } else { + $url = $this->download->getURL( + $params['url'], + $request->getParam('format'), + $this->sessionSegment->getFlash($params['url']) + ); + + return $response->withRedirect($url); + } } catch (PasswordException $e) { return $response->withRedirect( $this->container->get('router')->pathFor('video').'?url='.urlencode($params['url']) diff --git a/templates/video.tpl b/templates/video.tpl index 85a4a25..5b82363 100644 --- a/templates/video.tpl +++ b/templates/video.tpl @@ -29,17 +29,18 @@ {/if}


{else} - + Download
{/if} diff --git a/tests/VideoDownloadTest.php b/tests/VideoDownloadTest.php index 3c5d760..202e858 100644 --- a/tests/VideoDownloadTest.php +++ b/tests/VideoDownloadTest.php @@ -146,7 +146,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase { return [ [ - 'https://www.youtube.com/watch?v=M7IpKCZ47pU', null, + 'https://www.youtube.com/watch?v=M7IpKCZ47pU', 'best[protocol^=http]', "It's Not Me, It's You - Hearts Under Fire-M7IpKCZ47pU", 'mp4', 'googlevideo.com', @@ -159,7 +159,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase 'googlevideo.com', ], [ - 'https://vimeo.com/24195442', null, + 'https://vimeo.com/24195442', 'best[protocol^=http]', 'Carving the Mountains-24195442', 'mp4', 'vimeocdn.com', @@ -188,7 +188,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase { return [ [ - 'https://twitter.com/verge/status/813055465324056576/video/1', null, + 'https://twitter.com/verge/status/813055465324056576/video/1', 'best', 'The Verge - This tiny origami robot can self-fold and complete tasks-813055465324056576', 'mp4', 'video.twimg.com', @@ -225,6 +225,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase $this->assertObjectHasAttribute('url', $info); $this->assertObjectHasAttribute('ext', $info); $this->assertObjectHasAttribute('title', $info); + $this->assertObjectHasAttribute('extractor_key', $info); $this->assertObjectHasAttribute('formats', $info); $this->assertObjectHasAttribute('_filename', $info); } @@ -322,7 +323,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase */ public function testGetAudioStreamAvconvError($url, $format) { - $config = \Alltube\Config::getInstance(); + $config = Config::getInstance(); $config->avconv = 'foobar'; $this->download->getAudioStream($url, $format); } @@ -339,7 +340,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase */ public function testGetAudioStreamCurlError($url, $format) { - $config = \Alltube\Config::getInstance(); + $config = Config::getInstance(); $config->curl = 'foobar'; $config->rtmpdump = 'foobar'; $this->download->getAudioStream($url, $format);