1

I am looking for a way to lower the size of images and videos before I upload them to a server, at the moment I am sending files that are way too big and I cant seem to find any solution of how to compress the files, I know apps like whatsapp and facebook compress videos in a few seconds and cut them in 90% size, anyone got advice, direction I would be grateful.

Thank you.

Omry Rozenfeld
  • 125
  • 2
  • 8
  • This is a little overly broad of a question for here, my assumption is Facebook and Whatsapp use or write a image/compressor that they use to change the file attributes like compression ratio or codec type. – hoss May 21 '15 at 17:51
  • Do you know how i can achieve something similar to them using some library? If so, would you point me to that library perhaps? Thanks – Omry Rozenfeld May 22 '15 at 16:05

2 Answers2

3

You can use ffmpeg, an open source video library, to do the compression.

Be aware that video compression is generally quite compute intense so it is unlikely to take just 'a few seconds' except for small videos.

There are a number of ways to include ffmpeg in your application. Take a look at these 'wrapper' projects for examples to ether use or to help you build your own ffmpeg library:

As an example, the following code will compress an mp4 video file (default compression) once you have selected or built a ffmpeg wrapper (this code uses a custom ffmpeg library but it should give you an overview and you should be able to substitute one of the examples above):

public class VideoCompressionTask extends AsyncTask<String, String, String> {
/* This Class is an AsynchTask to compress a video on a background thread
 * 
 */

@Override
protected String doInBackground(String... params) {
    //Compress the video in the background

    //Get the the path of the video to compress
    String videoPath;
    String videoFileName;
    File videoFileToCompress;
    if (params.length == 1) {
        videoPath = params[0];
        videoFileToCompress = new File(videoPath);
        videoFileName = videoFileToCompress.getName();
    } else {
        //One or all of the params are not present - log an error and return
        Log.d("VideoCompressionTask","doInBackground wrong number of params");
        return null;
    }

    //Make sure the video to compress actually exists
    if(!videoFileToCompress.exists()) {
        Log.d("VideoCompressionTask","doInBackground video file to compress does not exist");
        return null;
    }

    //If the compressed file already exists then delete it first and let this task create a new one
    File compressedVideoFile = new File(compressedFilePath);
    if(compressedVideoFile.exists()) {
        compressedVideoFile.delete();
    }

    String argv[] = {"ffmpeg", "-i", videoPath, "-strict", "experimental", "-acodec", "aac", compressedFilePath};
    int ffmpegWrapperreturnCode = FfmpegJNIWrapper.call_ffmpegWrapper(appContext, argv);
    Log.d("VideoCompressionTask","doInBackground ffmpegWrapperreturnCode: " + ffmpegWrapperreturnCode);

    return(compressedFilePath);
}
Mick
  • 24,231
  • 1
  • 54
  • 120
2

I had exact need today so came up with this code. Send this function a bitmap and it will return a file path (local) of compressed image. Then create a File object with the returned file path and send it to server:

 public File compressImage(Bitmap bmp) {
        Bitmap scaledBitmap = null;

        int actualHeight = bmp.getHeight();
        int actualWidth = bmp.getWidth();

//      max Height and width values of the compressed image is taken as 816x612
        float imgRatio = actualWidth / actualHeight;
        float maxRatio = logoMaxWidth / logoMaxHeight;
//      width and height values are set maintaining the aspect ratio of the image
        if (actualHeight > logoMaxHeight || actualWidth > logoMaxWidth) {
            if (imgRatio < maxRatio) {
                imgRatio = logoMaxHeight / actualHeight;
                actualWidth = (int) (imgRatio * actualWidth);
                actualHeight = (int) logoMaxHeight;
            } else if (imgRatio > maxRatio) {
                imgRatio = logoMaxWidth / actualWidth;
                actualHeight = (int) (imgRatio * actualHeight);
                actualWidth = (int) logoMaxWidth;
            } else {
                actualHeight = (int) logoMaxHeight;
                actualWidth = (int) logoMaxWidth;
            }
        }
        try {
            scaledBitmap = Bitmap.createScaledBitmap(bmp, actualWidth, actualHeight, true);
        } catch (OutOfMemoryError exception) {
            logoUploadFaied();
            exception.printStackTrace();
        }
        String uriSting = (System.currentTimeMillis() + ".jpg");
        File file = new File(Environment.getExternalStorageDirectory()
                + File.separator + uriSting);
        try {
            file.createNewFile();
        } catch (IOException e) {
            logoUploadFaied();
            e.printStackTrace();
        }

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            logoUploadFaied();
            e.printStackTrace();
        }
        try {
            fos.write(getBytesFromBitmap(scaledBitmap));
            fos.close();
            //recycling bitMap to overcome OutOfMemoryError
            if(scaledBitmap!=null){
                scaledBitmap.recycle();
                scaledBitmap=null;
            }
        } catch (IOException e) {
            logoUploadFaied();
            e.printStackTrace();
        }
        return file;
    }
Karan
  • 2,120
  • 15
  • 27
  • glad to help! video compression can be tricky. you can start here http://stackoverflow.com/questions/15950610/video-compression-on-android-using-new-mediacodec-library – Karan May 21 '15 at 18:08