Problem with upload and FFMPEG

Friends, I need to integrate this function of the system ffmpeg upload drag and drop. I’m doing well, but when I click to upload, nothing happens:

PHP Code:


$fn = (isset($_SERVER['HTTP_X_FILENAME']) ? $_SERVER['HTTP_X_FILENAME'] : false);

extension_loaded('ffmpeg') or die('Error in loading ffmpeg');

function ExtractThumb($in, $out)
{
    $thumb_stdout;
    $errors;
    $retval = 0;

    // Delete the file if it already exists
    if (file_exists($out)) { unlink($out); }
    $dir = rtrim(dirname(__FILE__), '/\\\\') . DIRECTORY_SEPARATOR . 'ffmpeg/ffmpeg';
    // Use ffmpeg to generate a thumbnail from the movie
    $cmd = "".$dir." -itsoffset -4 -i $in -vcodec mjpeg -vframes 1 -an -f rawvideo -s 320x240 $out 2>&1";
    exec($cmd, $thumb_stdout, $retval);
}

if ($fn) {

    // AJAX call
    file_put_contents(
        'uploads/' . $_SERVER['HTTP_X_HEIGHT'] . "_" . $fn,
        file_get_contents('php://input')
    );
    echo "$fn uploaded";
    ExtractThumb($fn, $fn . '.jpg');
    exit();

}
else {

    // form submit
    $files = $_FILES['fileselect'];

    foreach ($files['error'] as $id => $err) {
        if ($err == UPLOAD_ERR_OK) {
            $fn = $files['name'][$id];
            move_uploaded_file(
                $files['tmp_name'][$id],
                'uploads/' . $fn
            );
            echo "<p>File $fn uploaded.</p>";
        }
    }

}

If using Chrome, I highly recommend opening Developer Tools, then go to the Network tab, then drag your file onto your webpage, and the network tab should show the AJAX request. Click on the request to see what output was generated (any errors, notices, warning, echo statements, etc). Then post those here so we can help you decipher those messages.

After clicking the file .js, I click on Headers?

You will want to click on the php file that your Ajax executes (if you don’t see one being executed, then your ajax request never fired).

And you will be primarily looking at the Response

Here is an example

The php file is not listed in Network. = /

Silly question, as I assumed you are attempting to do this via Ajax based on your PHP code. Are you using Ajax? Or are you primarily trying to upload it via a button?

The upload should be done by clicking the button. The js is the one you helped me to adapt:


(function() {
	var filesThatWereDropped = new Array();
	
	// getElementById
	function $id(id) {
		return document.getElementById(id);
	}


	// output information
	function Output(msg) {
		var m = $id("messages");
		m.innerHTML = msg + m.innerHTML;
	}


	// file drag hover
	function FileDragHover(e) {
		e.stopPropagation();
		e.preventDefault();
		e.target.className = (e.type == "dragover" ? "hover" : "");
	}


	// file selection
	function FileSelectHandler(e) {

		// cancel event and hover styling
		FileDragHover(e);

		// fetch FileList object
		var files = e.target.files || e.dataTransfer.files;

		// process all File objects
		for (var i = 0, f; f = files[i]; i++) {
			ParseFile(f);
		}

	}
	
	function UploadFiles(e) {
		e.stopPropagation();
		e.preventDefault();
		
		// process all File objects
		while (filesThatWereDropped.length > 0) {
			var f = filesThatWereDropped.pop();
			UploadFile(f);
		}

	}


	// output file information
	function ParseFile(file) {

		fileInfo = "<div><strong>Nome:</strong> " + file.name + "</div>";
		fileInfo += "<div><strong>Tamanho:</strong> " + file.size + " kb</div>";
		fileInfo += "<div><strong>Tipo:</strong> " + file.type + "</div>";

		document.getElementById('messages').innerHTML = fileInfo + document.getElementById('messages').innerHTML;

		// display text
		if (file.type.indexOf("text") == 0) {
			var reader = new FileReader();
			reader.onload = function(e) {
				Output(
					"<p><strong>" + file.name + ":</strong></p><pre>" +
					e.target.result.replace(/</g, "<").replace(/>/g, ">") +
					"</pre>"
				);
			}
			reader.readAsText(file);
		}
		
		filesThatWereDropped.push(file);

	}


	// upload JPEG files
	function UploadFile(file) {

		// following line is not necessary: prevents running on SitePoint servers
		if (location.host.indexOf("sitepointstatic") >= 0) return

		var xhr = new XMLHttpRequest();
		if (xhr.upload && file.type == "application/vnd.rn-realmedia-vbr" || file.type == "application/pdf" || file.type == "video/x-ms-wmv" || file.type == "video/x-flv" || file.type == "image/png" || file.type == "image/jpeg" || file.type == "image/gif" && file.size <= $id("MAX_FILE_SIZE").value) {

			// create progress bar
			var o = $id("progress");
			var progress = o.appendChild(document.createElement("p"));
			progress.appendChild(document.createTextNode("upload " + file.name));


			// progress bar
			xhr.upload.addEventListener("progress", function(e) {
				var pc = parseInt(100 - (e.loaded / e.total * 100));
				progress.style.backgroundPosition = pc + "% 0";
			}, false);

			// file received/failed
			xhr.onreadystatechange = function(e) {
				if (xhr.readyState == 4) {
					progress.className = (xhr.status == 200 ? "success" : "failure");
				}
			};

			// start upload
			//'upload.php?titulo=teste'
			xhr.open("POST", $id("upload").action, true);
			xhr.setRequestHeader("X_FILENAME", file.name);
			xhr.setRequestHeader("X_SIZE", file.size);
			xhr.setRequestHeader("X_WIDTH", file.width);
			xhr.setRequestHeader("X_HEIGHT", file.height);
			xhr.send(file);

		}

	}


	// initialize
	function Init() {

		var fileselect = $id("fileselect"),
			filedrag = $id("filedrag"),
			submitbutton = $id("btnSubmit");

		// file select
		fileselect.addEventListener("change", FileSelectHandler, false);

		// is XHR2 available?
		var xhr = new XMLHttpRequest();
		if (xhr.upload) {

			// file drop
			filedrag.addEventListener("dragover", FileDragHover, false);
			filedrag.addEventListener("dragleave", FileDragHover, false);
			filedrag.addEventListener("drop", FileSelectHandler, false);
			filedrag.style.display = "block";

			submitbutton.addEventListener("click", UploadFiles, false);
		}

	}

	// call initialization file
	if (window.File && window.FileList && window.FileReader) {
		Init();
	}


})();

Ah, okay. So you would have needed to click the button to see the event register in the network tab.

Also, when you do that, be sure to change this code

    // form submit  
    $files = $_FILES['fileselect'];  

    foreach ($files['error'] as $id => $err) {  
        if ($err == UPLOAD_ERR_OK) {  
            $fn = $files['name'][$id];  
            move_uploaded_file(  
                $files['tmp_name'][$id],  
                'uploads/' . $fn  
            );  
            echo "<p>File $fn uploaded.</p>";  
        }  
    } 

To this

    // form submit  
    $files = $_FILES['fileselect'];  

    foreach ($files['error'] as $id => $err) {  
        if ($err == UPLOAD_ERR_OK) {  
            $fn = $files['name'][$id];  
            move_uploaded_file(  
                $files['tmp_name'][$id],  
                'uploads/' . $fn  
            );  
            echo "<p>File $fn uploaded.</p>";  
        }  
        else {
           echo "<p>{$id} - {$err}</p>";
        }
    }  

So you can see the error you are receiving

Same thing. Whether I drag to select a file and when I click “Upload” nothing happens and no error returns.

Doesn’t the upload button invoke the UploadFiles function in your JavaScript? If that is the case, you should see a request start to happen in the Developer Tools Network section.

