PHP - Extract frame during Video upload - php

I'm having a problem finding if this is even possible (no info anywhere to be found).
Is it possible to EXTRACT a frame (thumbnail) during the video upload?
Extract using jscript is also an option if it's possible to extract user side.
Thanks for the help!

Fast forward almost five years since this question was posted, and the answer is now a yes!
Live demo
How to extract a frame during video upload using JavaScript
Before showing code, this is what we'll do:
Set an event handler on the input element that will take the video to be uploaded
When a file is selected from the file system, use the URL object to create a url to the local video file.
Load that URL into a video element.
When the video has loaded into memory, draw a frame on a canvas object.
Now export the frame rendered on the canvas into an image element (or optionally send that image to your server as a data url).
<input type="file" id="upload"/>
<img id="thumbnail"/>
<script>
var input = document.getElementById('upload');
var img = document.getElementById('thumbnail');
input.addEventListener('change', function(event){
var file = this.files[0];
var url = URL.createObjectURL(file);
var video = document.createElement('video');
video.src = url;
var snapshot = function(){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
img.src = canvas.toDataURL('image/png');
video.removeEventListener('canplay', snapshot);
};
video.addEventListener('canplay', snapshot);
});
</script>

I don't think there is a good way to do that in php. (https://stackoverflow.com/a/1309425/1488032)
If it is not just some webspace that you have rented but have the rights to install and run other software on the server I would suggest using something like ffmpeg and calling it from within php using system(), passthru() or exec() to extract what you want and do the rest of the processing in php again.
I'm running a browser game that relies on svg images embedded in xhtml but some browsers (especially mobile ones) don't support the full svg syntax. In this case I use such a system() call to do svg-to-png conversion using imagemagick's convert binary and display the result on my page.
system("echo '$svgString' | convert svg:- png:- | base64");
I suppose you have to fall back to something similar.
Here's some information on extracting frames using ffmpeg:
http://ubuntuforums.org/showthread.php?t=1141293

Javascript: no.
During upload: no.
Once you've uploaded, yes.
"Dev" provided the right link in the comments, but what you should do is save the video to your server and then run ffMpeg to grab the image. You can download ffMPEG here: http://ffmpeg.org/download.html (grab hte build you need if you're not confident on building it yourself - there are Linux and Windows builds).
The documentation is here: http://ffmpeg.org/ffmpeg.html but there is a slightly easier to read tutorial at http://linuxers.org/tutorial/how-extract-images-video-using-ffmpeg for grabbing an image.
Note: there is a PHP extension clled "phpFFMPEG" but I suggest you don't use it. Simply run the desired commands through "exec()" in PHP. Check for error return values as you can only run ffMPEG once per CPU core, so if you try it twice at the same time it might fail - either queue the actions or try again if it fails.

First, you need to select a program to extract the frame. ffmpeg is commonly used for this. Whatever you pick, it needs to be able to work with partial file contents.
php scripts dont start executing until after the entire file upload has completed, but php recently got a feature so that a different php script can be executed during the file upload, and will be able to get at uploading scripts data(the filename is the thing of interest to you).
http://php.net/manual/en/session.upload-progress.php
Then, basically call the external program to extract the frame from the monitoring script, using the temp file name being uploaded in the upload handling script.
to summarize:
upload the file to upload.php.
monitor.php will get the temp file name being uploaded in upload.php, and extract the frame.

