Help streaming with expiring links - neocorps - 2012-05-05
Hello,
This is my first post here and I don't know if this question is for this forum.
I'm using xbmc to play movies from a server I got online with the help of an addon, I used the original url and it all plays perfectly. The problem is that we need to give the users an expiring url in order to keep our content from being accessible from third party users.
We have managed to get everything working and the video plays perfectly but after 1 - 3 minutes the video stops and xbmc returns us to the movie list.
I think I know what the problem is, the file gets buffered in packets and after the first packet is buffered xbmc tries to find the link again and it fails, thus sending an error and returning us to the main screen. But why does this happen?, the url is valid and if I test it on a web browser it works.
Here is the log:
Code: 14:17:29 T:1712 NOTICE: item1=title=[127 Hours (2010)], url=[http://www.ourdomain.com/test/portal.php?id=ffc620d1a3f13b9a5d26ddaa9948c60c], thumbnail=[http://www.testing.com/imagenes/32p.jpg], action=[], show=[], category=[Biografia Suspenso ]
14:17:29 T:1712 NOTICE: item2=title=[127 Hours (2010)], url=[http://www.ourdomain.com/test/portal.php?id=bb704f1bd8c8bfe3286dd434ec2e0861], thumbnail=[http://www.testing.com/imagenes/32p.jpg], action=[], show=[], category=[]
14:17:31 T:1712 NOTICE: elegido=title=[127 Hours (2010)], url=[http://www.ourdomain.com/test/portal.php?id=ffc620d1a3f13b9a5d26ddaa9948c60c], thumbnail=[http://www.ourdomain.com/imagenes/32p.jpg], action=[], show=[], category=[Biografia Suspenso ]
14:17:34 T:6124 NOTICE: DVDPlayer: Opening: http://www.ourdomain.com/test/portal.php?id=ffc620d1a3f13b9a5d26ddaa9948c60c
14:17:34 T:6124 WARNING: CDVDMessageQueue(player)::Put MSGQ_NOT_INITIALIZED
14:17:34 T:4240 NOTICE: Creating InputStream
14:17:35 T:4240 NOTICE: Creating Demuxer
14:17:39 T:7040 WARNING: XFILE::CFileCurl::CReadState::FillBuffer: curl failed with code 33
14:17:39 T:7040 ERROR: CFileCurl::CReadState::Open, didn't get any data from stream.
14:17:39 T:7040 ERROR: XFILE::CFileCache::Process, error 0 seeking. seek returned -1
14:17:39 T:4240 NOTICE: Opening video stream: 0 source: 256
14:17:39 T:4240 NOTICE: Creating video codec with codec id: 28
14:17:39 T:4240 NOTICE: CDVDVideoCodecFFmpeg::Open() Using codec: H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
14:17:39 T:4240 NOTICE: Creating video thread
14:17:39 T:4240 NOTICE: Opening audio stream: 1 source: 256
14:17:39 T:4240 NOTICE: Finding audio codec for: 86018
14:17:39 T:3284 NOTICE: running thread: video_thread
14:17:39 T:4240 NOTICE: Creating audio thread
14:17:39 T:4240 NOTICE: Opening Subtitle stream: 2 source: 256
14:17:39 T:4336 NOTICE: running thread: CDVDPlayerAudio::Process()
14:17:39 T:4336 NOTICE: Creating audio device with codec id: 86018, channels: 2, sample rate: 48000, no pass-through
14:17:39 T:3284 NOTICE: fps: 23.809524, pwidth: 1280, pheight: 688, dwidth: 1280, dheight: 688
14:17:39 T:3284 NOTICE: Display resolution DESKTOP : 1366x768 @ 60.00 - Full Screen (12)
14:17:39 T:3284 NOTICE: D3D: rendering method forced to DXVA2 processor
14:21:49 T:7040 WARNING: XFILE::CFileCurl::CReadState::FillBuffer: curl failed with code 28
14:21:51 T:7040 WARNING: XFILE::CFileCurl::CReadState::FillBuffer: curl failed with code 33
14:23:07 T:4336 WARNING: CDVDMessageQueue(audio)::Get - asked for new data packet, with nothing available
14:23:08 T:3284 WARNING: CDVDMessageQueue(video)::Get - asked for new data packet, with nothing available
14:23:08 T:4240 NOTICE: CDVDPlayer::OnExit()
14:23:08 T:4240 NOTICE: DVDPlayer: eof, waiting for queues to empty
14:23:08 T:4240 NOTICE: DVDPlayer: closing audio stream
14:23:08 T:4240 NOTICE: Closing audio stream
14:23:08 T:4240 NOTICE: CDVDMessageQueue(audio)::WaitUntilEmpty
14:23:08 T:4240 NOTICE: Waiting for audio thread to exit
14:23:08 T:4336 NOTICE: thread end: CDVDPlayerAudio::OnExit()
14:23:08 T:4240 NOTICE: Closing audio device
14:23:08 T:4240 NOTICE: Deleting audio codec
14:23:08 T:4240 NOTICE: DVDPlayer: closing video stream
14:23:08 T:4240 NOTICE: Closing video stream
14:23:08 T:4240 NOTICE: CDVDMessageQueue(video)::WaitUntilEmpty
14:23:08 T:4240 NOTICE: waiting for video thread to exit
14:23:08 T:3284 ERROR: Got MSGQ_ABORT or MSGO_IS_ERROR return true
14:23:08 T:3284 NOTICE: thread end: video_thread
14:23:08 T:4240 NOTICE: deleting video codec
14:23:08 T:4240 NOTICE: DVDPlayer: closing subtitle stream
14:23:08 T:4240 NOTICE: Closing subtitle stream
14:23:08 T:4240 NOTICE: CDVDPlayer::OnExit() deleting demuxer
14:23:08 T:4240 NOTICE: CDVDPlayer::OnExit() deleting input stream
14:23:08 T:3572 NOTICE: -->Python Interpreter Initialized<--
14:23:08 T:3572 NOTICE: [config.py] xbmceden config
Here is where the movie fails and takes us to the movie list
For what I can tell, the scripts tries to get the next package from the url and it fails, although it gets the first 2 - 3 minutes.
Here is the portal.php file that sends the available file to xbmc.
PHP Code: require_once('includes/connection.php'); require_once('includes/functions.php'); //specific file functions function fileExists($path){ return (@fopen($path,"r")==true); } function file_extension($filename){ $path_info = pathinfo($filename); return $path_info['extension']; } function content_type($extension){ switch($extension){ case 'mkv': return 'video/x-matroska'; break; case 'avi': return 'video/avi'; break; case 'divx': return 'video/divx'; break; case 'mpg': return 'video/mpg'; break; case 'mp4': return 'video/mp4'; break; case 'flv': return 'video/x-flv'; break; case 'jpg': return 'image/jpeg'; break; case 'png': return 'image/png'; break; case 'bmp': return 'image/bmp'; break; } } //Get the link we are to provide from the DB if(isset($_GET['id'])){
//Checks DB for url $safe_id = mysql_prep($_GET['id']); $query = "SELECT *, NOW() as cur_date FROM links WHERE md5 = '{$safe_id}' LIMIT 1"; $result = mysql_query($query, $connection); confirm_query($result); if(mysql_num_rows($result)){ $link = mysql_fetch_array($result); $exp = strtotime($link['exp']); $cur = strtotime($link['cur_date']); //Check if the link has expired if($exp>$cur){ //Get the file $media = get_all_elements_by_id($link['tbl'], $link['media_id']); $file = $media['media_link']; //Get file size $ch = curl_init($file); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $data = curl_exec($ch); curl_close($ch); if (preg_match('/Content-Length: (\d+)/', $data, $matches)) { // Contains file size in bytes $contentLength = (int)$matches[1]; }
//get the file extension $extension = file_extension($file); if (fileExists($file)){ //Send file headers header('Content-Description: File Transfer'); header('Content-type: '.content_type($extension)); header('Content-Disposition: attachment; filename='.basename($file)); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header('Pragma: public'); header('Content-Length: ' . $contentLength); ob_clean(); flush(); readfile($file); exit; } else { //No File error_log("The file does not exist : ".$file, 0); } } else { //Expired error_log("This link has expired : ".$_GET['id'], 0); } } else { //ID Not Found error_log("we could not find the movie : ".$_GET['id'], 0); } } else { //ID Not Found error_log("we could not find the movie ", 0); }
If anyone notices anythign wrong with the php file or maybe knows a solution for this, please feel free to post.
RE: Help streaming with expiring links - Bstrdsmkr - 2012-05-06
This is the error you're getting.
Quote:CURLE_RANGE_ERROR (33)
The server does not support or accept range requests.
Your link needs to live longer than it takes for the client to fully buffer the video. Something like 6hrs should work.
RE: Help streaming with expiring links - neocorps - 2012-05-06
(2012-05-06, 00:04)Bstrdsmkr Wrote: This is the error you're getting.
Quote:CURLE_RANGE_ERROR (33)
The server does not support or accept range requests.
Your link needs to live longer than it takes for the client to fully buffer the video. Something like 6hrs should work.
Thank you for your reply, What I don't understand is that the link is supposed to live 1 hour, and the movie lasts about 1 - 3 minutes before it crashes, if what you say is true, then it should last about 1 hour before it crashes?.
I'll try making the links live longer though.
RE: Help streaming with expiring links - Bstrdsmkr - 2012-05-06
Sorry if that was unclear, those were meant to be two separate thoughts. The problem from xbmc's point of view is that when it makes the next request for a number of bytes to refill the buffer, the request is denied or errors. It looks like in this line:
Code: header('Content-Length: ' . $contentLength);
You're returning the whole file. You need to detect the Range header in the incoming request and return the byte range requested. Start here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html section 14.5
The expiration comment was just a "keep in mind" that commonly gets overlooked in serving streams
RE: Help streaming with expiring links - neocorps - 2012-05-06
(2012-05-06, 02:11)Bstrdsmkr Wrote: Sorry if that was unclear, those were meant to be two separate thoughts. The problem from xbmc's point of view is that when it makes the next request for a number of bytes to refill the buffer, the request is denied or errors. It looks like in this line:
Code: header('Content-Length: ' . $contentLength);
You're returning the whole file. You need to detect the Range header in the incoming request and return the byte range requested. Start here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html section 14.5
The expiration comment was just a "keep in mind" that commonly gets overlooked in serving streams
Ok that makes total sense, let me look into it and post my results. Thank you!
RE: Help streaming with expiring links - neocorps - 2012-05-06
I added this next line:
PHP Code: header("Accept-Ranges: bytes");
And the file seems to be downloading ok, my issue now is that I can't skip to a certain time on the movie, I think the problem is that I'm sending the full Content-Length, instead of a range, so I'm gonna test using this:
PHP Code: if ($partial_content) header('Content-Range: bytes ' . $offset . '-' . ($offset + $length) . '/' . $file_size);
And Content-Length should have the length of the range I want to download.
I'm posting all this for future references to anyone who might have the same problem I do.
RE: Help streaming with expiring links - neocorps - 2012-05-08
I have a question though.
I get the range from $_SERVER['HTTP_RANGE'], but all I get is something like this :
PHP Code: echo 'HTTP_RANGE = ''$_SERVER['HTTP_RANGE'];
output: HTTP_RANGE = 100000-
If my file weights 100200, why does it show only 100000 (that's 200bytes less), thought the range should be something like "200-400".
I'm a bit confused on how XBMC sends the range requests.
RE: Help streaming with expiring links - Bstrdsmkr - 2012-05-08
I'm not sure I'm understanding the question. If your server is receiving a request with the header "HTTP_RANGE = 100000-" then xbmc wants you to return the file segment from byte number 100000 to the end of the file
RE: Help streaming with expiring links - neocorps - 2012-05-08
That's where It gets confusing to me, cause I've just started the movie, to my understanding the file should start with byte number 0 and buffer say 100 bytes and then ask me for byte 101 to byte 201.
I'm gonna do some tests to see if I get another HTTP_RANGE.
RE: Help streaming with expiring links - Bstrdsmkr - 2012-05-08
Ahhh, I bet what you're seeing is XBMC determining the file type, codec, and etc. I'd say once it's got that, you'll start getting requests from the beginning of the file as you would normally expect
|