Now is uploading normally. I had forgotten to enable video .avi: file.type == “video/avi”.

The problem now is that the image is not being generated, only. This is wrong, I believe:


if ($fn) {

	// AJAX call
	file_put_contents(
		'uploads/' . $_SERVER['HTTP_X_HEIGHT'] . "_" . $fn,
		file_get_contents('php://input')
	);
	echo "$fn uploaded";
	ExtractThumb('uploads/'.$fn, 'imgs/test.jpg');
	exit();

}

I would try this because you are technically renaming the file when it is written to your server to have the height as a prefix:

if ($fn) {

    $localFileName =  'uploads/' . $_SERVER['HTTP_X_HEIGHT'] . "_" . $fn;
    // AJAX call
    file_put_contents(
        $localFileName,
        file_get_contents('php://input')
    );
    echo "$fn uploaded";
    ExtractThumb($localFileName, $localFileName . '.jpg');
    exit();

}  

It worked! Would you like to do so, is?

ExtractThumb($localFileName, ‘imgs/’ . $localFileName . ‘.jpg’);

Currently, both the video and the image is saved in the directory /uploads. I created a directory /imgs inside.

Another thing I’m trying to do is record the width and height of the image. Are being saved as “undefined”.

I’m doing this:

JS


xhr.open("POST", $id("upload").action, true);
xhr.setRequestHeader("X_FILENAME", file.name);
xhr.setRequestHeader("X_SIZE", file.size);
xhr.setRequestHeader("X_WIDTH", file.width);
xhr.setRequestHeader("X_HEIGHT", file.height);
xhr.send(file);

PHP

$localFileName =  'uploads/' . $_SERVER['HTTP_X_HEIGHT'] . "_" . $fn; 

I’m not certain you can get the width and height of a video file the way you are attempting to. I bet it works for images, but not likely for video (I searched on google, but didn’t quickly find a solution, so you may want to try it yourself to see if you can come up with anything).

The below code should place the uploaded file in uploads, and the thumbnail in imgs

if ($fn) {   

    $uploadFileName =  'uploads/' . $_SERVER['HTTP_X_HEIGHT'] . "_" . $fn; 
    $imgFileName =  'imgs/' . $_SERVER['HTTP_X_HEIGHT'] . "_" . $fn; 
    // AJAX call   
    file_put_contents(   
        $uploadFileName,   
        file_get_contents('php://input')   
    );   
    echo "$fn uploaded";   
    ExtractThumb($uploadFileName, $imgFileName . '.jpg');   
    exit();   

} 

For video height and width I use ffmpeg. I get the dimensions of the images only.

How do I run the ExtractThumb () only if I’m uploading a video? I make an “if”?

I would add this to your JavaScript


			xhr.setRequestHeader("X_TYPE", file.type);

Then check for your video types in your PHP before calling ExtractThumb

So it does not work:

if ($_SERVER['HTTP_X_TYPE'] == 'video/avi' || $_SERVER['HTTP_X_TYPE'] == 'video/x-ms-wmv' || $_SERVER['HTTP_X_TYPE'] == 'video/x-flv' || $_SERVER['HTTP_X_TYPE'] == 'application/vnd.rn-realmedia-vbr'){
ExtractThumb($uploadFileName, $imgFileName . '.jpg');
}
var_dump($_SERVER['HTTP_X_TYPE']);
if ($_SERVER['HTTP_X_TYPE'] == 'video/avi' || $_SERVER['HTTP_X_TYPE'] == 'video/x-ms-wmv' || $_SERVER['HTTP_X_TYPE'] == 'video/x-flv' || $_SERVER['HTTP_X_TYPE'] == 'application/vnd.rn-realmedia-vbr'){ 
ExtractThumb($uploadFileName, $imgFileName . '.jpg'); 
} 

Open Developer Tools, Network tab, upload your video, click on the PHP file and paste the output of the Response section so I can see what the value of HTTP_X_TYPE is

string(9) “video/avi”