5 if (php_sapi_name() == 'cli') {
7 errorInput('No URL given as command line parameter');
10 } else if (!isset($_SERVER['CONTENT_TYPE'])) {
11 errorInput('Content type header missing');
12 } else if ($_SERVER['CONTENT_TYPE'] == 'text/plain') {
14 $pageUrl = file_get_contents('php://input');
15 } else if ($_SERVER['CONTENT_TYPE'] == 'application/x-www-form-urlencoded') {
17 if (!isset($_POST['url'])) {
18 errorInput('"url" POST parameter missing');
20 $pageUrl = $_POST['url'];
22 errorInput('Content type is not text/plain but ' . $_SERVER['CONTENT_TYPE']);
25 $parts = parse_url($pageUrl);
26 if ($parts === false) {
27 errorInput('Invalid URL in POST data');
28 } else if (!isset($parts['scheme'])) {
29 errorInput('Invalid URL in POST data: No scheme');
30 } else if ($parts['scheme'] !== 'http' && $parts['scheme'] !== 'https') {
31 errorInput('Invalid URL in POST data: Non-HTTP scheme');
36 function getYoutubeDlJson($pageUrl, $youtubedlPath)
39 . ' --no-playlist'//would otherwise cause multiple json blocks
42 . ' ' . escapeshellarg($pageUrl);
45 1 => ['pipe', 'w'],//stdout
46 2 => ['pipe', 'w'],//stderr
48 $proc = proc_open($cmd, $descriptors, $pipes);
49 if ($proc === false) {
50 errorOut('Error running youtube-dl');
52 $stdout = stream_get_contents($pipes[1]);
53 $stderr = stream_get_contents($pipes[2]);
55 $exitCode = proc_close($proc);
57 if ($exitCode === 0) {
58 //stdout contains the JSON data
62 if (strlen($stderr)) {
63 $lines = explode("\n", trim($stderr));
64 $lastLine = end($lines);
66 $lines = explode("\n", trim($stdout));
67 $lastLine = end($lines);
70 if ($exitCode === 127) {
72 'youtube-dl not found at ' . $youtubedlPath,
73 '500 youtube-dl not found'
75 } else if (strpos($lastLine, 'Unsupported URL') !== false) {
77 'Unsupported URL at ' . $pageUrl,
78 '406 Unsupported URL (No video found)'
82 errorOut('youtube-dl error: ' . $lastLine);
85 function extractVideoUrlFromJson($json)
87 $data = json_decode($json);
89 errorOut('Cannot decode JSON: ' . json_last_error_msg());
93 foreach ($data->formats as $format) {
94 if (strpos($format->format, 'hls') !== false) {
95 //dreambox 7080hd does not play hls files
98 if (strpos($format->format, 'vp9') !== false) {
99 //dreambox 7080hd does not play VP9 video streams
102 if ($format->protocol == 'http_dash_segments') {
103 //split up into multiple small files
106 if ($format->ext == 'flv') {
107 //Internal data flow error
110 $safeFormats[] = $format;
115 //filter: best quality
116 usort($safeFormats, function ($a, $b) {
117 return ($b->quality ?? 0) - ($a->quality ?? 0);
119 foreach ($safeFormats as $format) {
125 //use URL chosen by youtube-dl
131 'No video URL found',
132 '406 No video URL found'
138 function playVideoOnDreambox($videoUrl, $dreamboxUrl)
140 ini_set('track_errors', 1);
141 $xml = @file_get_contents($dreamboxUrl . '/web/session');
142 if ($xml === false) {
143 if (!isset($http_response_header)) {
145 'Error fetching dreambox web interface token: '
146 . $GLOBALS['lastError']
150 list($http, $code, $message) = explode(
151 ' ', $http_response_header[0], 3
154 //dreambox web interface authentication has been enabled
156 'Error: Web interface authentication is required',
157 '401 Dreambox web authentication required'
161 'Failed to fetch dreambox session token: ' . $php_errormsg,
162 $code . ' ' . $message
166 $sx = simplexml_load_string($xml);
167 $token = (string) $sx;
169 $playUrl = $dreamboxUrl
170 . '/web/mediaplayerplay'
171 . '?file=4097:0:1:0:0:0:0:0:0:0:'
172 . str_replace('%3A', '%253A', rawurlencode($videoUrl));
174 $ctx = stream_context_create(
178 'header' => 'Content-type: application/x-www-form-urlencoded',
179 'content' => 'sessionid=' . $token,
180 //'ignore_errors' => true
184 $ret = file_get_contents($playUrl, false, $ctx);
185 if ($ret !== false) {
186 if (php_sapi_name() != 'cli') {
187 header('HTTP/1.0 200 OK');
189 echo "Video play request sent to dreambox\n";
193 'Failed to send video play request to dreambox: ' . $php_errormsg
198 function errorHandlerStore($number, $message, $file, $line)
200 $GLOBALS['lastError'] = $message;
203 $GLOBALS['lastError'] = null;