7 if (php_sapi_name() == 'cli') {
10 "No URL given as command line parameter\n"
12 . " play.php [--dry-run|-n] <url>"
16 array_shift($argv);//remove script itself
17 foreach ($argv as $val) {
19 $options[$val] = true;
24 if (isset($options['--dry-run']) || isset($options['-n'])) {
27 } else if (!isset($_SERVER['CONTENT_TYPE'])) {
28 errorInput('Content type header missing');
29 } else if ($_SERVER['CONTENT_TYPE'] == 'text/plain') {
31 $pageUrl = file_get_contents('php://input');
32 } else if ($_SERVER['CONTENT_TYPE'] == 'application/x-www-form-urlencoded') {
34 if (!isset($_POST['url'])) {
35 errorInput('"url" POST parameter missing');
37 $pageUrl = $_POST['url'];
39 errorInput('Content type is not text/plain but ' . $_SERVER['CONTENT_TYPE']);
42 $parts = parse_url($pageUrl ?? null);
43 if ($parts === false) {
44 errorInput('Invalid URL in POST data');
45 } else if (!isset($parts['scheme'])) {
46 errorInput('Invalid URL in POST data: No scheme');
47 } else if ($parts['scheme'] !== 'http' && $parts['scheme'] !== 'https') {
48 errorInput('Invalid URL in POST data: Non-HTTP scheme');
50 return [$pageUrl, $dryRun];
53 function getYoutubeDlJson($pageUrl, $youtubedlPath)
56 . ' --no-playlist'//would otherwise cause multiple json blocks
59 . ' ' . escapeshellarg($pageUrl);
62 1 => ['pipe', 'w'],//stdout
63 2 => ['pipe', 'w'],//stderr
65 $proc = proc_open($cmd, $descriptors, $pipes);
66 if ($proc === false) {
67 errorOut('Error running youtube-dl');
69 $stdout = stream_get_contents($pipes[1]);
70 $stderr = stream_get_contents($pipes[2]);
72 $exitCode = proc_close($proc);
74 if ($exitCode === 0) {
75 //stdout contains the JSON data
79 if (strlen($stderr)) {
80 $lines = explode("\n", trim($stderr));
81 $lastLine = end($lines);
83 $lines = explode("\n", trim($stdout));
84 $lastLine = end($lines);
87 if ($exitCode === 127) {
89 'youtube-dl not found at ' . $youtubedlPath,
90 '500 youtube-dl not found'
92 } else if (strpos($lastLine, 'Unsupported URL') !== false) {
94 'Unsupported URL at ' . $pageUrl,
95 '406 Unsupported URL (No video found)'
99 errorOut('youtube-dl error: ' . $lastLine);
102 function extractVideoUrlFromJson($json)
104 $data = json_decode($json);
105 if ($data === null) {
106 errorOut('Cannot decode JSON: ' . json_last_error_msg());
110 foreach ($data->formats as $format) {
111 if (strpos($format->format, 'hls') !== false) {
112 //dreambox 7080hd does not play hls files
115 if (strpos($format->format, 'vp9') !== false
116 || $format->vcodec == 'vp9'
118 //dreambox 7080hd does not play VP9 video streams
121 if (strtolower(substr($format->vcodec, 0, 6)) == 'avc1.6') {
122 //dreambox DM7080 does not play H.264 High Profile
125 if ($format->protocol == 'http_dash_segments') {
126 //split up into multiple small files
129 if ($format->ext == 'flv') {
130 //Internal data flow error
133 $safeFormats[] = $format;
138 //filter: best quality
139 usort($safeFormats, function ($a, $b) {
140 $a->acodec = $a->acodec ?? null;
141 $b->acodec = $b->acodec ?? null;
142 if ((($a->acodec != 'none') + ($b->acodec != 'none')) == 1) {
143 return ($b->acodec != 'none') - ($a->acodec != 'none');
145 return ($b->quality ?? 0) - ($a->quality ?? 0);
147 foreach ($safeFormats as $format) {
148 //echo $format->format . ' | ' . $format->vcodec . ' | ' . $format->acodec . "\n";
154 //use URL chosen by youtube-dl
160 'No video URL found',
161 '406 No video URL found'
167 function playVideoOnDreambox($videoUrl, $dreamboxUrl)
169 ini_set('track_errors', 1);
170 $xml = @file_get_contents($dreamboxUrl . '/web/session');
171 if ($xml === false) {
172 if (!isset($http_response_header)) {
174 'Error fetching dreambox web interface token: '
175 . $GLOBALS['lastError']
179 list($http, $code, $message) = explode(
180 ' ', $http_response_header[0], 3
183 //dreambox web interface authentication has been enabled
185 'Error: Web interface authentication is required',
186 '401 Dreambox web authentication required'
190 'Failed to fetch dreambox session token: ' . $php_errormsg,
191 $code . ' ' . $message
195 $sx = simplexml_load_string($xml);
196 $token = (string) $sx;
198 $playUrl = $dreamboxUrl
199 . '/web/mediaplayerplay'
200 . '?file=4097:0:1:0:0:0:0:0:0:0:'
201 . str_replace('%3A', '%253A', rawurlencode($videoUrl));
203 $ctx = stream_context_create(
207 'header' => 'Content-type: application/x-www-form-urlencoded',
208 'content' => 'sessionid=' . $token,
209 //'ignore_errors' => true
213 $ret = file_get_contents($playUrl, false, $ctx);
214 if ($ret !== false) {
215 if (php_sapi_name() != 'cli') {
216 header('HTTP/1.0 200 OK');
218 echo "Video play request sent to dreambox\n";
222 'Failed to send video play request to dreambox: ' . $php_errormsg
227 function errorHandlerStore($number, $message, $file, $line)
229 $GLOBALS['lastError'] = $message;
232 $GLOBALS['lastError'] = null;