How can i capture slow motion video in my app?
I tried using
mMediaRecorder.setVideoFrameRate(100);
but app crashes if i set the value 20 or more with IllegalStateException
.
I have researched a lot.Normal video is between 24 and 30 fps.To see slow motion video we need to capture 100-120 fps but device does not allow that.But I see the default camera in my device has an option of Slow motion.Also few apps in play store allow to create slow motion videos.I also tried setting higher setCaptureRate()
,but with that also normal mode video is captured.At few places it is mentioned that slow motion movie can be accomplished through OpenCV/JavaCV
libraries but i failed to understand how to use these libraries to capture slow motion video in android?
From the source you provided (CamcorderProfile), all you have to do is INCREASE taken images per second:
mMediaRecorder.setVideoFrameRate(QUALITY_HIGH_SPEED_LOW);
or
mMediaRecorder.setVideoFrameRate(QUALITY_HIGH_SPEED_HIGH);
So, if you take a 100 images per seconds, and show 25 Frames per second, that recorded second takes 4 seconds to shown
Please, read the documentation on the class you are using:
public static final int QUALITY_HIGH_SPEED_LOW
High speed ( >= 100fps) quality level corresponding to the lowest available resolution.
For all the high speed profiles defined below ((from QUALITY_HIGH_SPEED_LOW to QUALITY_HIGH_SPEED_2160P), they are similar as normal recording profiles, with just higher output frame rate and bit rate. Therefore, setting these profiles with setProfile(CamcorderProfile) without specifying any other encoding parameters will produce high speed videos rather than slow motion videos that have different capture and output (playback) frame rates. To record slow motion videos, the application must set video output (playback) frame rate and bit rate appropriately via setVideoFrameRate(int) and setVideoEncodingBitRate(int) based on the slow motion factor. If the application intends to do the video recording with MediaCodec encoder, it must set each individual field of MediaFormat similarly according to this CamcorderProfile.
Although I am not able to capture smooth slow motion video without jerks but i am able to convert captured video into slow motion using ffmpeg which comes out to be very smooth and even.For integrating FFmpeg in android we can use precompiled libraries like ffmpeg-android.
As per the case in question,we can capture video from camera and then convert it into slow motion using ffmpeg.
To create a slow motion video we can use the below command-
String[] complexCommand = {"-y", "-i", inputFileAbsolutePath, "-filter_complex", "[0:v]setpts=2.0*PTS[v];[0:a]atempo=0.5[a]", "-map", "[v]", "-map", "[a]", "-b:v", "2097k", "-r", "60", "-vcodec", "mpeg4", outputFileAbsolutePath};
Here,
-y
Overwrite output files without asking
-i
ffmpeg reads from an arbitrary number of input “files” specified by the -i option
-map
Output link labels are referred to with -map.
-b:v
Set the video bitrate
-r
Set frame rate
-vcodec
Set the video codec
-filter_complex filtergraph
Define a complex filtergraph, i.e. one with arbitrary number of inputs and/or outputs.
The filter works by changing the presentation timestamp (PTS) of each video frame.To slow down your video, you have to use a multiplier greater than 1. For example, if there are two succesive frames shown at timestamps 1 and 2, and you want to slow down the video, those timestamps need to become 2 and 4, respectively.Thus, we have to multiply them by 2.0.
You can speed up or slow down audio with the atemto audio filter.The atempo filter is limited to using values between 0.5 and 2.0 (so it can slow it down to no less than half the original speed, and speed up to no more than double the input).To slow down the audio to half of its speed we have to use atempo value 0.5 .
Check out this fffmpeg video editor tutorial which I have written on my blog which includes creating slow motion video and the complete code for the tutorial here.
What worked for me was to put higher the capture rate of mMediaRecorder
like:
mMediaRecorder.setVideoFrameRate(profile.videoFrameRate / 2);
mMediaRecorder.setVideoEncodingBitRate(profile.videoBitRate / 2);
mMediaRecorder.setCaptureRate(profile.videoFrameRate);
Where profile
is the CamcorderProfile
set with QUALITY_HIGH
(I can't have more since I'm using a LG G2, API 19).
Here in my case,profile.videoFrameRate
is equal to 30.
More info about setCaptureRate
in the official documentation:
Set video frame capture rate. This can be used to set a different video frame capture rate than the recorded video's playback rate. This method also sets the recording mode to time lapse. In time lapse video recording, only video is recorded. Audio related parameters are ignored when a time lapse recording session starts, if an application sets them.
The video recorded result is twice as long as the initial capture. However setting the capture rate disables the audio. In my case, my max fps rate seems to be 30fps, and then it got played back at 15fps.
Hope it helps.
Try this code.It will help...
myCamera = getCameraInstance();
mediaRecorder = new MediaRecorder();
myCamera.unlock();
mediaRecorder.setCamera(myCamera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
mediaRecorder.setPreviewDisplay(mSurfaceView.getHolder().getSurface());