Android Compress Video Before Upload to Server

Android Compress Video before Upload to Server

I got a similar problem. Where I had to upload video in server having size within 5.4mb. But due to different camera resolutions of different phones, there was a problem. These are the solutions which I have opted

mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
mediaRecorder.setVideoEncodingBitRate(690000 );

Hope these will help you

how to reduce size of video before upload to server programmatically in android

You have two way to do that:

  • Encode it to a lower bit rate and/or lower resolution. Have a look here: Is it possible to compress video on Android?.

  • Try to zip/compress it. Have a look here: http://www.jondev.net/articles/Zipping_Files_with_Android_%28Programmatically%29

Unfortunately I never tried to do that with a 140MB video. This is why I suggested to you the first library (FFmpeg 4 Android).

By the way, try to increase also your UPLOAD_LIMIT on your server. But this is not the problem, even if you increase it to 10MB you still have to compress it. Do not try to increase the UPLOAD_LIMIT to 140MB, it will cause for sure an HTTP timeout.

Otherwise you need to enable a chunked upload.

Have a look on this discussion:

Android: OutOfMemoryError while uploading video - how best to chunk?

How to compress video and upload to server?

Client side (ANDROID) code

    package pack.coderzheaven;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;

public class UploadAudioDemo extends Activity {

private static final int SELECT_AUDIO = 2;
String selectedPath = "";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

openGalleryAudio();
}

public void openGalleryAudio(){

Intent intent = new Intent();
intent.setType("audio/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Select Audio "), SELECT_AUDIO);
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {

if (resultCode == RESULT_OK) {

if (requestCode == SELECT_AUDIO)
{
System.out.println("SELECT_AUDIO");
Uri selectedImageUri = data.getData();
selectedPath = getPath(selectedImageUri);
System.out.println("SELECT_AUDIO Path : " + selectedPath);
doFileUpload();
}

}
}

public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}

private void doFileUpload(){
HttpURLConnection conn = null;
DataOutputStream dos = null;
DataInputStream inStream = null;
String lineEnd = "rn";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1*1024*1024;
String responseFromServer = "";
String urlString = "http://your_website.com/upload_audio_test/upload_audio.php";
try
{
//------------------ CLIENT REQUEST
FileInputStream fileInputStream = new FileInputStream(new File(selectedPath) );
// open a URL connection to the Servlet
URL url = new URL(urlString);
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
dos = new DataOutputStream( conn.getOutputStream() );
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name="uploadedfile";filename="" + selectedPath + """ + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// close streams
Log.e("Debug","File is written");
fileInputStream.close();
dos.flush();
dos.close();
}
catch (MalformedURLException ex)
{
Log.e("Debug", "error: " + ex.getMessage(), ex);
}
catch (IOException ioe)
{
Log.e("Debug", "error: " + ioe.getMessage(), ioe);
}
//------------------ read the SERVER RESPONSE
try {
inStream = new DataInputStream ( conn.getInputStream() );
String str;

while (( str = inStream.readLine()) != null)
{
Log.e("Debug","Server Response "+str);
}
inStream.close();

}
catch (IOException ioex){
Log.e("Debug", "error: " + ioex.getMessage(), ioex);
}
}
}

server side (PHP) code

<?php
// Where the file is going to be placed
$target_path = "uploads/";

/* Add the original filename to our target path.
Result is "uploads/filename.extension" */
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);

if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "The file ". basename( $_FILES['uploadedfile']['name']).
" has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
echo "filename: " . basename( $_FILES['uploadedfile']['name']);
echo "target_path: " .$target_path;
}
?>

Things to keep in mind
1. Make sure your server is running.
2. Your server file path should be right.
3. Check your folder write permission in the server.

above client side code is for AUDIO files

you can use it for image,video also
by doing some changes in it like

  intent.setType("audio/*");

use video/image as per your requirement and use it

for zipping use below logic

One majorly annoying issue that I stumbled upon, was the fact that I couldn't send multiple attachments using Intents to the Google Mail app. The quickest way around that was of course to compress all of the files into one (ZIP).

After searching around online, I didn't really find much on zipping files on your Android device - most of the articles were for standard java applications, which assumed that all your files were in the current directory that you wanted to zip.

So, I used what I could and whipped up my own wrapper class that allows you to easily zip files in Android!

Here is the class:

  import android.util.Log; 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


public class Compress {
private static final int BUFFER = 2048;

private String[] _files;
private String _zipFile;

public Compress(String[] files, String zipFile) {
_files = files;
_zipFile = zipFile;
}

public void zip() {
try {
BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(_zipFile);

ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));

byte data[] = new byte[BUFFER];

for(int i=0; i < _files.length; i++) {
Log.v("Compress", "Adding: " + _files[i]);
FileInputStream fi = new FileInputStream(_files[i]);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(_files[i].substring(_files[i].lastIndexOf("/") + 1));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}

out.close();
} catch(Exception e) {
e.printStackTrace();
}

}

}

If that all makes sense to you already, then you probably won't be interested in my explanations below, otherwise, keep reading. :)

private static final int BUFFER = 2048; 

private String[] _files;
private String _zipFile;

These are the properties that I've declared for the class.

The first is the BUFFER (for reading the data and writing it to the zip stream), second is the _files array, which will hold all the files (path as well) that will be zipped up, and the third is the name of the zip file (path as well).

public Compress(String[] files, String zipFile) { 
_files = files;
_zipFile = zipFile;
}

This is the constructor, which is the first thing that gets called when instantiating the class - you'll pass it an array of the files you wish to zip, and a string of what the name of the final zip file will be. It then saves this data in the properties, to be used when you call the zip method.

BufferedInputStream origin = null; 
FileOutputStream dest = new FileOutputStream(_zipFile);

ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));

byte data[] = new byte[BUFFER];

Next we move into the zip method - the first things we do is setup our BufferedInputStream, which we'll be using to read the data from the file input stream (each file in the files array).

The FileOutputStream creates the zip file, and sets up the stream, which we then pass to the ZipOutputStream for writing to.

If you want more in depth details about each of these objects (classes), then do a quick search for FileOutputStream or ZipOutputStream in Google.

for(int i=0; i < _files.length; i++) { 
Log.v("Compress", "Adding: " + _files[i]);

FileInputStream fi = new FileInputStream(_files[i]);
origin = new BufferedInputStream(fi, BUFFER);

ZipEntry entry = new ZipEntry(_files[i].substring(_files[i].lastIndexOf("/") + 1));
out.putNextEntry(entry);

int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}

origin.close();
}

out.close();

And here we have the main loop, which will go through each file in the _files array and compress each one into the zip file.

Here we first setup a FileInputStream for reading the files - the BufferedInputStream will manage the amount of data that it'll be reading at a time (based on the BUFFER).

The ZipEntry is used for adding the actual file/directory structure - for example, if you add '/mnt/sdcard/data/myzip.zip', it would actually create that directory structure in the zip file, so if you want to just add the file into the root of the zip, you'll need to parse it out. Personally, I just used substring, and lastIndexOf to grab the file at the end.

Once the entry is set, you can add it to the zip output stream using out.putNextEntry.

Now we have another loop, which will be used for reading the data, 2048 bytes at a time, and write it to the zip output stream (to the new entry location).

Finally, we clean up - close the streams.

How can I reduce size of a video before uploading it to firebase?

Here is solution,
Create a file

    File file;
ProgressDialog dialogUpload;

Create Async Task to compress Video size

public class VideoCompressAsyncTask extends AsyncTask<String, String, String> {

Context mContext;

public VideoCompressAsyncTask(Context context) {
mContext = context;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
dialogUpload = new ProgressDialog(getActivity());
dialogUpload.setCancelable(false);
dialogUpload.setMessage("Please wait until the video upload is complete");
dialogUpload.show();
}

@Override
protected String doInBackground(String... paths) {
String filePath = null;
try {
String path = paths[0];
String directoryPath = paths[1];
filePath = SiliCompressor.with(mContext).compressVideo(path, directoryPath);

} catch (URISyntaxException e) {
e.printStackTrace();
}
return filePath;
}


@Override
protected void onPostExecute(String compressedFilePath) {
super.onPostExecute(compressedFilePath);
File imageFile = new File(compressedFilePath);
ByteArrayOutputStream byteBuffer;

float length = imageFile.length() / 1024f; // Size in KB
String value;
if (length >= 1024)
value = length / 1024f + " MB";
else
value = length + " KB";

String text = String.format(Locale.US, "%s\nName: %s\nSize: %s", getString(R.string.video_compression_complete), imageFile.getName(), value);
Log.e(TAG, "text: " + text);
Log.e(TAG, "imageFile.getName() : " + imageFile.getName());
Log.e(TAG, "Path 0 : " + compressedFilePath);

try {
File file = new File(compressedFilePath);
InputStream inputStream = null;//You can get an inputStream using any IO API
inputStream = new FileInputStream(file.getAbsolutePath());
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
VideoUri = Uri.fromFile(file);
try {
while ((bytesRead = inputStream.read(buffer)) != -1) {
output64.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
output64.close();
ba1 = output.toString();
// Here video size is reduce and call your method to upload file on server
uploadVideoMethod();

} catch (IOException e) {
e.printStackTrace();
}
}
}

On button click call AsycTask like below

new VideoCompressAsyncTask(getActivity()).execute(file.getAbsolutePath(), file.getParent());

Note: you may get file from onActivityResult.

Hope this will help you.



Related Topics



Leave a reply



Submit