Basically, I took rodrigo-silveira answer provided in this thread and modified it for my use and now the solution works like a charm. Even I was trying to upload the video thumbnail/poster of a video that a user wishes to upload and save the video and the thumbnail in a folder. Also, I didn't want to use ffmpeg.
Here is what I did: In the upload file called "upload.php" I have the following code with slight modification to rodrigo-silveira's solution above:
upload.php:
<input type="file" id="upload"/>
<img id="thumbnail"/>
<form action="action_page.php" method="post" target="_blank">
<input type="hidden" id="mytext" name="mytext" >
<input type="submit" value="Submit">
</form>
<script>
var input = document.getElementById('upload');
var img = document.getElementById('thumbnail');
input.addEventListener('change', function(event){
var file = this.files[0];
var url = URL.createObjectURL(file);
var video = document.createElement('video');
video.src = url;
var snapshot = function(){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = 350;
canvas.height = 250;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
img.src = canvas.toDataURL('image/png');
document.getElementById("mytext").value = img.src;
video.removeEventListener('canplay', snapshot);
};
video.addEventListener('canplay', snapshot);
});
</script>
Both the HTML part and the JavaScript above are within the upload.php's body tag.
Now on to the action_page.php file:
<?php
$data = $_POST['mytext'];
$file = "photos/file".time().".png";
$uri = substr($data,strpos($data, ",") + 1);
file_put_contents($file, base64_decode($uri));
?>
Save both PHP files in the same folder and create another folder called "photos" in that folder. Your video thumbnail/poster image from a video that is selected in the upload.php page gets saved in the "photos" folder as png file. (Note: this solution does not upload the video, just the video thumbnail. But that is straight forward from here on.)

Related

how to read image file as data url using php

