15

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?

Android Developer
  • 9,157
  • 18
  • 82
  • 139
  • Hi, have you succeed? Else do you know any android app wich really capture at 120 fps? Thanks – Jugali Lakota Jun 04 '16 at 22:58
  • @JugaliLakota 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..Check out my answer – Android Developer Mar 25 '17 at 09:08

4 Answers4

14

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.

Community
  • 1
  • 1
Bonatti
  • 2,778
  • 5
  • 23
  • 42
  • so u want me to put- `mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH_SPEED_HIGH));` and then `mMediaRecorder.setVideoFrameRate(100)` ?????plese check ur answer..i can't put `QUALITY_HIGH_SPEED_HIGH` inside `mMediaRecorder.setVideoFrameRate()` – Android Developer Oct 16 '15 at 12:08
  • 1
    No... What I want you to do, is to understand the commands you are issuing to the device. if you use [setCaptureRate(`a Number`)](http://developer.android.com/intl/es/reference/android/media/MediaRecorder.html#setCaptureRate%28double%29) then by increasing this value, you can add more frames and "film in slow motion"... or you could use the already ready stuff from the class CamcorderProfile.... however, what you should not do, is just keep on trying code without understanding what they do. – Bonatti Oct 16 '15 at 12:29
  • okay..now i tried setting `mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH_SPEED_720P));` and then `mMediaRecorder.setVideoFrameRate(30);` but my app crashed...its not working for higer values in `setVideoFrameRate()` – Android Developer Oct 16 '15 at 12:50
  • 1
    Read my last comment again. note the function used, as well as the documentation that is linked. – Bonatti Oct 16 '15 at 16:31
  • Thanku for ur time..I tried setting ` `mMediaRecorder.setCaptureRate(CamcorderProfile.QUALITY_HIGH_SPEED_LOW);` where `CamcorderProfile.QUALITY_HIGH_SPEED_LOW` is equal to `2000`...this will capture 2000 frames per second..now i want to show less number of frames per second..how should i do that?I tried setting -`mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_CIF));` where `CamcorderProfile.QUALITY_CIF` is equal to 3.but still the recorded video shows normal video.. – Android Developer Oct 16 '15 at 19:24
  • Hey have u tried ur answer?does it capture slow motion video?I tried many things but still I am not able to capture slow motion video... – Android Developer Oct 22 '15 at 06:53
  • 1
    QUALITY_HIGH_SPEED_LOW is NOT equal to 2000 fps!! Do you have an idea what a 2000 fps camera would cost?! Stop being stubborn and read the documentation! Next, you need to play the recorded video in a media player which supports "slow-motion". you can write your own, or you can use VLC for this. – Mibit Oct 22 '15 at 15:01
  • @AlexMo I have read complete document.As per the document I tried above code updated in question.It produces slow motion but that is not smooth and appears like changing images.Any way to improve it? – Android Developer Oct 23 '15 at 07:26
  • try to decrease the quality (QUALITY_LOW) and increase it step by step if the play-back experience is better with lower quality. Which kind of smartphone do you use for testing? – Mibit Oct 23 '15 at 08:59
  • @AlexMo I am using Asus Zenfone 2 ZE551ML with primary camera 13 MP, 4128 x 3096 pixels and Video 1080p@30fp..If I use `QUALITY_LOW` it does not produces slow motion video – Android Developer Oct 23 '15 at 10:00
  • @AndroidLearner Again. Try to search for code samples that allow you to show the video you just capture, with a different refresh rate.... As you stated, `It produces slow motion` .... `but that is not smooth`... what is happening is, the refresh rate from your video player is capped at something (lets guess at 30 FPS = Frames per second)... What you need to do, is to record at a know rate, then show at mulitples of that rate.. if you are recording at 30 FPS, you should shown at 30/45/90/etc. values, so that the player does not skip frames, or merge them. Where/HOW are you showing the video? – Bonatti Oct 23 '15 at 10:13
  • [If you search](https://www.google.com.br/search?q=android+VideoView+set+play+rate&ie=utf-8&oe=utf-8&gws_rd=cr&ei=8wkqVvCwHYv9wQSEu7eYAQ), you will see that the default VideoView is not able to alter/set its play rate. The video player is a facility for developers that just want to show something... If you are altering default behaviors, then you must search for a customizable video player, or code your own... Again, you have captured the movie in "slow motion" i.e. with more frames, then you must now shown that, in "slow motion", i.e. with a linear frame rate from the file. – Bonatti Oct 23 '15 at 10:23
  • I am storing the captured video in device storage ... I am uploading the video to server by fetching that video from device storage...Then I am loading videos from server and then playing in my app...I want that the captured video which is stored in device storage should have smooth slow motion – Android Developer Oct 23 '15 at 10:27
  • I just cannot get this to work. Can you please have a look at my question? https://stackoverflow.com/q/35116159/629663 – Siddharth Feb 04 '16 at 20:18
4

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.

Android Developer
  • 9,157
  • 18
  • 82
  • 139
0

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 CamcorderProfileset 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.

fxhereng
  • 11
  • 5
-2

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());
Naveen
  • 814
  • 2
  • 9
  • 22
  • 4
    why is anyone upvoting this answer when it has absolutely nothing to do with the question? What if I post an answer for a really good pudding recipe... will that get up-votes too? – Yevgeny Simkin Apr 19 '16 at 05:58