I have a Chromecast and a URL of an mp4 file online. I also have a 2Mbps download connection, which is pathetic and renders direct buffering to the Chromecast too slow. That's what I tried so far:
Through the developer console, I simply set location.href to the online URL of the mp4. The Chromecast would buffer for 20 seconds, play 10 seconds' worth of video, and then buffer again. So, through the console, I paused the video and let it buffer for 5 minutes. When I let it play again, it played for about 15 seconds, and then lost all progress and had to be returned to the home screen.
As I don't want to wait for the whole download of the mp4 to complete, I am currently attempting this: I buffer the mp4 to a local file which is in my htdocs directory, and I then direct the Chromecast to that file's location. However, when opening the mp4 file thorugh Chrome (the browser), instead of playing, it shows a download prompt, and the Chromecast returns to the home screen.
I have implemented the buffering in PHP, and it looks as thus:
$bufferSource = 'http://example.com/path/to/file.mp4';
$bufferedReader = fopen($bufferSource, 'r');
while(!($finished = feof($bufferedReader))){
if($finished !== false){ break; }
//get onle line
$buffer = fgets($bufferedReader);
file_put_contents('buffer.mp4', $buffer, FILE_APPEND);
}
fclose($bufferedReader);
I know that PHP does its work, as I can watch the file size grow on my computer, and I can open the file with VLC. Is there maybe another PHP script I could make to access the locally buffered mp4 file which simulates 'bufferability', so Chrome does not show the download dialog but buffers the file, as should do the Chromecast?
EDIT: One more thing. I am not directing the Chromecast to the PHP script. I am actually directing it directly to the buffer.mp4 file.
You're missing a Content-Type header in your PHP script.
Figure out what the original content type header is from your server (probably video/mp4) and send it with your proxying script like this:
header('Content-Type: video/mp4');
This will allow the browser to detect the content type and play it directly (if supported), without downloading.
Also, I would consider using a real proxy server, such as Nginx, rather than reinventing the wheel. This will be much easier and more reliable.
You can use a receiver with a Media Element tag and then point its source to your mp4 file on your server. If you don't want to write your own receiver, you can use either the default or Styled Media Receiver . You would need a very simple sender to send the url, check out the github repo for examples
Related
I'm uploading to a lightspeed server through "ncftpput" an image taken from a raspberry camera every minute.
I want to be able to show the updated image and I know how I can force the browser to use the latest version instead of the cached image.
So, everything works properly except that, if I refresh the image (like through shift-F5) during image upload, the browser reports image contains errors (or shows image partially).
Is there any way to ensure the image is fully loaded before serving the new one?
I'm not sure if I should operate on ncftp or use PHP to ensure the swap happens only after complete loading.
Image is a progressive jpg but that doesn't help...
Any suggestion?
Thanks
I ended up with NOT using FTP because, as Viney mentioned, the webserver doesn't know if the upload is completed.
I'm using "curl" which has the advantage of being preinstalled on raspberry distro and a php upload page.
It seems that PHP will pass the new image only once fully uploaded and avoid creating the issue when image is still partially uploaded.
So, to recap:
raspberry (webcam), after having taken the image:
curl -F"somepostparam=abcd" -F"operation=upload" -F"file=#filename.jpg" https://www.myserver.com/upload.php
PHP server code:
$uploadfile = '/home/domain/myserver.com/' . basename($_FILES['file']['name']);
move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile);
$content = file_get_contents($uploadfile);
Problem is this: you open browser (at 07:00:10 AM) image.jpg gets rendered now say it's 07:01:00 you hit refresh in browser but the raspberry is already started uploading image.jpg say it would take 3 secs to complete the full upload but the server doesn't know about ftp and would read whatever bytes are there in image,jpg and flushes to your browser. Had it been a baseline JPG it would have shown a cropped(in height) image but since it's a progressive JPG it would be messed up.I am not aware of whether it's possible but try looking up if you FTP supports a locking file.
How to solve ?
The best way is to let you server know that the file it's accessing is in a write process.If your ftp supports advisory locks then you can use it so when server tries accessing you file ( via system call) kernel would instruct it that the file is currently locked so the server will wait until ftp releases that lock.
In vsftp there would be a option lock_upload_files in VSFTPD.CONF setting yest would enable this feature
If you are unable to work out above solution then you can use some trick like checking file last modified time if it's almost same as current time then you make php wait for some guessed time that you think is avg. upload time of your file.For this method you should use PHP to send it to browser instead of server. ie Just change the src of your image from '/path/to/image.jpg' to 'gen-image.php'. This script will read that image and would flush it to the browser
gen-image.php
$guessedUploadTime = 3;// guessed time that ncftpput takes to finish
$currTime = time();
$modTime = filemtime('image.jpg');
if( ($currTime - $modTime) < $guessedUploadTime)
{
sleep($guessedUploadTime);
}
$file = '/path/to/image.jpg';
$type = 'image/jpeg';
header('Content-Type:'.$type);
readfile($file);
Note that the above solution is not ideal because if file has been just done uploading it won't be modified for another 57 seconds yet the browser request say at 07:02:04 has to wait unnecessarily for 3 seconds because mtime would be 07:02:03 and browser would get file only after 07:02:06. I would recommend you to search for some way(proly cmd based) to make server and ftp go hand in hand one should know the status of the other because that is the root cause of this problem.
I have a php page with an embedded HTML5 video, say video.mp4. On cloudflare, I have a pagerule setup for mydomain.com/.php* and set it to cache everything. Will cloudflare cache the embedded video?
Thanks.
EDIT: Apparently cloudflare f***s up when caching videos. If a user watches half a video and cloudflare only caches that, every single visitor to your website will receive half the video.
But where do you want it to cache? In memory on the cloudflare server, or the user's Browser. I assume the latter because the former should not matter
have you tried:
preload="auto"
Check the HTTP Response Header to see if it has
Cache-Control: max-age=xxxxx
Where xxxxx = number of seconds the Browser should cache.
'Expires' is also a date where the Browser would no longer keep it in cache.
To see the Header, right click, select Inspect Element, go to the "Network Tab" refresh the page, select the video from the list of resources, view the Response Header.
To store the video in memory, the PHP /tmp directory is a memory directory.
To verify the tmp directory use:
echo sys_get_temp_dir();
To get the video into the temp directory
$data = file_get_contents('http://example.com/video/test.mp4');
$fp = fopen('/tmp/test.mp4','w');
fwrite($fp,$data);
fclose($fp);
You may need to set a handler for content-type: video/mp4.
But the type on the video control should do it. As I recall I had to set the handler, so the HTTP response header had the correct content type.
<source src="/tmp/test.mp4" type="video/mp4";/>
You could make a PHP script to server the mp4 with the correct header.
header('Content-Type: video/mp4');
echo file_get_contents('/tmp/test.mp4');
Then in the video control:
src="video.php"
How come you don't have the PageRule set to mydomain.com/* to cache everything?
"Will cloudflare cache the embedded video?"
But, yes, the PageRule should cache everything.
I'm trying to develop an online management system for a very large FLAC music library for a radio station. It's got a beefy server and not many users, so I want to be able to offer a file download service where PHP transcodes the FLAC files into MP3/WAV depending on what the endpoint wants.
This works fine:
if($filetype == "wav") {
header("Content-Length: ". $bitrate * $audio->get_length());
$command = "flac -c -d ".$audio->get_filename().".flac";
}
ob_end_flush();
$handle = popen($command, "r");
while($read = fread($handle, 8192)) echo $read;
pclose($handle);
and allows the server to start sending the file to the user before the transcoding (well, decoding in this case) completes, for maximum speed.
However, the problem I'm getting is that while this script is executing, I can't get Apache to handle any other requests on the entire domain. It'll still work fine on other VirtualHosts on the same machine, but nobody can load any pages on this website while one person happens to be downloading a file.
I've also tried implementing the same thing using proc_open with no difference, and have played with the Apache settings for number of workers and the like.
Is the only way to stop this behaviour to use something like exec and waiting for the encoding process to finish before I start sending the user the file? Because that seems sub-optimal! :(
UPDATE: it seems that other people can still access the website, but not me - i.e. it's somehow related to sessions. This confuses me even more!
Use session_write_close() at some point before you start streaming... You may also want to stream_set_blocking(false) on the read pipe.
My test server is apache 2 to work php coding. i want to create a mp3 server.
Everything is working fine, however today i tried to build an admin page by taking the mp3 info, change it, delete etc. There is a play button in page for selected mp3, when clicked to play button, file loading with header option and playing,
Sample code is here:
session control &
$filename = '/home/bla..bla/mp3/'. $_GET['v'] . '.mp3';
if(file_exists($filename)) {
header('Content-Type: audio/mpeg');
header('Content-length: '.filesize($filename));
header('X-Pad: avoid browser bug');
header('Cache-Control: no-cache');
readfile($filename);
}else{
exit();
}
Everything looks fine, but when i click to another button (e.g. search again mp3 with ajax code or take value with javascript in same page) nothing is happening.
Page is waiting to load mp3 file. looks like blocking request. when mp3 loading %60 or %70, query is coming.
if i can't find a solution,i will be killer :)
ps: my system build on apache2, PHP5 , MySQL, using audio tag in admin page but same problem with jplayer.
Most likely you're running into session locking. When requesting a page in which you session_start(), the session file is opened and locked to prevent problems with concurrent access. The file stays locked until the current script is finished. While the file is locked, other processes can't access it and will wait until it becomes unlocked.
Before you do any long-running tasks like streaming an MP3 file, unlock the session with session_write_close.
Even better, let the web server handle the mundane task of streaming a file, don't keep a PHP process busy with it. Try mod_xsendfile.
I am creating a simple Proxy server for my website. Why I am not using mod_proxy and mod_cache is a different discussion. Here's the code:
shell_exec("nohup curl --create-dirs -o {$write_path} {$source_url} > /dev/null 2> /dev/null & echo $!");
sleep(1);
$read_speed = 65.5; # 65.5 kb/s download rate
$handle = fopen($write_path, "rb");
$content_type = select_meta_item($headers, 'Content-Type');
$file_size = select_meta_item($headers, 'Content-Length');
send_headers($content_type, $file_size);
flush();
while (!feof($handle))
{
echo fread($handle, round($read_speed * 1024));
flush();
sleep(1);
}
fclose($handle);
Streaming an MP3 doesn't work using this method. Plays in Chrome, but not in Firefox. Initially I'll be using this to stream MP3 files through Long Tail's JW Player. If it all works out, I'll also be using this to send ZIP files.
The question is whether your file format can be streamed by the client implementation. If Firefox does not support playing an mp3 until it is done being downloaded, no amount of server-side trickery will help you achieve streaming. You will need client-side support, such as a flash-based inline player.
For ZIP files, given that the encoding table is placed at the end of the archive, no software will be able to open it until it has been completely downloaded.
As a side note, have you considered creating a FIFO, pointing curl at the FIFO input, and applying readfile to the FIFO output, thereby letting the OS handle things?
I figured it out. The code it works fine.
The file was being called by APACHE by the 404 handler (ErrorDocument). Apache automatically sent the 404 header prior to the PHP script being called.
This file (code above), not starts the CURL process and redirects to a file that streams. Since Apache returned the 404, Firefox ignored the MP3 response. (whereas Chrome didn't). Now that I redirect, it works fine.