In javascript, I read the file data by binding the on-change method to the file input and saving the file data into another input using the following code
$("#release_cover_custom").on('change', function (evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function (theFile) {
return function (e) {
$("#release_cover_custom_data").val(e.target.result);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
});
why i use the above code?, to store the image data, because i have a form where i provide settings for the email template that would be sent later and there i have to provide the background image to be used inside the email, i need to preview the email with all the settings and along with the background image provided to upload before saving the form or uploading the image, so i read the image data, save it to an input and then open a modal window to preview email and post all the necessary variables there including the image data which is then used in the following way inside the css to apply the background-image like below in my php view file
background-image:url('" . $background_image . "') !important;
Now i want to do the achieve the same thing via php, means if i have the image saved to a path and i want to read the image data and use it in the same way i did using javascript to futher pass it to the css property,
i tried to use base64_encode(file_get_contents('path/to/file'))
but the encoding seems to be different for the image data, as the background image is not shown should i be using some other method to achieve it in php.
#quagaar reply (on the question) helped me solve the problem and replaced the following
$background_image=base64_encode(file_get_contents('/path/to/file'));
with
$background_image='data:image/png;base64,'.base64_encode(file_get_contents('/path/to/file'));
and everything works fine as expected.
EDIT:
between i was dealing with images only and if you are working with Images only and you need mime type (e.g. for headers, or like my case), then this is a fast and reliable technique:
$file = 'path/to/image.jpg';
$image_mime = image_type_to_mime_type(exif_imagetype($file));
It will output true image mime type even if you rename your image file.

resize external images from other websites before loading them?

Iam working on a project , which involves fetching images from various websites and displaying a Thumnail or resized version of orignal image.
As i will be fetching many images at time , this takes more time , As Orignal image files will be loaded.
What i need is given an image url , i need resized version of that image file? So that i need not download the Large orignal image file...
for example : orignal image : 500X800 some 500kb
what i need is : 100X150 some 100kb image file..
Is it possible using Jquery? OR PHP?
Are their any functions like imagecopyresampled(PHP) in Jquery or any plugins?
Well, the big file needs to be downloaded at one point to create the thumbnail.
What you can do, through JQuery, is ask your server for the thumbnail, the server downloads the file, creates the thumbnail and sends back to the client the URL of the thumbnail when the resizing is done. This way, the client will gradually receive thumbnails as they are ready.
Edit After experimenting a bit, I found out that as soon as an img requests a picture, even if you dynamically remove its src attribute, the download continue.
So I decided to write a sample code (there's not much validation and it only works for jpeg, adding the other types would be really easy though). The solution is divided in 3 parts:
HTML
First, I used an empty div with some specific attributes to let jQuery what to load. I need to apologize to Nuria Oliver, she had the first "big picture" I could find on the net. So, here's a sample div:
<div class="thumbnail" data-source="http://www.nuriaoliver.com/pics/nuria1.jpg" data-thumbnail-width="100" data-thumbnail-height= "200"/></div>
I use thumbnail as class to be able to find easily the divs I want. The other data parameters allow me to configure the thumbnail with the source, width and height.
JavaScript / jQuery
Now, we need to locate all these divs requesting thumbnails... using jQuery it is pretty easy. We extract all the data settings and push them in an array. We then feed a PHP page with the query and wait for the response. While doing so, I'm filling the div with some HTML showing the "progress"
<script type="text/javascript">
$(".thumbnail").each(function() {
var img = $(this);
var thumbnailWidth = img.data("thumbnail-width");
var thumbnailHeight = img.data("thumbnail-height");
var thumbnailSource = img.data("source");
var innerDiv = "<div style='width:" + thumbnailWidth + "px; height:" + thumbnailHeight + "px'>Loading Thumbnail<br><img src='loading.gif'></div>";
img.html(innerDiv); // replace with placeholder
var thumbnailParams = {};
thumbnailParams['src'] = thumbnailSource;
thumbnailParams['width'] = thumbnailWidth;
thumbnailParams['height'] = thumbnailHeight;
$.ajax({
url: "imageloader.php",
data: thumbnailParams,
success: function(data) {
img.html("<img src='" + data + "'>");
},
});
})
</script>
PHP
On the PHP side of things, I do a quick test to see if the picture has already been cached (I'm only using the file name, this should be more complicated but it was just to give you an example) otherwise I download the picture, resize it, store it in a thumbnail folder and return the path to jQuery:
<?php
$url = $_GET["src"];
$width = $_GET["width"];
$height = $_GET["height"];
$filename = "thumbnail/" . basename($url);
if(is_file($filename)) // File is already cached
{
echo $filename;
exit;
}
// for now only assume JPG, but checking the extention should be easy to support other types
file_put_contents($filename, file_get_contents($url)); // download large picture
list($originalWidth, $originalHeight) = getimagesize($filename);
$original = imagecreatefromjpeg($filename); // load original file
$thumbnail = imagecreatetruecolor($width, $height); // create thumbnail
imagecopyresized($thumbnail, $original, 0, 0, 0, 0, $width, $height, $originalWidth, $originalHeight); // copy the thumbnail
imagedestroy($original);
imagejpeg($thumbnail, $filename); // overwrite existing file
imagedestroy($thumbnail);
echo $filename;
Browser
So, what does it do exactly? In the Browser, when I open the page I first see:
And as soon as the server is done processing the image, it gets updated automatically to:
Which is a thumbnail version, 100x200 of our original picture.
I hope this covers everything you needed!
PHP Thumb is a good plugin it worked for me and easy to operate.
And the best part is there are many options to select about the output file like its quality, max width for potrait images , max width for landscape images etc..
And we can set permissions like block off server requests, block off domain thumbnails.. etc
Note: this was actually posted by someone , as an answer to this question..But it was deleted.So iam reposting it, as it was useful.
for this to work you need to do some actual image processing which you cant do with js, so some server side language is needed.PHP is an option
If you are not interesting in obfuscating the image source, you may very well rely on an external tool like http://images.weserv.nl/ which takes an original image and allows you to request it in a different size.
If you end up not relying on a global CDN, at least sort out proper caching. Last thing you want to do is resize the same image over and over again for subsequent identical requests - any benefit of image's lower size will probably be negated by processing time.

read images and upload, after

What I'm trying to accomplish
[x] 1) User fills out form
[x] 2) User adds images to form through "drag & drop (html5)" or by "click to choose images"
and a preview is displayed on the page. (done)
Here it's easy to add code to trigger an upload of theese images to the server but I don't want that just yet.
[x] 3) Users clicks "add me & my desk" --> Create user account if doesn't already exist
[x] 4) Desk is added, and a connection to the right user is added as well.
[x] 5) Create a folder with the same name (id) as the desk_id.
::::THE QUESTION::::
6) -->> now I want to upload those dragged and dropped, or selected images to that folder.
:::::::::::::::::::
I've gotten this far with the information I found here: http://www.html5rocks.com/en/tutorials/file/dndfiles/ (the actual page really rocks!9
I know about this awesome solution: http://blueimp.github.com/jQuery-File-Upload/
But it's overkill for what I'm trying to do, and I happen to be so proud that I've got everything else working, and I really do think I'm so close.
words and expressions that keep coming up: read blob, check array blob, read from sandbox, canvas.toDataURL()
I feel that the answer is here: http://www.html5rocks.com/en/tutorials/file/xhr2/
AND / OR HERE http://www.html5rocks.com/en/tutorials/file/dndfiles/ Or HERE /
http://www.html5rocks.com/en/tutorials/file/filesystem/ (under "Duplicating user-selected files"), OR HERE http://robertnyman.com/2010/12/16/utilizing-the-html5-file-api-to-choose-upload-preview-and-see-progress-for-multiple-files/
You could say I'm at the next step after this: Preview an image before it is uploaded
but perhaps I could get a push in the right direction? :)
Of course I've had a look at these:
HTML5 Pre-resize images before uploading
facebook js api - HTML5 canvas upload as a photo
Currently displaying preview from DND files like this:
for (var i = 0, f; f = uppladdadeFiler[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb preview" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('listImages').insertBefore(span, null);
var span2 = document.createElement('span');
span2.innerHTML = ['<img class="thumb inside" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('huvudbilden').insertBefore(span2, null);
};
})(f);
$('#valdaBilder').show();
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
I will give you some inputs which I hope will lead you in the right direction. Please note that I am not providing an off-the-shelf working answer because of two reasons - 1. I am just too lazy:) and 2. from what I can see you are smart enough to figure it out once you get the gist of it... so here goes:
First thing to do is have a button named, say, 'Upload Files' and attach a fn to it like uploadFiles(). Now this function will look something like below:
function uploadFiles()
{
var file = files[0];
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function()
{
if (xhr.readyState==4 && xhr.status==200)
alert(xhr.responseText);
};
xhr.open('POST', '/upload.php', true);
xhr.setRequestHeader('X-FILE-NAME', file.name);
xhr.send(file);
}
Ok, so the explanation:
var file = files[0];
The files object array should be something that you create in your drag and drop eventlistener functions, which will be file objects representing the files you dropped into the dropzone. Usually you create them so: files = event.dataTransfer.files; which creates a FileList object named files In the example I am only considering the first file in the dropzone - hence files[0]
I guess the rest of the code is pretty self-explanatory. One thing to note is:
xhr.setRequestHeader('X-FILE-NAME', file.name);
xhr.send(file);
As you can see we are sending out raw binary data content to the server. So the post operation is writing into the server stream with raw binary data of what the file contains. This is an important point because this affects how the server is able to read this posted data.
Server side upload.php:
I am just going to read the first 1000 bytes of the uploaded file and print it back into the client (which, based on the javascript code above, will alert it into the browser)
<?php
$streamHandle = fopen("php://input","rb");
$streamContent = fread($streamHandle,1000);
echo $streamContent;
?>
Many people get confused on how to read content at the server side and think about using $_POST, or $_FILES, but if you are sending data using X-FILE-NAME, then you have to read it by opening a handle to php://input which is the standard input stream of the running php process.
Once you have read the stream, it is only a matter of fwrite-ing it into a new file in whatever directory you want to.
Like I said, this is not a turn-key solution that you can just copy-paste into your particular code, but I hope this helps you in looking in the right direction for file uploads using HTML5's drag and drop and the file API provided by Javascript to support it.

