Merge branch 'release-1.1.0'

This commit is contained in:
Pierre Rudloff 2018-03-20 12:12:22 +01:00
commit 7f6537b5aa
23 changed files with 306 additions and 198 deletions

View File

@ -10,5 +10,5 @@ Before opening a new issue, make sure that:
## Translation
If you want to help translating Alltube in your language,
If you want to help translating AllTube in your language,
you can join our [POEditor project](https://poeditor.com/join/project/GJmE0wN7Xw).

View File

@ -57,7 +57,7 @@ module.exports = function (grunt) {
options: {
archive: 'alltube-<%= githash.main.tag %>.zip'
},
src: ['*.php', 'config/*', '!config/config.yml', 'dist/**', '.htaccess', 'img/**', 'LICENSE', 'README.md', 'robots.txt', 'resources/sitemap.xml', 'resources/manifest.json', 'templates/**', 'templates_c/', 'vendor/**', 'classes/**', 'controllers/**', 'bower_components/**', 'i18n/**', '!vendor/ffmpeg/**', '!vendor/bin/ffmpeg', '!vendor/phpunit/**', '!vendor/squizlabs/**', '!vendor/rinvex/country/resources/geodata/*.json', '!vendor/rinvex/country/resources/flags/*.svg', 'node_modules/open-sans-fontface/fonts/**']
src: ['*.php', 'config/*', '!config/config.yml', 'dist/**', '.htaccess', 'img/**', 'LICENSE', 'README.md', 'robots.txt', 'resources/sitemap.xml', 'resources/manifest.json', 'templates/**', 'templates_c/', 'vendor/**', 'classes/**', 'controllers/**', 'bower_components/**', 'i18n/**', '!vendor/ffmpeg/**', '!vendor/bin/ffmpeg', '!vendor/anam/phantomjs-linux-x86-binary/**', '!vendor/bin/phantomjs', '!vendor/phpunit/**', '!vendor/squizlabs/**', '!vendor/rinvex/country/resources/geodata/*.json', '!vendor/rinvex/country/resources/flags/*.svg', 'node_modules/open-sans-fontface/fonts/**']
}
},
phpdocumentor: {

View File

@ -8,9 +8,9 @@ Please answer these questions when reporting a new issue:
**What is your web server (Apache, IIS, etc.)?**
**What version of Alltube are you using?**
**What version of AllTube are you using?**
**How did you install Alltube (with Git or with a release package)?**
**How did you install AllTube (with Git or with a release package)?**
**What version of PHP are you using?**

View File

@ -1,8 +1,8 @@
# Alltube Download
# AllTube Download
HTML GUI for youtube-dl ([alltubedownload.net](http://alltubedownload.net/))
![Screenshot](img/screenshot.png "Alltube GUI screenshot")
![Screenshot](img/screenshot.png "AllTube GUI screenshot")
## Setup
@ -31,9 +31,12 @@ 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/
chmod 770 templates_c/
```
(You need to adapt this to your permission model.
You can find more information about this [in the Smarty documentation](https://www.smarty.net/docsv2/en/installing.smarty.basic.tpl#id2778738).)
If your web server is Apache,
you need to set the `AllowOverride` setting to `All` or `FileInfo`.
@ -145,7 +148,7 @@ so that it points to your ffmpeg/avconv binary (`/usr/bin/avconv` on Debian/Ubun
## Use as library
Alltube can also be used as a library to extract a video URL from a webpage.
AllTube can also be used as a library to extract a video URL from a webpage.
You can install it with:
@ -176,6 +179,11 @@ The library documentation is available on [alltube.surge.sh](https://alltube.sur
You can also have a look at this [example project](https://github.com/Rudloff/alltube-example-project).
## JSON API
We also provide a JSON API that you can use like this:
[/json?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdQw4w9WgXcQ](https://alltubedownload.net/json?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdQw4w9WgXcQ)
## FAQ
Please read the [FAQ](resources/FAQ.md) before reporting any issue.

View File

@ -5,6 +5,7 @@
namespace Alltube;
use Exception;
use Symfony\Component\Yaml\Yaml;
/**
@ -172,7 +173,7 @@ class Config
*/
$options = [];
} else {
throw new \Exception("Can't find config file at ".$yamlPath);
throw new Exception("Can't find config file at ".$yamlPath);
}
self::$instance = new self($options);
self::$instance->file = $yamlfile;

View File

@ -5,6 +5,8 @@
namespace Alltube;
use Locale as PHPLocale;
use Rinvex\Country\Country;
use Teto\HTTP\AcceptLanguage;
/**
@ -55,7 +57,7 @@ class Locale
*/
public function getFullName()
{
return \Locale::getDisplayName($this->getIso15897(), $this->getIso15897());
return PHPLocale::getDisplayName($this->getIso15897(), $this->getIso15897());
}
/**
@ -91,7 +93,7 @@ class Locale
/**
* Get country information from locale.
*
* @return \Rinvex\Country\Country|array
* @return Country|array
*/
public function getCountry()
{

View File

@ -5,6 +5,8 @@
namespace Alltube;
use Aura\Session\Segment;
use Aura\Session\SessionFactory;
use Symfony\Component\Process\Process;
/**
@ -29,7 +31,7 @@ class LocaleManager
/**
* Session segment used to store session variables.
*
* @var \Aura\Session\Segment
* @var Segment
*/
private $sessionSegment;
@ -40,9 +42,9 @@ class LocaleManager
*/
public function __construct(array $cookies = [])
{
$session_factory = new \Aura\Session\SessionFactory();
$session_factory = new SessionFactory();
$session = $session_factory->newInstance($cookies);
$this->sessionSegment = $session->getSegment('Alltube\LocaleManager');
$this->sessionSegment = $session->getSegment(self::class);
$cookieLocale = $this->sessionSegment->get('locale');
if (isset($cookieLocale)) {
$this->setLocale(new Locale($cookieLocale));

View File

@ -5,9 +5,11 @@
namespace Alltube;
use Exception;
/**
* Exception thrown when a video requires a password.
*/
class PasswordException extends \Exception
class PasswordException extends Exception
{
}

View File

@ -8,6 +8,7 @@
namespace Alltube;
use Barracuda\ArchiveStream\TarArchive;
use GuzzleHttp\Client;
/**
* Class used to create a Tar archive from playlists and stream it to the browser.
@ -33,7 +34,7 @@ class PlaylistArchiveStream extends TarArchive
/**
* Guzzle client.
*
* @var \GuzzleHttp\Client
* @var Client
*/
private $client;
@ -65,7 +66,7 @@ class PlaylistArchiveStream extends TarArchive
*/
public function __construct(Config $config = null)
{
$this->client = new \GuzzleHttp\Client();
$this->client = new Client();
$this->download = new VideoDownload($config);
}

View File

@ -5,7 +5,9 @@
namespace Alltube;
use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;
use Slim\Router;
/**
@ -43,8 +45,8 @@ class UglyRouter extends Router
* @param array $data Named argument replacement data
* @param array $queryParams Optional query string parameters
*
* @throws \RuntimeException If named route does not exist
* @throws \InvalidArgumentException If required data not provided
* @throws RuntimeException If named route does not exist
* @throws InvalidArgumentException If required data not provided
*
* @return string
*/

View File

@ -5,6 +5,8 @@
namespace Alltube;
use Exception;
use stdClass;
use Symfony\Component\Process\Process;
/**
@ -24,8 +26,8 @@ class VideoDownload
*
* @param Config $config Config instance.
*
* @throws \Exception If youtube-dl is missing
* @throws \Exception If Python is missing
* @throws Exception If youtube-dl is missing
* @throws Exception If Python is missing
*/
public function __construct(Config $config = null)
{
@ -39,9 +41,9 @@ class VideoDownload
so they will always go to the logs.
*/
if (!is_file($this->config->youtubedl)) {
throw new \Exception("Can't find youtube-dl at ".$this->config->youtubedl);
throw new Exception("Can't find youtube-dl at ".$this->config->youtubedl);
} elseif (!$this->checkCommand([$this->config->python, '--version'])) {
throw new \Exception("Can't find Python at ".$this->config->python);
throw new Exception("Can't find Python at ".$this->config->python);
}
}
@ -82,8 +84,8 @@ class VideoDownload
* @param string $password Video password
*
* @throws PasswordException If the video is protected by a password and no password was specified
* @throws \Exception If the password is wrong
* @throws \Exception If youtube-dl returns an error
* @throws Exception If the password is wrong
* @throws Exception If youtube-dl returns an error
*
* @return string
*/
@ -108,12 +110,13 @@ class VideoDownload
$process->run();
if (!$process->isSuccessful()) {
$errorOutput = trim($process->getErrorOutput());
$exitCode = $process->getExitCode();
if ($errorOutput == 'ERROR: This video is protected by a password, use the --video-password option') {
throw new PasswordException($errorOutput);
throw new PasswordException($errorOutput, $exitCode);
} elseif (substr($errorOutput, 0, 21) == 'ERROR: Wrong password') {
throw new \Exception(_('Wrong password'));
throw new Exception(_('Wrong password'), $exitCode);
} else {
throw new \Exception($errorOutput);
throw new Exception($errorOutput, $exitCode);
}
} else {
return trim($process->getOutput());
@ -209,7 +212,7 @@ class VideoDownload
*
* @return array Arguments
*/
private function getRtmpArguments(\stdClass $video)
private function getRtmpArguments(stdClass $video)
{
$arguments = [];
@ -260,14 +263,14 @@ class VideoDownload
* @param string $filetype Filetype of the converted file
* @param bool $audioOnly True to return an audio-only file
*
* @throws \Exception If avconv/ffmpeg is missing
* @throws Exception If avconv/ffmpeg is missing
*
* @return Process Process
*/
private function getAvconvProcess(\stdClass $video, $audioBitrate, $filetype = 'mp3', $audioOnly = true)
private function getAvconvProcess(stdClass $video, $audioBitrate, $filetype = 'mp3', $audioOnly = true)
{
if (!$this->checkCommand([$this->config->avconv, '-version'])) {
throw(new \Exception(_('Can\'t find avconv or ffmpeg.')));
throw new Exception(_('Can\'t find avconv or ffmpeg at ').$this->config->avconv.'.');
}
if ($video->protocol == 'rtmp') {
@ -314,8 +317,8 @@ class VideoDownload
* @param string $format Format to use for the video
* @param string $password Video password
*
* @throws \Exception If your try to convert and M3U8 video
* @throws \Exception If the popen stream was not created correctly
* @throws Exception If your try to convert and M3U8 video
* @throws Exception If the popen stream was not created correctly
*
* @return resource popen stream
*/
@ -323,7 +326,7 @@ class VideoDownload
{
$video = $this->getJSON($url, $format, $password);
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.'));
}
$avconvProc = $this->getAvconvProcess($video, $this->config->audioBitrate);
@ -331,7 +334,7 @@ class VideoDownload
$stream = popen($avconvProc->getCommandLine(), 'r');
if (!is_resource($stream)) {
throw new \Exception(_('Could not open popen stream.'));
throw new Exception(_('Could not open popen stream.'));
}
return $stream;
@ -340,17 +343,17 @@ class VideoDownload
/**
* Get video stream from an M3U playlist.
*
* @param \stdClass $video Video object returned by getJSON
* @param stdClass $video Video object returned by getJSON
*
* @throws \Exception If avconv/ffmpeg is missing
* @throws \Exception If the popen stream was not created correctly
* @throws Exception If avconv/ffmpeg is missing
* @throws Exception If the popen stream was not created correctly
*
* @return resource popen stream
*/
public function getM3uStream(\stdClass $video)
public function getM3uStream(stdClass $video)
{
if (!$this->checkCommand([$this->config->avconv, '-version'])) {
throw(new \Exception(_('Can\'t find avconv or ffmpeg.')));
throw new Exception(_('Can\'t find avconv or ffmpeg at ').$this->config->avconv.'.');
}
$process = new Process(
@ -368,7 +371,7 @@ class VideoDownload
$stream = popen($process->getCommandLine(), 'r');
if (!is_resource($stream)) {
throw new \Exception(_('Could not open popen stream.'));
throw new Exception(_('Could not open popen stream.'));
}
return $stream;
@ -379,7 +382,7 @@ class VideoDownload
*
* @param array $urls URLs of the video ($urls[0]) and audio ($urls[1]) files
*
* @throws \Exception If the popen stream was not created correctly
* @throws Exception If the popen stream was not created correctly
*
* @return resource popen stream
*/
@ -401,7 +404,7 @@ class VideoDownload
$stream = popen($process->getCommandLine(), 'r');
if (!is_resource($stream)) {
throw new \Exception(_('Could not open popen stream.'));
throw new Exception(_('Could not open popen stream.'));
}
return $stream;
@ -410,13 +413,13 @@ class VideoDownload
/**
* Get video stream from an RTMP video.
*
* @param \stdClass $video Video object returned by getJSON
* @param stdClass $video Video object returned by getJSON
*
* @throws \Exception If the popen stream was not created correctly
* @throws Exception If the popen stream was not created correctly
*
* @return resource popen stream
*/
public function getRtmpStream(\stdClass $video)
public function getRtmpStream(stdClass $video)
{
$process = new Process(
array_merge(
@ -434,7 +437,7 @@ class VideoDownload
);
$stream = popen($process->getCommandLine(), 'r');
if (!is_resource($stream)) {
throw new \Exception(_('Could not open popen stream.'));
throw new Exception(_('Could not open popen stream.'));
}
return $stream;
@ -446,11 +449,11 @@ class VideoDownload
* @param object $video Video object returned by youtube-dl
* @param string $format Requested format
*
* @throws \Exception If the popen stream was not created correctly
* @throws Exception If the popen stream was not created correctly
*
* @return resource
*/
public function getPlaylistArchiveStream(\stdClass $video, $format)
public function getPlaylistArchiveStream(stdClass $video, $format)
{
$playlistItems = [];
foreach ($video->entries as $entry) {
@ -458,7 +461,7 @@ class VideoDownload
}
$stream = fopen('playlist://'.implode(';', $playlistItems).'/'.$format, 'r');
if (!is_resource($stream)) {
throw new \Exception(_('Could not open fopen stream.'));
throw new Exception(_('Could not open fopen stream.'));
}
return $stream;
@ -473,8 +476,8 @@ class VideoDownload
* @param string $filetype Filetype of the converted file
* @param string $password Video password
*
* @throws \Exception If your try to convert and M3U8 video
* @throws \Exception If the popen stream was not created correctly
* @throws Exception If your try to convert and M3U8 video
* @throws Exception If the popen stream was not created correctly
*
* @return resource popen stream
*/
@ -482,7 +485,7 @@ class VideoDownload
{
$video = $this->getJSON($url, $format, $password);
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.'));
}
$avconvProc = $this->getAvconvProcess($video, $audioBitrate, $filetype, false);
@ -490,7 +493,7 @@ class VideoDownload
$stream = popen($avconvProc->getCommandLine(), 'r');
if (!is_resource($stream)) {
throw new \Exception(_('Could not open popen stream.'));
throw new Exception(_('Could not open popen stream.'));
}
return $stream;

View File

@ -23,7 +23,7 @@
"phpunit/phpunit": "~6.5.2",
"doctrine/instantiator": "~1.0.0",
"ffmpeg/ffmpeg": "~3.4.1",
"rg3/youtube-dl": "2018.01.21",
"rg3/youtube-dl": "2018.03.20",
"heroku/heroku-buildpack-php": "*",
"anam/phantomjs-linux-x86-binary": "~2.1.1"
},
@ -39,10 +39,10 @@
"type": "package",
"package": {
"name": "rg3/youtube-dl",
"version": "2018.01.21",
"version": "2018.03.20",
"dist": {
"type": "zip",
"url": "https://github.com/rg3/youtube-dl/archive/2018.01.21.zip"
"url": "https://github.com/rg3/youtube-dl/archive/2018.03.20.zip"
}
}
},

137
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "4252f8c5d568e5b9854a84da162e621c",
"content-hash": "9609172b4f93eda8b344d78f57053dc5",
"packages": [
{
"name": "aura/session",
@ -485,21 +485,24 @@
},
{
"name": "nikic/fast-route",
"version": "v1.2.0",
"version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/FastRoute.git",
"reference": "b5f95749071c82a8e0f58586987627054400cdf6"
"reference": "181d480e08d9476e61381e04a71b34dc0432e812"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/b5f95749071c82a8e0f58586987627054400cdf6",
"reference": "b5f95749071c82a8e0f58586987627054400cdf6",
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812",
"reference": "181d480e08d9476e61381e04a71b34dc0432e812",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35|~5.7"
},
"type": "library",
"autoload": {
"psr-4": {
@ -524,7 +527,7 @@
"router",
"routing"
],
"time": "2017-01-19T11:35:12+00:00"
"time": "2018-02-13T20:26:39+00:00"
},
{
"name": "php-mock/php-mock",
@ -1139,16 +1142,16 @@
},
{
"name": "symfony/process",
"version": "v3.4.3",
"version": "v3.4.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "ff69f110c6b33fd33cd2089ba97d6112f44ef0ba"
"reference": "cc4aea21f619116aaf1c58016a944e4821c8e8af"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/ff69f110c6b33fd33cd2089ba97d6112f44ef0ba",
"reference": "ff69f110c6b33fd33cd2089ba97d6112f44ef0ba",
"url": "https://api.github.com/repos/symfony/process/zipball/cc4aea21f619116aaf1c58016a944e4821c8e8af",
"reference": "cc4aea21f619116aaf1c58016a944e4821c8e8af",
"shasum": ""
},
"require": {
@ -1184,20 +1187,20 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"time": "2018-01-03T07:37:34+00:00"
"time": "2018-02-12T17:55:00+00:00"
},
{
"name": "symfony/yaml",
"version": "v3.4.3",
"version": "v3.4.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "25c192f25721a74084272671f658797d9e0e0146"
"reference": "6af42631dcf89e9c616242c900d6c52bd53bd1bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/25c192f25721a74084272671f658797d9e0e0146",
"reference": "25c192f25721a74084272671f658797d9e0e0146",
"url": "https://api.github.com/repos/symfony/yaml/zipball/6af42631dcf89e9c616242c900d6c52bd53bd1bb",
"reference": "6af42631dcf89e9c616242c900d6c52bd53bd1bb",
"shasum": ""
},
"require": {
@ -1242,7 +1245,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2018-01-03T07:37:34+00:00"
"time": "2018-02-16T09:50:28+00:00"
},
{
"name": "zonuexe/http-accept-language",
@ -1399,16 +1402,16 @@
},
{
"name": "heroku/heroku-buildpack-php",
"version": "v130",
"version": "v132",
"source": {
"type": "git",
"url": "https://github.com/heroku/heroku-buildpack-php.git",
"reference": "1bbbc45da0f80dbb75606972c26236172b7d724c"
"reference": "dd950a605fb0c5e50ab71774e299fa26c9093f80"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/heroku/heroku-buildpack-php/zipball/1bbbc45da0f80dbb75606972c26236172b7d724c",
"reference": "1bbbc45da0f80dbb75606972c26236172b7d724c",
"url": "https://api.github.com/repos/heroku/heroku-buildpack-php/zipball/dd950a605fb0c5e50ab71774e299fa26c9093f80",
"reference": "dd950a605fb0c5e50ab71774e299fa26c9093f80",
"shasum": ""
},
"bin": [
@ -1439,7 +1442,7 @@
"nginx",
"php"
],
"time": "2018-01-11T17:45:21+00:00"
"time": "2018-03-02T17:10:10+00:00"
},
{
"name": "myclabs/deep-copy",
@ -1644,16 +1647,16 @@
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "4.2.0",
"version": "4.3.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "66465776cfc249844bde6d117abff1d22e06c2da"
"reference": "94fd0001232e47129dd3504189fa1c7225010d08"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/66465776cfc249844bde6d117abff1d22e06c2da",
"reference": "66465776cfc249844bde6d117abff1d22e06c2da",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08",
"reference": "94fd0001232e47129dd3504189fa1c7225010d08",
"shasum": ""
},
"require": {
@ -1691,7 +1694,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": "2017-11-27T17:38:31+00:00"
"time": "2017-11-30T07:14:17+00:00"
},
{
"name": "phpdocumentor/type-resolver",
@ -1742,16 +1745,16 @@
},
{
"name": "phpspec/prophecy",
"version": "1.7.3",
"version": "1.7.5",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf"
"reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf",
"reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401",
"reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401",
"shasum": ""
},
"require": {
@ -1763,7 +1766,7 @@
},
"require-dev": {
"phpspec/phpspec": "^2.5|^3.2",
"phpunit/phpunit": "^4.8.35 || ^5.7"
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5"
},
"type": "library",
"extra": {
@ -1801,7 +1804,7 @@
"spy",
"stub"
],
"time": "2017-11-24T13:59:53+00:00"
"time": "2018-02-19T10:16:54+00:00"
},
{
"name": "phpunit/php-code-coverage",
@ -2013,16 +2016,16 @@
},
{
"name": "phpunit/phpunit",
"version": "6.5.5",
"version": "6.5.7",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "83d27937a310f2984fd575686138597147bdc7df"
"reference": "6bd77b57707c236833d2b57b968e403df060c9d9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/83d27937a310f2984fd575686138597147bdc7df",
"reference": "83d27937a310f2984fd575686138597147bdc7df",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6bd77b57707c236833d2b57b968e403df060c9d9",
"reference": "6bd77b57707c236833d2b57b968e403df060c9d9",
"shasum": ""
},
"require": {
@ -2093,7 +2096,7 @@
"testing",
"xunit"
],
"time": "2017-12-17T06:31:19+00:00"
"time": "2018-02-26T07:01:09+00:00"
},
{
"name": "phpunit/phpunit-mock-objects",
@ -2156,10 +2159,10 @@
},
{
"name": "rg3/youtube-dl",
"version": "2018.01.21",
"version": "2018.03.20",
"dist": {
"type": "zip",
"url": "https://github.com/rg3/youtube-dl/archive/2018.01.21.zip",
"url": "https://github.com/rg3/youtube-dl/archive/2018.03.20.zip",
"reference": null,
"shasum": null
},
@ -2212,21 +2215,21 @@
},
{
"name": "sebastian/comparator",
"version": "2.1.2",
"version": "2.1.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "11c07feade1d65453e06df3b3b90171d6d982087"
"reference": "34369daee48eafb2651bea869b4b15d75ccc35f9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/11c07feade1d65453e06df3b3b90171d6d982087",
"reference": "11c07feade1d65453e06df3b3b90171d6d982087",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9",
"reference": "34369daee48eafb2651bea869b4b15d75ccc35f9",
"shasum": ""
},
"require": {
"php": "^7.0",
"sebastian/diff": "^2.0",
"sebastian/diff": "^2.0 || ^3.0",
"sebastian/exporter": "^3.1"
},
"require-dev": {
@ -2272,7 +2275,7 @@
"compare",
"equality"
],
"time": "2018-01-12T06:34:42+00:00"
"time": "2018-02-01T13:46:46+00:00"
},
{
"name": "sebastian/diff",
@ -2726,16 +2729,16 @@
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.2.2",
"version": "3.2.3",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "d7c00c3000ac0ce79c96fcbfef86b49a71158cd1"
"reference": "4842476c434e375f9d3182ff7b89059583aa8b27"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d7c00c3000ac0ce79c96fcbfef86b49a71158cd1",
"reference": "d7c00c3000ac0ce79c96fcbfef86b49a71158cd1",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4842476c434e375f9d3182ff7b89059583aa8b27",
"reference": "4842476c434e375f9d3182ff7b89059583aa8b27",
"shasum": ""
},
"require": {
@ -2745,7 +2748,7 @@
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0"
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
@ -2773,20 +2776,20 @@
"phpcs",
"standards"
],
"time": "2017-12-19T21:44:46+00:00"
"time": "2018-02-20T21:35:23+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.6.0",
"version": "v1.7.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296"
"reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
"reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b",
"reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b",
"shasum": ""
},
"require": {
@ -2798,7 +2801,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6-dev"
"dev-master": "1.7-dev"
}
},
"autoload": {
@ -2832,20 +2835,20 @@
"portable",
"shim"
],
"time": "2017-10-11T12:05:26+00:00"
"time": "2018-01-30T19:27:44+00:00"
},
{
"name": "symfony/var-dumper",
"version": "v3.4.3",
"version": "v3.4.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "545be7e78ccbec43e599f10ff7500d0b09eda9d0"
"reference": "80964679d81da3d5618519e0e4be488c3d7ecd7d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/545be7e78ccbec43e599f10ff7500d0b09eda9d0",
"reference": "545be7e78ccbec43e599f10ff7500d0b09eda9d0",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/80964679d81da3d5618519e0e4be488c3d7ecd7d",
"reference": "80964679d81da3d5618519e0e4be488c3d7ecd7d",
"shasum": ""
},
"require": {
@ -2901,7 +2904,7 @@
"debug",
"dump"
],
"time": "2018-01-03T17:14:19+00:00"
"time": "2018-02-22T17:29:24+00:00"
},
{
"name": "theseer/tokenizer",
@ -2945,16 +2948,16 @@
},
{
"name": "webmozart/assert",
"version": "1.2.0",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f"
"reference": "0df1908962e7a3071564e857d86874dad1ef204a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f",
"reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f",
"url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a",
"reference": "0df1908962e7a3071564e857d86874dad1ef204a",
"shasum": ""
},
"require": {
@ -2991,7 +2994,7 @@
"check",
"validate"
],
"time": "2016-11-23T20:04:58+00:00"
"time": "2018-01-29T19:49:41+00:00"
}
],
"aliases": [],

View File

@ -10,11 +10,16 @@ use Alltube\Locale;
use Alltube\LocaleManager;
use Alltube\PasswordException;
use Alltube\VideoDownload;
use Aura\Session\Segment;
use Aura\Session\SessionFactory;
use Exception;
use GuzzleHttp\Client;
use Psr\Container\ContainerInterface;
use Slim\Container;
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Http\Stream;
use Slim\Views\Smarty;
/**
* Main controller.
@ -45,14 +50,14 @@ class FrontController
/**
* Session segment used to store session variables.
*
* @var \Aura\Session\Segment
* @var Segment
*/
private $sessionSegment;
/**
* Smarty view.
*
* @var \Slim\Views\Smarty
* @var Smarty
*/
private $view;
@ -88,9 +93,9 @@ class FrontController
$this->container = $container;
$this->view = $this->container->get('view');
$this->localeManager = $this->container->get('locale');
$session_factory = new \Aura\Session\SessionFactory();
$session_factory = new SessionFactory();
$session = $session_factory->newInstance($cookies);
$this->sessionSegment = $session->getSegment('Alltube\Controller\FrontController');
$this->sessionSegment = $session->getSegment(self::class);
if ($this->config->stream) {
$this->defaultFormat = 'best';
}
@ -214,7 +219,7 @@ class FrontController
}
} catch (PasswordException $e) {
return $this->password($request, $response);
} catch (\Exception $e) {
} catch (Exception $e) {
$response = $response->withHeader(
'Content-Disposition',
'attachment; filename="'.
@ -311,13 +316,13 @@ class FrontController
/**
* Display an error page.
*
* @param Request $request PSR-7 request
* @param Response $response PSR-7 response
* @param \Exception $exception Error to display
* @param Request $request PSR-7 request
* @param Response $response PSR-7 response
* @param Exception $exception Error to display
*
* @return Response HTTP response
*/
public function error(Request $request, Response $response, \Exception $exception)
public function error(Request $request, Response $response, Exception $exception)
{
$this->view->render(
$response,
@ -366,7 +371,7 @@ class FrontController
$response = $response->withHeader('Content-Type', 'video/'.$video->ext);
$body = new Stream($stream);
} else {
$client = new \GuzzleHttp\Client();
$client = new 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'));
@ -397,7 +402,7 @@ class FrontController
private function getRemuxStream(array $urls, $format, Response $response, Request $request)
{
if (!$this->config->remux) {
throw new \Exception(_('You need to enable remux mode to merge two formats.'));
throw new Exception(_('You need to enable remux mode to merge two formats.'));
}
$stream = $this->download->getRemuxStream($urls);
$response = $response->withHeader('Content-Type', 'video/x-matroska');
@ -464,7 +469,7 @@ class FrontController
);
} else {
if (empty($videoUrls[0])) {
throw new \Exception(_("Can't find URL of video."));
throw new Exception(_("Can't find URL of video."));
}
return $response->withRedirect($videoUrls[0]);
@ -533,7 +538,7 @@ class FrontController
return $response->withRedirect(
$this->container->get('router')->pathFor('video').'?url='.urlencode($params['url'])
);
} catch (\Exception $e) {
} catch (Exception $e) {
$response->getBody()->write($e->getMessage());
return $response->withHeader('Content-Type', 'text/plain')->withStatus(500);
@ -543,6 +548,36 @@ class FrontController
}
}
/**
* Return the JSON object generated by youtube-dl.
*
* @param Request $request PSR-7 request
* @param Response $response PSR-7 response
*
* @return Response HTTP response
*/
public function json(Request $request, Response $response)
{
$params = $request->getQueryParams();
$format = $this->getFormat($request);
if (isset($params['url'])) {
try {
return $response->withJson(
$this->download->getJSON(
$params['url'],
$format
)
);
} catch (Exception $e) {
return $response->withJson(['error' => $e->getMessage()])
->withStatus(500);
}
} else {
return $response->withJson(['error' => 'You need to provide the url parameter'])
->withStatus(400);
}
}
/**
* Generate the canonical URL of the current page.
*

View File

@ -21,7 +21,7 @@ msgstr " :"
#: templates/playlist.tpl:26 templates/password.tpl:10 templates/video.tpl:97
#: templates/video.tpl:100 templates/index.tpl:19
#: controllers/FrontController.php:265
#: controllers/FrontController.php:270
msgid "Download"
msgstr "Télécharger"
@ -41,7 +41,7 @@ msgstr "L'accès à cette vidéo nécessite un mot de passe."
msgid "Video password"
msgstr "Mot de passe de la vidéo"
#: templates/extractors.tpl:4 controllers/FrontController.php:159
#: templates/extractors.tpl:4 controllers/FrontController.php:164
msgid "Supported websites"
msgstr "Sites web supportés"
@ -145,65 +145,65 @@ msgstr "kbit/s"
msgid "with"
msgstr "avec de l'audio à"
#: classes/VideoDownload.php:114
#: classes/VideoDownload.php:117
msgid "Wrong password"
msgstr "Mauvais mot de passe"
#: classes/VideoDownload.php:270 classes/VideoDownload.php:353
msgid "Can't find avconv or ffmpeg."
msgstr "Impossible de trouver avconv ou ffmpeg."
#: classes/VideoDownload.php:326 classes/VideoDownload.php:485
#: classes/VideoDownload.php:329 classes/VideoDownload.php:488
msgid "Conversion of M3U8 files is not supported."
msgstr "La conversion des fichiers M3U8 n'est pas possible."
#: classes/VideoDownload.php:334 classes/VideoDownload.php:371
#: classes/VideoDownload.php:404 classes/VideoDownload.php:437
#: classes/VideoDownload.php:493
#: classes/VideoDownload.php:337 classes/VideoDownload.php:374
#: classes/VideoDownload.php:407 classes/VideoDownload.php:440
#: classes/VideoDownload.php:496
msgid "Could not open popen stream."
msgstr "Impossible d'ouvrir le flux popen."
#: classes/VideoDownload.php:461
#: classes/VideoDownload.php:464
msgid "Could not open fopen stream."
msgstr "Impossible d'ouvrir le flux fopen."
#: controllers/FrontController.php:116
#: controllers/FrontController.php:121
msgid "Easily download videos from Youtube, Dailymotion, Vimeo and other websites."
msgstr "Téléchargez facilement des vidéos depuis Youtube, Dailymotion, Vimeo et d'autres sites web."
#: controllers/FrontController.php:160
#: controllers/FrontController.php:165
msgid "List of all supported websites from which Alltube Download can extract video or audio files"
msgstr "Liste de tous les sites web depuis lesquels Alltube Download peut extraire des fichiers vidéo ou audio"
#: controllers/FrontController.php:185
#: controllers/FrontController.php:190
msgid "Password prompt"
msgstr "Demande de mot de passe"
#: controllers/FrontController.php:186
#: controllers/FrontController.php:191
msgid "You need a password in order to download this video with Alltube Download"
msgstr "Vous avez besoin d'un mot de passe pour télécharger cette vidéo avec Alltube Download"
#: controllers/FrontController.php:261
#: controllers/FrontController.php:266
msgid "Video download"
msgstr "Téléchargement d'une vidéo"
#: controllers/FrontController.php:262
#: controllers/FrontController.php:267
msgid "Download video from "
msgstr "Téléchargement d'une vidéo depuis "
#: controllers/FrontController.php:265
#: controllers/FrontController.php:270
msgid "from"
msgstr "depuis"
#: controllers/FrontController.php:328
#: controllers/FrontController.php:333
msgid "Error"
msgstr "Erreur"
#: controllers/FrontController.php:400
#: controllers/FrontController.php:405
msgid "You need to enable remux mode to merge two formats."
msgstr "Vous devez activer le mode remux pour fusionner deux formats."
#: controllers/FrontController.php:467
#: controllers/FrontController.php:472
msgid "Can't find URL of video."
msgstr "Impossible de trouver l'URL de la vidéo."
#: classes/VideoDownload.php:273 classes/VideoDownload.php:356
msgid "Can't find avconv or ffmpeg at "
msgstr "Impossible de trouver avconv ou ffmpeg à "

View File

@ -19,7 +19,7 @@ msgstr ""
#: templates/playlist.tpl:26 templates/password.tpl:10 templates/video.tpl:97
#: templates/video.tpl:100 templates/index.tpl:19
#: controllers/FrontController.php:265
#: controllers/FrontController.php:270
msgid "Download"
msgstr ""
@ -39,7 +39,7 @@ msgstr ""
msgid "Video password"
msgstr ""
#: templates/extractors.tpl:4 controllers/FrontController.php:159
#: templates/extractors.tpl:4 controllers/FrontController.php:164
msgid "Supported websites"
msgstr ""
@ -139,68 +139,68 @@ msgstr ""
msgid "Bookmarklet"
msgstr ""
#: classes/VideoDownload.php:114
#: classes/VideoDownload.php:117
msgid "Wrong password"
msgstr ""
#: classes/VideoDownload.php:270 classes/VideoDownload.php:353
msgid "Can't find avconv or ffmpeg."
#: classes/VideoDownload.php:273 classes/VideoDownload.php:356
msgid "Can't find avconv or ffmpeg at "
msgstr ""
#: classes/VideoDownload.php:326 classes/VideoDownload.php:485
#: classes/VideoDownload.php:329 classes/VideoDownload.php:488
msgid "Conversion of M3U8 files is not supported."
msgstr ""
#: classes/VideoDownload.php:334 classes/VideoDownload.php:371
#: classes/VideoDownload.php:404 classes/VideoDownload.php:437
#: classes/VideoDownload.php:493
#: classes/VideoDownload.php:337 classes/VideoDownload.php:374
#: classes/VideoDownload.php:407 classes/VideoDownload.php:440
#: classes/VideoDownload.php:496
msgid "Could not open popen stream."
msgstr ""
#: classes/VideoDownload.php:461
#: classes/VideoDownload.php:464
msgid "Could not open fopen stream."
msgstr ""
#: controllers/FrontController.php:116
#: controllers/FrontController.php:121
msgid ""
"Easily download videos from Youtube, Dailymotion, Vimeo and other websites."
msgstr ""
#: controllers/FrontController.php:160
#: controllers/FrontController.php:165
msgid ""
"List of all supported websites from which Alltube Download can extract video "
"or audio files"
msgstr ""
#: controllers/FrontController.php:185
#: controllers/FrontController.php:190
msgid "Password prompt"
msgstr ""
#: controllers/FrontController.php:186
#: controllers/FrontController.php:191
msgid ""
"You need a password in order to download this video with Alltube Download"
msgstr ""
#: controllers/FrontController.php:261
#: controllers/FrontController.php:266
msgid "Video download"
msgstr ""
#: controllers/FrontController.php:262
#: controllers/FrontController.php:267
msgid "Download video from "
msgstr ""
#: controllers/FrontController.php:265
#: controllers/FrontController.php:270
msgid "from"
msgstr ""
#: controllers/FrontController.php:328
#: controllers/FrontController.php:333
msgid "Error"
msgstr ""
#: controllers/FrontController.php:400
#: controllers/FrontController.php:405
msgid "You need to enable remux mode to merge two formats."
msgstr ""
#: controllers/FrontController.php:467
#: controllers/FrontController.php:472
msgid "Can't find URL of video."
msgstr ""

View File

@ -51,6 +51,10 @@ $app->get(
'/redirect',
[$controller, 'redirect']
)->setName('redirect');
$app->get(
'/json',
[$controller, 'json']
)->setName('json');
$app->get(
'/locale/{locale}',
[$controller, 'locale']
@ -58,6 +62,6 @@ $app->get(
try {
$app->run();
} catch (\SmartyException $e) {
} catch (SmartyException $e) {
die('Smarty could not compile the template file: '.$e->getMessage());
}

View File

@ -1,7 +1,7 @@
{
"name": "alltube",
"description": "HTML GUI for youtube-dl",
"version": "1.0.0",
"version": "1.1.0",
"author": "Pierre Rudloff",
"bugs": "https://github.com/Rudloff/alltube/issues",
"dependencies": {

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpdoc>
<title>Alltube Download library documentation</title>
<title>AllTube Download library documentation</title>
</phpdoc>

View File

@ -30,7 +30,7 @@ You will also need to install `avconv` on your server:
sudo apt-get install libav-tools
```
## How do I deploy Alltube on Heroku?
## How do I deploy AllTube on Heroku?
Create a dyno with the following buildpacks:
@ -50,12 +50,12 @@ 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
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 run AllTube locally on your computer.
* You can enable streaming videos through the server (see below).
Please note that this can use a lot of resources on the server
(which is why we won't enable it on alltubedownload.net).
@ -94,7 +94,7 @@ You need to enable streaming (see above).
## The downloaded videos have a strange name like `videoplayback.mp4`
Alltube can rename videos automatically if you enable streaming (see above).
AllTube can rename videos automatically if you enable streaming (see above).
## I want to download a video that isn't available in my country
@ -134,7 +134,7 @@ chmod 0667 /tmp/heroku.fcgi.5000.sock
## How can I download 1080p videos from Youtube?
Youtube distributes HD content in two separate video and audio files.
So Alltube will offer you video-only and audio-only formats in the format list.
So AllTube will offer you video-only and audio-only formats in the format list.
You then need to merge them together with a tool like ffmpeg.

View File

@ -9,6 +9,7 @@ use Alltube\Config;
use Alltube\Controller\FrontController;
use Alltube\LocaleManager;
use Alltube\ViewFactory;
use Exception;
use PHPUnit\Framework\TestCase;
use Slim\Container;
use Slim\Http\Environment;
@ -146,7 +147,7 @@ class FrontControllerTest extends TestCase
}
/**
* Assert that calling controller function with these parameters returns an HTTP redirect.
* Assert that calling controller function with these parameters returns an HTTP 500 error.
*
* @param string $request Controller function to call
* @param array $params Query parameters
@ -159,6 +160,20 @@ class FrontControllerTest extends TestCase
$this->assertTrue($this->getRequestResult($request, $params, $config)->isServerError());
}
/**
* Assert that calling controller function with these parameters returns an HTTP 400 error.
*
* @param string $request Controller function to call
* @param array $params Query parameters
* @param Config $config Custom config
*
* @return void
*/
private function assertRequestIsClientError($request, array $params = [], Config $config = null)
{
$this->assertTrue($this->getRequestResult($request, $params, $config)->isClientError());
}
/**
* Test the constructor.
*
@ -348,7 +363,7 @@ class FrontControllerTest extends TestCase
*/
public function testError()
{
$result = $this->controller->error($this->request, $this->response, new \Exception('foo'));
$result = $this->controller->error($this->request, $this->response, new Exception('foo'));
$this->assertTrue($result->isServerError());
}
@ -428,7 +443,7 @@ class FrontControllerTest extends TestCase
$this->config->stream = true;
$this->assertRequestIsOk(
'redirect',
['url' => 'http://www.canalc2.tv/video/12163', 'format' => 'rtmp'],
['url' => 'http://www.rtvnh.nl/video/131946', 'format' => 'rtmp-264'],
$this->config
);
}
@ -538,6 +553,36 @@ class FrontControllerTest extends TestCase
);
}
/**
* Test the json() function without the URL parameter.
*
* @return void
*/
public function testJsonWithoutUrl()
{
$this->assertRequestIsClientError('json');
}
/**
* Test the json() function.
*
* @return void
*/
public function testJson()
{
$this->assertRequestIsOk('json', ['url' => 'https://www.youtube.com/watch?v=M7IpKCZ47pU']);
}
/**
* Test the json() function with an error.
*
* @return void
*/
public function testJsonWithError()
{
$this->assertRequestIsServerError('json', ['url' => 'http://example.com/foo']);
}
/**
* Test the locale() function.
*

View File

@ -27,7 +27,7 @@ class LocaleManagerTest extends TestCase
protected function setUp()
{
$this->localeManager = new LocaleManager();
$_SESSION['Alltube\LocaleManager']['locale'] = 'foo_BAR';
$_SESSION[LocaleManager::class]['locale'] = 'foo_BAR';
}
/**

View File

@ -126,7 +126,7 @@ class VideoDownloadTest extends TestCase
* Test getURL function with a protected video and no password.
*
* @return void
* @expectedException \Alltube\PasswordException
* @expectedException Alltube\PasswordException
*/
public function testGetURLWithMissingPassword()
{
@ -198,8 +198,8 @@ class VideoDownloadTest extends TestCase
'edgefcs.net',
],
[
'https://openload.co/embed/qTsjMEUtN4U', 'best[protocol^=http]',
'aup-the-lego-ninjago-movie-2017-1508463762.MP4.mp4-qTsjMEUtN4U',
'https://openload.co/f/kUEfGclsU9o', 'best[protocol^=http]',
'skyrim_no-audio_1080.mp4-kUEfGclsU9o',
'mp4',
'openload.co',
],
@ -249,10 +249,10 @@ class VideoDownloadTest extends TestCase
{
return [
[
'http://www.canalc2.tv/video/12163', 'rtmp',
'Terrasses_du_Numerique-12163',
'http://www.rtvnh.nl/video/131946', 'rtmp-264',
'Ketting_van_strandgasten-131946',
'flv',
'vod-flash.u-strasbg.fr',
'lb-nh-vod.cdn.streamgate.nl',
],
];
}