Remove dependency on curl (fixes #105)

avconv/ffmpeg now downloads the video directly when converting
This commit is contained in:
Pierre Rudloff 2017-04-24 19:16:38 +02:00
parent b9aad26803
commit b80b9c7b2e
7 changed files with 34 additions and 72 deletions

5
FAQ.md
View file

@ -15,7 +15,6 @@ Here are the parameters that you can set:
* `youtubedl`: path to your youtube-dl binary * `youtubedl`: path to your youtube-dl binary
* `python`: path to your python binary * `python`: path to your python binary
* `params`: an array of parameters to pass to youtube-dl * `params`: an array of parameters to pass to youtube-dl
* `curl_params`: an array of parameters to pass to curl
* `convert`: true to enable audio conversion * `convert`: true to enable audio conversion
* `avconv`: path to your avconv or ffmpeg binary * `avconv`: path to your avconv or ffmpeg binary
* `rtmpdump`: path to your rtmpdump binary * `rtmpdump`: path to your rtmpdump binary
@ -31,10 +30,10 @@ convert: true
avconv: path/to/avconv avconv: path/to/avconv
``` ```
You will also need to install `avconv` and `curl` on your server: You will also need to install `avconv` on your server:
```bash ```bash
sudo apt-get install libav-tools curl sudo apt-get install libav-tools
``` ```
## How do I deploy Alltube on Heroku? ## How do I deploy Alltube on Heroku?

View file

@ -122,13 +122,13 @@ server {
## Other dependencies ## 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. You need [avconv](https://libav.org/avconv.html) and [rtmpdump](http://rtmpdump.mplayerhq.hu/) 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: On Debian-based systems:
```bash ```bash
sudo apt-get install libav-tools rtmpdump curl sudo apt-get install libav-tools rtmpdump
``` ```
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).

View file

@ -61,20 +61,6 @@ class Config
*/ */
public $rtmpdump = 'vendor/bin/rtmpdump'; public $rtmpdump = 'vendor/bin/rtmpdump';
/**
* curl binary path.
*
* @var string
*/
public $curl = '/usr/bin/curl';
/**
* curl parameters.
*
* @var array
*/
public $curl_params = [];
/** /**
* Disable URL rewriting. * Disable URL rewriting.
* *
@ -104,9 +90,7 @@ class Config
* * python: Python binary path * * python: Python binary path
* * avconv: avconv or ffmpeg binary path * * avconv: avconv or ffmpeg binary path
* * rtmpdump: rtmpdump binary path * * rtmpdump: rtmpdump binary path
* * curl: curl binary path
* * params: Array of youtube-dl parameters * * params: Array of youtube-dl parameters
* * curl_params: Array of curl parameters
* * convert: Enable conversion? * * convert: Enable conversion?
* *
* @param array $options Options * @param array $options Options

View file

@ -98,7 +98,7 @@ class VideoDownload
throw new \Exception($errorOutput); throw new \Exception($errorOutput);
} }
} else { } else {
return $process->getOutput(); return trim($process->getOutput());
} }
} }
@ -222,31 +222,30 @@ class VideoDownload
} }
/** /**
* Get a process that runs curl in order to download a video. * Get a process that runs avconv in order to convert a video to MP3.
* *
* @param object $video Video object returned by youtube-dl * @param string $url URL of the video file
* *
* @return \Symfony\Component\Process\Process Process * @return \Symfony\Component\Process\Process Process
*/ */
private function getCurlProcess($video) private function getAvconvMp3Process($url)
{ {
if (!shell_exec('which '.$this->config->curl)) { if (!shell_exec('which '.$this->config->avconv)) {
throw(new \Exception('Can\'t find curl')); throw(new \Exception('Can\'t find avconv or ffmpeg'));
} }
$builder = ProcessBuilder::create(
array_merge(
[
$this->config->curl,
'--silent',
'--location',
'--user-agent', $video->http_headers->{'User-Agent'},
$video->url,
],
$this->config->curl_params
)
);
return $builder->getProcess(); return ProcessBuilder::create(
[
$this->config->avconv,
'-v', 'quiet',
//Vimeo needs a correct user-agent
'-user-agent', $this->getProp(null, null, 'dump-user-agent'),
'-i', $url,
'-f', 'mp3',
'-vn',
'pipe:1',
]
);
} }
/** /**
@ -260,40 +259,23 @@ class VideoDownload
*/ */
public function getAudioStream($url, $format, $password = null) public function getAudioStream($url, $format, $password = null)
{ {
if (!shell_exec('which '.$this->config->avconv)) {
throw(new \Exception('Can\'t find avconv or ffmpeg'));
}
$video = $this->getJSON($url, $format, $password); $video = $this->getJSON($url, $format, $password);
if (in_array($video->protocol, ['m3u8', 'm3u8_native'])) { if (in_array($video->protocol, ['m3u8', 'm3u8_native'])) {
throw(new \Exception('Conversion of M3U8 files is not supported.')); throw(new \Exception('Conversion of M3U8 files is not supported.'));
} }
//Vimeo needs a correct user-agent
ini_set(
'user_agent',
$video->http_headers->{'User-Agent'}
);
$avconvProc = ProcessBuilder::create(
[
$this->config->avconv,
'-v', 'quiet',
'-i', '-',
'-f', 'mp3',
'-vn',
'pipe:1',
]
);
if (parse_url($video->url, PHP_URL_SCHEME) == 'rtmp') { if (parse_url($video->url, PHP_URL_SCHEME) == 'rtmp') {
$process = $this->getRtmpProcess($video); $process = $this->getRtmpProcess($video);
} else {
$process = $this->getCurlProcess($video);
}
$chain = new Chain($process); $chain = new Chain($process);
$chain->add('|', $avconvProc); $chain->add('|', $this->getAvconvMp3Process('-'));
return popen($chain->getProcess()->getCommandLine(), 'r'); return popen($chain->getProcess()->getCommandLine(), 'r');
} else {
$avconvProc = $this->getAvconvMp3Process($video->url);
//dump($avconvProc->getProcess()); die;
return popen($avconvProc->getProcess()->getCommandLine(), 'r');
}
} }
/** /**

View file

@ -5,10 +5,8 @@ params:
- --no-warnings - --no-warnings
- --playlist-end - --playlist-end
- 1 - 1
curl_params:
convert: false convert: false
avconv: vendor/bin/ffmpeg avconv: vendor/bin/ffmpeg
rtmpdump: vendor/bin/rtmpdump rtmpdump: vendor/bin/rtmpdump
curl: /usr/bin/curl
uglyUrls: false uglyUrls: false
stream: false stream: false

View file

@ -45,7 +45,6 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
public function testGetInstance() public function testGetInstance()
{ {
$this->assertEquals($this->config->convert, false); $this->assertEquals($this->config->convert, false);
$this->assertInternalType('array', $this->config->curl_params);
$this->assertInternalType('array', $this->config->params); $this->assertInternalType('array', $this->config->params);
$this->assertInternalType('string', $this->config->youtubedl); $this->assertInternalType('string', $this->config->youtubedl);
$this->assertInternalType('string', $this->config->python); $this->assertInternalType('string', $this->config->python);

View file

@ -350,11 +350,11 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
* *
* @return void * @return void
* @expectedException Exception * @expectedException Exception
* @dataProvider urlProvider * @dataProvider rtmpUrlProvider
*/ */
public function testGetAudioStreamCurlError($url, $format) public function testGetAudioStreamRtmpError($url, $format)
{ {
$download = new VideoDownload(new Config(['curl'=>'foobar', 'rtmpdump'=>'foobar'])); $download = new VideoDownload(new Config(['rtmpdump'=>'foobar']));
$download->getAudioStream($url, $format); $download->getAudioStream($url, $format);
} }