HTML5 CANVAS: How to save and reopen image from server

I draw something with html5-canvas. then i want to save it, and when the page is loaded again, I want to load the image I saved back to the canvas. I succeed with saving the data into a file in the server, but for some reason it's a strange file that can't open by ant software, and ofcourse not by my canvas. I save it as png base64, but i tried other things that didn't work.
javascript code:
function save(){ //saves the canvas into a string as a base64 png image. jsvalue is sent to the server by an html form
var b_canvas = document.getElementById("a");
var b_context = b_canvas.getContext("2d");
var img = b_canvas.toDataURL("image/png");
document.classic_form.jsvalue.value = img;
}
// opens the image file and displays it on the canvas
var canvas = document.getElementById("a");
var context = canvas.getContext("2d");
var img = new Image();
img.src = "backpicture.png";
img.onload = function() {
context.drawImage(img, 0, 0);
};
php code:
<?php
$str=$_POST['jsvalue'];
$file=fopen("backpicture.txt","w");
if(isset($_POST['submit']))
fwrite($file,$str);
fclose($file)
?>
it creates the file, but shows nothing on the canvas when I load the page again.
I also tried to use Canvas2Image.saveAsPNG(), but it still didn't work.
can you please help?
thanks!
In order to save the file properly you need to decode the base64 data (and save as png):
file_put_contents('backpicture.png', base64_decode($str));
This:
.toDataURL("image/png");
Will give you something like this:
image/png;base64,iVBORw0K...[base64encoded_string]...
As #Variant said, you need to base64_decode it, but, ignoring "image/png;base64,"
This should work:
file_put_contents('backpicture.png',base64_decode(substr($str,22)));

