Merge branch 'feature/stream' into develop
This commit is contained in:
commit
9fed42d648
9 changed files with 382 additions and 51 deletions
|
@ -38,7 +38,7 @@ class Config
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
public $params = ['--no-playlist', '--no-warnings', '-f best[protocol^=http]', '--playlist-end', 1];
|
public $params = ['--no-playlist', '--no-warnings', '--playlist-end', 1];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable audio conversion.
|
* Enable audio conversion.
|
||||||
|
@ -82,6 +82,12 @@ class Config
|
||||||
*/
|
*/
|
||||||
public $uglyUrls = false;
|
public $uglyUrls = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stream downloaded files trough server?
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
public $stream = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* YAML config file path.
|
* YAML config file path.
|
||||||
*
|
*
|
||||||
|
|
|
@ -295,4 +295,33 @@ class VideoDownload
|
||||||
|
|
||||||
return popen($chain->getProcess()->getCommandLine(), 'r');
|
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)) {
|
||||||
|
throw(new \Exception('Can\'t find avconv or ffmpeg'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$procBuilder = ProcessBuilder::create(
|
||||||
|
[
|
||||||
|
$this->config->avconv,
|
||||||
|
'-v', 'quiet',
|
||||||
|
'-i', $video->url,
|
||||||
|
'-f', $video->ext,
|
||||||
|
'-c', 'copy',
|
||||||
|
'-bsf:a', 'aac_adtstoasc',
|
||||||
|
'-movflags', 'frag_keyframe+empty_moov',
|
||||||
|
'pipe:1',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
return popen($procBuilder->getProcess()->getCommandLine(), 'r');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
"symfony/process": "~3.2.0",
|
"symfony/process": "~3.2.0",
|
||||||
"ptachoire/process-builder-chain": "~1.2.0",
|
"ptachoire/process-builder-chain": "~1.2.0",
|
||||||
"rudloff/smarty-plugin-noscheme": "~0.1.0",
|
"rudloff/smarty-plugin-noscheme": "~0.1.0",
|
||||||
|
"guzzlehttp/guzzle": "~6.2.0",
|
||||||
|
"rudloff/rtmpdump-bin": "~2.3",
|
||||||
"aura/session": "~2.1.0"
|
"aura/session": "~2.1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
|
229
composer.lock
generated
229
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "15507d8a1cb225e2e118500a7883b255",
|
"content-hash": "44b24b403652e1a7e450280e4643e37e",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aura/session",
|
"name": "aura/session",
|
||||||
|
@ -95,6 +95,177 @@
|
||||||
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
||||||
"time": "2014-12-30T15:22:37+00:00"
|
"time": "2014-12-30T15:22:37+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "guzzlehttp/guzzle",
|
||||||
|
"version": "6.2.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/guzzle/guzzle.git",
|
||||||
|
"reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/ebf29dee597f02f09f4d5bbecc68230ea9b08f60",
|
||||||
|
"reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"guzzlehttp/promises": "^1.0",
|
||||||
|
"guzzlehttp/psr7": "^1.3.1",
|
||||||
|
"php": ">=5.5"
|
||||||
|
},
|
||||||
|
"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-10-08T15:01:37+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "guzzlehttp/promises",
|
||||||
|
"version": "v1.3.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/guzzle/promises.git",
|
||||||
|
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
|
||||||
|
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.5.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.4-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-12-20T10:07:11+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "guzzlehttp/psr7",
|
||||||
|
"version": "1.3.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/guzzle/psr7.git",
|
||||||
|
"reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b",
|
||||||
|
"reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b",
|
||||||
|
"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.4-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-06-24T23:00:38+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "jeremykendall/php-domain-parser",
|
"name": "jeremykendall/php-domain-parser",
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
|
@ -446,6 +617,34 @@
|
||||||
"description": "Add ability to chain symfony processes",
|
"description": "Add ability to chain symfony processes",
|
||||||
"time": "2016-04-10T08:33:20+00:00"
|
"time": "2016-04-10T08:33:20+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "rudloff/rtmpdump-bin",
|
||||||
|
"version": "2.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Rudloff/rtmpdump-bin.git",
|
||||||
|
"reference": "133cdd80e3bab66593e88a5276158596383afd97"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Rudloff/rtmpdump-bin/zipball/133cdd80e3bab66593e88a5276158596383afd97",
|
||||||
|
"reference": "133cdd80e3bab66593e88a5276158596383afd97",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"rtmpdump/rtmpdump": "2.3"
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"rtmpdump"
|
||||||
|
],
|
||||||
|
"type": "library",
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"GPL-2.0"
|
||||||
|
],
|
||||||
|
"description": "rtmpdump binary for Linux 64 bit",
|
||||||
|
"time": "2016-04-12T19:17:32+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "rudloff/smarty-plugin-noscheme",
|
"name": "rudloff/smarty-plugin-noscheme",
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
|
@ -1475,34 +1674,6 @@
|
||||||
},
|
},
|
||||||
"type": "library"
|
"type": "library"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "rudloff/rtmpdump-bin",
|
|
||||||
"version": "2.3",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/Rudloff/rtmpdump-bin.git",
|
|
||||||
"reference": "133cdd80e3bab66593e88a5276158596383afd97"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/Rudloff/rtmpdump-bin/zipball/133cdd80e3bab66593e88a5276158596383afd97",
|
|
||||||
"reference": "133cdd80e3bab66593e88a5276158596383afd97",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"rtmpdump/rtmpdump": "2.3"
|
|
||||||
},
|
|
||||||
"bin": [
|
|
||||||
"rtmpdump"
|
|
||||||
],
|
|
||||||
"type": "library",
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"GPL-2.0"
|
|
||||||
],
|
|
||||||
"description": "rtmpdump binary for Linux 64 bit",
|
|
||||||
"time": "2016-04-12T19:17:32+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "sebastian/code-unit-reverse-lookup",
|
"name": "sebastian/code-unit-reverse-lookup",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
|
|
@ -3,7 +3,6 @@ python: /usr/bin/python
|
||||||
params:
|
params:
|
||||||
- --no-playlist
|
- --no-playlist
|
||||||
- --no-warnings
|
- --no-warnings
|
||||||
- -f best[protocol^=http]
|
|
||||||
- --playlist-end
|
- --playlist-end
|
||||||
- 1
|
- 1
|
||||||
curl_params:
|
curl_params:
|
||||||
|
@ -12,3 +11,4 @@ avconv: vendor/bin/ffmpeg
|
||||||
rtmpdump: vendor/bin/rtmpdump
|
rtmpdump: vendor/bin/rtmpdump
|
||||||
curl: /usr/bin/curl
|
curl: /usr/bin/curl
|
||||||
uglyUrls: false
|
uglyUrls: false
|
||||||
|
stream: false
|
||||||
|
|
|
@ -68,6 +68,11 @@ class FrontController
|
||||||
$session_factory = new \Aura\Session\SessionFactory();
|
$session_factory = new \Aura\Session\SessionFactory();
|
||||||
$session = $session_factory->newInstance($_COOKIE);
|
$session = $session_factory->newInstance($_COOKIE);
|
||||||
$this->sessionSegment = $session->getSegment('Alltube\Controller\FrontController');
|
$this->sessionSegment = $session->getSegment('Alltube\Controller\FrontController');
|
||||||
|
if ($this->config->stream) {
|
||||||
|
$this->defaultFormat = 'best';
|
||||||
|
} else {
|
||||||
|
$this->defaultFormat = 'best[protocol^=http]';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -156,9 +161,13 @@ class FrontController
|
||||||
}
|
}
|
||||||
if (isset($params['audio'])) {
|
if (isset($params['audio'])) {
|
||||||
try {
|
try {
|
||||||
$url = $this->download->getURL($params['url'], 'mp3[protocol^=http]', $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);
|
return $response->withRedirect($url);
|
||||||
|
}
|
||||||
} catch (PasswordException $e) {
|
} catch (PasswordException $e) {
|
||||||
return $this->password($request, $response);
|
return $this->password($request, $response);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
@ -178,10 +187,15 @@ class FrontController
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
$video = $this->download->getJSON($params['url'], null, $password);
|
$video = $this->download->getJSON($params['url'], $this->defaultFormat, $password);
|
||||||
} catch (PasswordException $e) {
|
} catch (PasswordException $e) {
|
||||||
return $this->password($request, $response);
|
return $this->password($request, $response);
|
||||||
}
|
}
|
||||||
|
if ($this->config->stream) {
|
||||||
|
$protocol = '';
|
||||||
|
} else {
|
||||||
|
$protocol = '[protocol^=http]';
|
||||||
|
}
|
||||||
$this->view->render(
|
$this->view->render(
|
||||||
$response,
|
$response,
|
||||||
'video.tpl',
|
'video.tpl',
|
||||||
|
@ -190,6 +204,8 @@ class FrontController
|
||||||
'class' => 'video',
|
'class' => 'video',
|
||||||
'title' => $video->title,
|
'title' => $video->title,
|
||||||
'description' => 'Download "'.$video->title.'" from '.$video->extractor_key,
|
'description' => 'Download "'.$video->title.'" from '.$video->extractor_key,
|
||||||
|
'protocol' => $protocol,
|
||||||
|
'config' => $this->config,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -222,6 +238,43 @@ class FrontController
|
||||||
return $response->withStatus(500);
|
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)) {
|
||||||
|
$format = 'best';
|
||||||
|
}
|
||||||
|
$video = $this->download->getJSON($url, $format, $password);
|
||||||
|
if ($video->protocol == 'm3u8') {
|
||||||
|
$stream = $this->download->getM3uStream($video);
|
||||||
|
$response = $response->withHeader('Content-Type', 'video/'.$video->ext);
|
||||||
|
if ($request->isGet()) {
|
||||||
|
$response = $response->withBody(new Stream($stream));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$client = new \GuzzleHttp\Client();
|
||||||
|
$stream = $client->request('GET', $video->url, ['stream' => true]);
|
||||||
|
$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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$response = $response->withHeader('Content-Disposition', 'attachment; filename="'.$video->_filename.'"');
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect to video file.
|
* Redirect to video file.
|
||||||
*
|
*
|
||||||
|
@ -235,13 +288,23 @@ class FrontController
|
||||||
$params = $request->getQueryParams();
|
$params = $request->getQueryParams();
|
||||||
if (isset($params['url'])) {
|
if (isset($params['url'])) {
|
||||||
try {
|
try {
|
||||||
$url = $this->download->getURL(
|
if ($this->config->stream) {
|
||||||
$params['url'],
|
return $this->getStream(
|
||||||
$request->getParam('format'),
|
$params['url'],
|
||||||
$this->sessionSegment->getFlash($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);
|
return $response->withRedirect($url);
|
||||||
|
}
|
||||||
} catch (PasswordException $e) {
|
} catch (PasswordException $e) {
|
||||||
return $response->withRedirect(
|
return $response->withRedirect(
|
||||||
$this->container->get('router')->pathFor('video').'?url='.urlencode($params['url'])
|
$this->container->get('router')->pathFor('video').'?url='.urlencode($params['url'])
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
"homepage": "https://www.alltubedownload.net/",
|
"homepage": "https://www.alltubedownload.net/",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"alltube",
|
"alltube",
|
||||||
"dowload",
|
"download",
|
||||||
"video",
|
"video",
|
||||||
"youtube"
|
"youtube"
|
||||||
],
|
],
|
||||||
|
|
|
@ -29,18 +29,18 @@
|
||||||
{/if}
|
{/if}
|
||||||
<select name="format" id="format" class="formats monospace">
|
<select name="format" id="format" class="formats monospace">
|
||||||
<optgroup label="Generic formats">
|
<optgroup label="Generic formats">
|
||||||
<option value="best[protocol^=http]">
|
<option value="best{$protocol}">
|
||||||
{strip}
|
{strip}
|
||||||
Best ({$video->ext})
|
Best ({$video->ext})
|
||||||
{/strip}
|
{/strip}
|
||||||
</option>
|
</option>
|
||||||
<option value="worst[protocol^=http]">
|
<option value="worst{$protocol}">
|
||||||
Worst
|
Worst
|
||||||
</option>
|
</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label="Detailed formats" class="monospace">
|
<optgroup label="Detailed formats" class="monospace">
|
||||||
{foreach $video->formats as $format}
|
{foreach $video->formats as $format}
|
||||||
{if $format->protocol|in_array:array('http', 'https')}
|
{if $config->stream || $format->protocol|in_array:array('http', 'https')}
|
||||||
{strip}
|
{strip}
|
||||||
<option value="{$format->format_id}">
|
<option value="{$format->format_id}">
|
||||||
{$format->ext}
|
{$format->ext}
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
<input class="downloadBtn" type="submit" value="Download" /><br/>
|
<input class="downloadBtn" type="submit" value="Download" /><br/>
|
||||||
</form>
|
</form>
|
||||||
{else}
|
{else}
|
||||||
<input type="hidden" name="format" value="best[protocol^=http]" />
|
<input type="hidden" name="format" value="best{$protocol}" />
|
||||||
<a class="downloadBtn"
|
<a class="downloadBtn"
|
||||||
href="{$video->url|escape}">Download</a><br/>
|
href="{$video->url|escape}">Download</a><br/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -146,7 +146,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
return [
|
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",
|
"It's Not Me, It's You - Hearts Under Fire-M7IpKCZ47pU",
|
||||||
'mp4',
|
'mp4',
|
||||||
'googlevideo.com',
|
'googlevideo.com',
|
||||||
|
@ -159,7 +159,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
|
||||||
'googlevideo.com',
|
'googlevideo.com',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'https://vimeo.com/24195442', null,
|
'https://vimeo.com/24195442', 'best[protocol^=http]',
|
||||||
'Carving the Mountains-24195442',
|
'Carving the Mountains-24195442',
|
||||||
'mp4',
|
'mp4',
|
||||||
'vimeocdn.com',
|
'vimeocdn.com',
|
||||||
|
@ -179,6 +179,23 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides M3U8 URLs for tests.
|
||||||
|
*
|
||||||
|
* @return array[]
|
||||||
|
*/
|
||||||
|
public function M3uUrlProvider()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'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',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides incorrect URLs for tests.
|
* Provides incorrect URLs for tests.
|
||||||
*
|
*
|
||||||
|
@ -199,6 +216,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @dataProvider URLProvider
|
* @dataProvider URLProvider
|
||||||
|
* @dataProvider M3uUrlProvider
|
||||||
*/
|
*/
|
||||||
public function testGetJSON($url, $format)
|
public function testGetJSON($url, $format)
|
||||||
{
|
{
|
||||||
|
@ -207,6 +225,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertObjectHasAttribute('url', $info);
|
$this->assertObjectHasAttribute('url', $info);
|
||||||
$this->assertObjectHasAttribute('ext', $info);
|
$this->assertObjectHasAttribute('ext', $info);
|
||||||
$this->assertObjectHasAttribute('title', $info);
|
$this->assertObjectHasAttribute('title', $info);
|
||||||
|
$this->assertObjectHasAttribute('extractor_key', $info);
|
||||||
$this->assertObjectHasAttribute('formats', $info);
|
$this->assertObjectHasAttribute('formats', $info);
|
||||||
$this->assertObjectHasAttribute('_filename', $info);
|
$this->assertObjectHasAttribute('_filename', $info);
|
||||||
}
|
}
|
||||||
|
@ -235,6 +254,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @dataProvider urlProvider
|
* @dataProvider urlProvider
|
||||||
|
* @dataProvider M3uUrlProvider
|
||||||
*/
|
*/
|
||||||
public function testGetFilename($url, $format, $filename, $extension)
|
public function testGetFilename($url, $format, $filename, $extension)
|
||||||
{
|
{
|
||||||
|
@ -267,6 +287,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @dataProvider urlProvider
|
* @dataProvider urlProvider
|
||||||
|
* @dataProvider M3uUrlProvider
|
||||||
*/
|
*/
|
||||||
public function testGetAudioFilename($url, $format, $filename)
|
public function testGetAudioFilename($url, $format, $filename)
|
||||||
{
|
{
|
||||||
|
@ -302,7 +323,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
|
||||||
*/
|
*/
|
||||||
public function testGetAudioStreamAvconvError($url, $format)
|
public function testGetAudioStreamAvconvError($url, $format)
|
||||||
{
|
{
|
||||||
$config = \Alltube\Config::getInstance();
|
$config = Config::getInstance();
|
||||||
$config->avconv = 'foobar';
|
$config->avconv = 'foobar';
|
||||||
$this->download->getAudioStream($url, $format);
|
$this->download->getAudioStream($url, $format);
|
||||||
}
|
}
|
||||||
|
@ -319,7 +340,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
|
||||||
*/
|
*/
|
||||||
public function testGetAudioStreamCurlError($url, $format)
|
public function testGetAudioStreamCurlError($url, $format)
|
||||||
{
|
{
|
||||||
$config = \Alltube\Config::getInstance();
|
$config = Config::getInstance();
|
||||||
$config->curl = 'foobar';
|
$config->curl = 'foobar';
|
||||||
$config->rtmpdump = 'foobar';
|
$config->rtmpdump = 'foobar';
|
||||||
$this->download->getAudioStream($url, $format);
|
$this->download->getAudioStream($url, $format);
|
||||||
|
@ -328,11 +349,50 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
|
||||||
/**
|
/**
|
||||||
* Test getAudioStream function with a M3U8 file.
|
* Test getAudioStream function with a M3U8 file.
|
||||||
*
|
*
|
||||||
|
* @param string $url URL
|
||||||
|
* @param string $format Format
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @expectedException Exception
|
* @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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue