Compress video like whatsapp - android

I'm not an expert in Video Editing but what I want to understand the logic of Whatsapp video processing.
First of all I have noticed that whatever the file is, Whatsapp sets the limit of Uploaded videos to 16MB, after which whatsapp crops the video to not exceed the limit. is this a convention or it's a personal choice ?
Secondly, When a video is recorded using the Camera it's not compressed by default, so whatsapp compresses it using FFMPEG I guess, and it takes no time. (tried for a video of 1min 1920x1080 with 125MB of size, becomes 640x360 with 5MB of size in no time, and the upload starts automatically).. how may they do this ? and why the choice of 640x360, It seems to me very fast for 2 asynchronous tasks : Compression + Upload.
When I run the compression command ffmpeg -y -i in.mp4 -codec:v libx264 -crf 23 -preset medium -codec:a libfdk_aac -vbr 4 -vf scale=-1:640,format=yuv420p out.mp4 it takes approximatively 1 min and the video is being rotated !! :D
Finally, when we download a video from Youtube it's already compressed (I guess) and whatsapp doesn't even try to compress it. So I think that it automatically detects thats the video is compressed. How can we detect this ?
Thank you.

Here are possible answers to your questions:
Quest. 1: Its a personal choice. The whatsapp team is trying to offer the best User Experience (UX) they could to users of their app, that is why they have kept a limit of 16MB for video file. Imagine how long it would take to upload a file of about 125MB. Hence, the app compresses the file for quicker upload and seamless experience.
Quest. 2: I guess you already answered this question yourself - Asynchronous programming. The large video file you feed it, gets encoded into a compressed format according to the algorithm they have written for the app. As Devs., we all know about algorithms and we all know there are things you can do to speed up execution. I guess they implemented their very own algorithm using Asynchronous programming that speeds up the process. The ffmpeg library you mentioned i guess was coded in C which i think doesn't support async call (not so sure though). After this, upload takes over.
Quest. 3&Finally: Codecs are standards. If you encode a video file to MPEG4, then try to re-encode it again to MPEG4 even using another program, you will get the same result as far as both programs are using same encoding standards, i.e. they didn't implement a specific algorithm for their programs(this takes years of work). So, when your Whatsapp tries to encode the file, it gives the same result.
Hope I have been able to answer your questions.
MichVeline

Use media codec instead of ffmpeg for better performance. If your use case is only to compress the video, MediaCodec would be best option for android. It helps you to write the code asynchronously and also gives you lots of freedom to optimize you algorithm.

Related

How to compress video in android faster?

I have recently used ffmpeg library for android to compress the video of length 10 seconds and size nearly 25 MB. Following are the commands i tried to use:
ffmpeg -i /video.mp4 -vcodec h264 -b:v 1000k -acodec mp2 /output.mp4
OR
ffmpeg -i input.mp4 -vcodec h264 -crf 20 output.mp4
Both of the commands were too slow. I canceled the task before it completed because it was taking too much time. It took more than 8 minutes to process JUST 20% of the video. Time is really critical for me so i can't opt for ffmpeg. I have following question:
Is there something wrong with the command or ffmpeg is slow anyway?
If its slow then is there any other well documented and reliable way/library for video compression that i can use in android?
Your file is in mp4 container and already has its streams in some predefined codec.
Now the size of any container(not specifically mp4) will depend upon what kind of compression(loosely codec) is used for compressing the data. This is why you will see different size for the same content in different formats.
There are other parameters which can affect the size of the file i.e frame rate, resolution, audio bit rate etc. If you reduce them then the size of file becomes less. e.g. in youtube you can choose to play video at a lower rate when bandwidth is the issue.
However, if you choose to do this you will have to re-process the entire file again and its going to to take a lot of time since you are demuxing the container, decoding the codec, applying filter(reducing frame etc), then recording, and then again remuxing. This entire process if not worth few extra MB of saving unless you have some compelling use case.
One solution is to use a more powerful machine but again this is limited by the architecture/constraint of the application to utilize powerful machine. To answer specifically for ffmpeg it wont make much difference.

Android, fast video processing

I have troubles in my current project which requires video processing. Basically crop function (video should be squared), trimming (video shouldn't be longer than 30 seconds) and quality reduction (bitrate should be equal 713K).
I've succesfully embedded FFmpeg into application, all functions are working quite fine except one major detail - processing as per my boss is taking too long time. For video that have around 52 MB for 36 seconds it's taking 50 seconds to perforn all the operations (I'm trimming video to 30 seconds before any other operation obviously). The problem is that on parallel project on iOS video processing takes like 10-15 seconds for greater files. I assume that it's related to fact that they're using Apple QuickTime format which obviusly was developed by Apple so it's not surprising that it's working quite fast.
So well, it was introduction, now my question: is there any way for Android to process any video in any quality (for now we can assume that all videos are in h264) in time of 10-15 seconds (not more then in 30 seconds, as my boss said)? Some alternative to FFmpeg, that can perform operations faster? I'nm pretty sure that there is no possibility to perform such work in a such short time, since I already feel like I searched thought while Internet, but I want to make sure that there is really no possibility to do such work. If anyone can provide me links to solution more faster than FFmpeg or confirm that there is no such solution, I will be very gratefull.
Update
Thanks to Alex Cohn I've resolved this with MediaCodec. After a while, I got 20 seconds processing on 52MB video with cropping to square and lowering bitrate. For any future Googlers out of here I can suggest to take a look at this respository:
Many stuff about MediaCodec
and more precisely at this file: Extract, edit and encode again, video and audio
If the video has been recorded on the same device, you have a very good chance that MediaCodec and native Android media APIs will be much faster (running both decoder and encoder in HW). Otherwise, you can try to decode the video with MediaCodec, and fall back to FFmpeg software decoder if it fails. Even then, if you can use MediaCodec for compression, this alone may deliver performance that will satisfy your boss.
There exists a (deprecated) project called libstagefright that builds FFmpeg with support for the hardware codec, and it was designed to work on API 10+.
Don't forget to compare the CPU characteristics of your Android device and the iOS platform (if that's a 6S, they have a significant fore). Consider multithreaded encoding and decoding.
BTW: Note that FFmpeg does not come with H264 encoder, and the typical bundle of FFmpeg+x264 is GPL, and requires all your app to be open sourced (or pay a hefty license fee for x264, but still be forced to comply with LGPL of FFmpeg).
Note that you can make square video by manipulating the MP4 headers only, without transcoding!

compress video file before uploading to server

I am trying to upload the video file to server , for small size video like 4 to 5 mb it works fine , but if when i am trying to upload the video more than 15 to 20 mb , it takes too much time for upload , that's why i want to compress the video , is there any library or tool available for compressing video before uploading to server.
thanks.
There are few approaches that you can take to upload larger size video on to the server:
1) You can make use of standard way of recording it across all mobiles which give you standard size:
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
mediaRecorder.setVideoEncodingBitRate(690000 );
2) Make use of ffmpeg or work around with it, it might help to compress video.
https://github.com/halfninja/android-ffmpeg-x264
3) (Recommended) Compressing the video according to me will degrade the quality of video to far worse stage, so what the other work around and best which majorly used is:
Make a Byte array of the video
Make small Chunks of that byte array
Make a Web-service on Server reads this Chunk one by one, send it in queue.
Once received on server make a Video file out of it again.
Runs this Operation in Background async or as service anyways. So it doesnt effect foreground process. Once its done Just Notify!!
Hope this will help
You can try use the FFMpeg library.
It's easy way to compress videos.
Can you check the site https://www.ffmpeg.org/ for more information, or post as comment what are you need to compress.
If you change CRF with the command -crf "15~25". It's a good compress video with good quality.

encoding images to video with ffpmeg

We are working on Android 3D Animation App.
We need to identify images, then save and encode the same to video using FFmpeg (Since Android API is not supporting). Once the video is generated, then audio is appended to the same.
We are facing 2 problems on this.
First is the memory leakage issue at the time of saving identified images for encoding. CPU of emulator is getting overloaded. Whether FFpmeg is called every time when an image is selected? How to resolve this issue?
Second (in case if we get through the first one) we are not able to encode the selected images, since this is generating green color video. What could be reason for this?
Whether is there any tool other than FFmpeg for video encoding from images to H264?
Whether images version (Rastar or Vector) will impact this video encoding?
Whether Android OS version is considered?
Any valuable inputs on this will be greatly appreciated.
Thanks
I played also with that idea using ffmpeg on an android phone, but I would suggest to do that on a server which has much more power. On a server you don't need to think about the cpu load of a smartphone.
In general for improving your ffmpeg run you need to publish the ffmpeg calls. ffmpeg is quiet complex where the order of the parameters directly correlates with the efficience.
I don't know which container format you preferer but maybe a simple mjpeg codec could work for you. AFIK there a just the jpeg frames connected to each other which should be much simple then encoding a video to h264/x264 (ffmpeg uses the last one).
A combination of both may be to generate a mjpeg stream which will be converted on the server side to a h264 video which may be downloaded to the client. but that really depends on the length of the video if you don't want to waste the traffic of your customers.

How to record the http live streaming from an IP Cam

I have created the application in which the client can view the ip camera which is giving
an http live stream of MJPEG using this link
Android ICS and MJPEG using AsyncTask
Now i want the user to record the video into its memory card .
I have googled for a while and the only two approaches which came in my mind :-
Either i keep storing the jpeg images and when user clicks stop recording then i
somehow clip all the images as to provide a 3GP video or some other file format.
But i don't know how to create the video from all the images and will this be an efficient
approach or not.
Or i do ffmpeg and in this case i will have to deal with NDK and it seems to be a longer
path which may lead to nowhere :P
So is FFMPEG a better option? If yes please share some links or is the first option better.
Thanks in advance
FFmpeg is the better option, but you'll probably get stuck with a pretty poor encoding resolution/compression. Maybe some low quality MPEG-4 like xvid will work, but even that might require too high of performance from the CPU.
Android doesn't have an API to access the video encoder logic in the SoC, so a native implementation is pretty much your only choice. If so, FFmpeg through NDK is probably the easiest.

Categories

Resources