Is that possible to display image thumbnail without uploading it to the server?

I want let user to upload images to server add some info (like description, tags) about each image.I use Uploadify to upload multiple images.
I wonder if it is possible to show thumbnails of the images (while the user enters the additional info about each image) before the images are actually uploaded to the server.
I want user to have the following experience:
Select multiple image files
Immediately after that enter additional information about each image while seeing images thumbnails
Press Upload Files button to upload images to server, and go to drink coffee...
I found this script, but I think it also uploads the file before displaying the image thumbnail.
I would appreciate any help !
If you could enforce an HTML 5 capable browser you could use the file-api
Example: http://html5demos.com/file-api
Sure it is possible. Use the FileReader object to get a data URL (or use File.url if you are sure the Client implements it.) and assign it to an new Image()object. Then you can insert the image into DOM.
As an alternative to the standard-based HTML5 APIs, you can use a plugin such as Flash or Browserplus.
There is actually a ready-made application which might do exactly what you want. It's called Plupload. You can upload your files / images using a variety of "runtimes", and do client-side image resizing before uploading. I guess you can hook a thumbnail preview somewhere in there, in certain runtimes.
Otherwise, you can try building what you want from scratch, using the HTML5 / Gears / BrowserPlus / etc. APIs.
I'm pretty sure flash and java can both do it. Flash would require certain (obvious) security precautions (ie, you can do this for any file, it must be selected by the user).
Meanwhile java would show a security popup.
Xavier posted this solution on another thread, and I tried to improove it to work with multiple file inputs. I hope it helps.
$("body").on('change', 'input:file', function(e){
for (var i = 0; i < e.originalEvent.srcElement.files.length; i++) {
var file = e.originalEvent.srcElement.files[i];
var img = document.createElement("img");
var reader = new FileReader();
reader.onloadend = function() {
img.src = reader.result;
}
img.width = "50";
reader.readAsDataURL(file);
if($(this).next().hasClass('image_place')){
$(this).next('.image_place').html('').append(img);
}else {
$(this).after('<div class="image_place"></div>');
$(this).next('.image_place').append(img);
}
}
});
It scans all file inputs in the document body and reads the image using the FileReader api. If it finds any images, it creates a div called "image_place" where he puts the image. If there's already a image inside, the script replaces the image.

Categories