I've looked around but cannot find an answer to my issue. I'm setting the MediaRecorder as follows:
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
if(CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_480P))
mMediaRecorder.setProfile(CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_480P));
else
mMediaRecorder.setProfile(CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_LOW));
On my Samsung S3, QUALITY480 is chosen by the code above. A video file is created but it has zero bytes. The same happens if I explicitly set it to QUALITY_LOW. If I set the profile to QUALITY_720P, then I get proper video. Anyone have any ideas? I don't want to set it to 720 so I can keep the file size down.
Thanks!
I hope you have more code than this bc media recorder is not simple to control see the docs..http://developer.android.com/reference/android/media/MediaRecorder.html
Ummm at first look i would say that you are using camera2 api and you are getting true back for your first desired profile but it is not available on device see the has profile doc on android Dev
Related
My app requires to record a video to capture the IFrames only (and not the P/B frames).
I am making use of the Media Recorder to capture the video (Not using cameraX as I need HEVC and camerax is recording in H.264).
The 'MediaRecorder.MetricsConstants.VIDEO_IFRAME_INTERVAL' is set to 1, by default - hence I get an IFrame every 1 sec and the rest of the frames in a second are 'P'. I need the VIDEO_IFRAME_INTERVAL constant to be set to 0, inorder to make all the frames 'I'. I have tried different ways to set it. Any help would be much appreciated.
I have tried setting it this way:
mRecorder.metrics.deepCopy().apply {
this.putInt(MediaRecorder.MetricsConstants.VIDEO_IFRAME_INTERVAL, 0)
}
Even if I set it to '2', '5' or '10' it doesn't seem to be having an effect.
I'm using the MediaRecorder to record the device's screen. I'd like to be able to control the frame rate of the video captured.
I've tried setting both the Capture Rate and the VideoFrameRate properties of the MediaRecorder, but they seem to have no effect:
this.mRecorder.setCaptureRate(this.fps);
this.mRecorder.setVideoFrameRate(this.fps);
As per the documentation (setCaptureRate, setVideoFrameRate), I am calling setCaptureRate and setVideoFrameRate after setting the format and video source, and before calling prepare:
this.mRecorder = new MediaRecorder();
this.mRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
this.mRecorder.setVideoSource(2);
this.mRecorder.setOutputFormat(2);
this.mRecorder.setOutputFile(this.mFilePath);
this.mRecorder.setVideoSize(screenWidth, screenHeight);
this.mRecorder.setVideoEncoder(2);
this.mRecorder.setAudioEncoder(2);
this.mRecorder.setVideoEncodingBitRate(this.mBitRate);
this.mRecorder.setCaptureRate(this.fps);
this.mRecorder.setVideoFrameRate(this.fps);
this.mRecorder.prepare();
I've checked, and this.fps is set to 5, so it is not like some other incorrect value... and the documentation says:
The fps can go as low as desired
Does anyone know how to set the FPS?
I have a Huawei P9 Plus smartphone running Android 7.0. I'm using MediaRecorder to record the front cam. It is a 8 MP camera. I'm using the following settings (I think this is the most important part, I'm not posting the whole class because it is too much lines of code):
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
mMediaRecorder.setOutputFile(videoFile.getAbsolutePath());
mMediaRecorder.setVideoEncodingBitRate(8000000);
mMediaRecorder.setVideoFrameRate(30)
mMediaRecorder.setVideoSize(1024 , 1920)
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaSurface = MediaCodec.createPersistentInputSurface();
mMediaRecorder.setInputSurface(mMediaSurface);
mMediaRecorder.prepare();
With this settings it works but sometimes the video is a bit jerky. Strange is also that with video size 1024 x 1920 it works but when I set 1080 x 1920 it does not work anymore (there is no error but the video is completely corrupted). Why is that? In the supported resolutions I got from the front cam characteristics 1080 x 1920 is listed but not 1024 x 1920.
Are my other settings ok? Is setVideoEncodingBitRate ok for a 8 MP camera?
I have also tried to use a given profile as follows:
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFile(videoFile.getAbsolutePath());
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_1080P));
mMediaRecorder.setVideoFrameRate(30)
mMediaSurface = MediaCodec.createPersistentInputSurface();
mMediaRecorder.setInputSurface(mMediaSurface);
mMediaRecorder.prepare();
When I run it this way I'm getting an error when I try to stop MediaRecorder (stop failed: -1007), probably because starting video recording did not succeed. Why? Did I make a mistake?
When I run it this way I'm getting an error when I try to stop MediaRecorder (stop failed: -1007), probably because starting video recording did not succeed. Why? Did I make a mistake
Your probably right. Try checking or adding property(e.g Boolean) to determine if the recorder has already started. In that case you won't be able to call stop if it is not yet started.
mMediaRecorder = new MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
// activate this for recording with sound\
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoSize(getMaxSupportedVideoSize().width,getMaxSupportedVideoSize().height);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
// Step 4: Set output file
mMediaRecorder.setOutputFile(getOutputMediaFile("movie"));
// Step 4: Set output file
mMediaRecorder.setOutputFile(getOutputMediaFile("movie"));
// Step 5: Set the preview output
mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
mMediaRecorder.setOrientationHint(90);
above code is working fine But, the quality of video is not as same as video i shoot over native android camera, my video recorded using media recorder is poor quality compare to the native one, how can i improve the video quality.
If any one knows help me out.Thanks
I'm not a Java/Android dev, I'm using Xamarin and C#, but I had much the same problem, and my solution should be directly applicable (even the syntax is almost identical).
I found that if you're using setCamera (and are previewing what the camera sees before you start up your mediaRecorder) then it won't let you change the quality settings on the mediaRecorder.
And then when you call mediaRecorder.start(), it either crashes or freezes or displays garbage.
Basically, as long as the Camera is previewing, the MediaRecorder won't be allowed to start recording at a different quality to that which the camera already has. You need to
stop the camera preview,
take away its preview surface
assign the camera to the MediaRecorder (with setCamera)
set the MediaRecorder up with the quality you need
then reattach the preview surface
Then when you start recording, everything works as it should.
So in your case, just before you call mediaRecorder.setCamera(), try the following:
mCamera.stopPreview();
mCamera.setPreviewDisplay(null);
Then further down, do your
mRecorder.setCamera()
That was the solution for me. I can now set the video quality to 720p (or 1080p) and it works perfectly.
However, when you stop recording, your previewing will also stop.
You'll probably need to reinstate your
mCamera.setPreviewDisplay(mPreview.getHolder().getSurface())
to what it was before, and restart the actual preview.
I hope it works for you too :)
Alternative 1
recorder.setVideoSize(640, 480);
recorder.setVideoFrameRate(16); //might be auto-determined due to lighting
recorder.setVideoEncodingBitRate(3000000);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// MPEG_4_SP
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
Alternative 2
CamcorderProfile cpHigh = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
recorder.setProfile(cpHigh);
Replace this code:
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoSize(getMaxSupportedVideoSize().width,getMaxSupportedVideoSize().height);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
with :
mMediaRecorder.setProfile(CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH));
Now, i have made a library to concatenate 2 videos, using the mp4parser library.
And with this i can pause and resume recording a video (after it records the second video, it appends it to the first one).
Now, my boss told me to do a wrapper, and use this for the phones that do not have hardware support for pausing a video. For phones that have that (Samsung Galaxy S2 and Samsung Galaxy S1 can pause a video recording , with their camera application), i need to do this with no libraries, so it would be fast.
How can I implement this native, if as seen on the media recorder state diagram, http://developer.android.com/reference/android/media/MediaRecorder.html , there is no pause state?
I have decompiled the Camera.apk app from an Samsung Galaxe Ace, and the code has in the CamcorderEngine.class a method like this:
public void doPauseVideoRecordingSync()
{
Log.v("CamcorderEngine", "doPauseVideoRecordingSync");
if (this.mMediaRecorder == null)
{
Log.e("CamcorderEngine", "MediaRecorder is not initialized.");
return;
}
if (!this.mMediaRecorderRecording)
{
Log.e("CamcorderEngine", "Recording is not started yet.");
return;
}
try
{
this.mMediaRecorder.pause();
enableAlertSound();
return;
}
catch (RuntimeException localRuntimeException)
{
Log.e("CamcorderEngine", "Could not pause media recorder. ", localRuntimeException);
enableAlertSound();
}
}
If I try this.mMediaRecorder.pause(); in my code, it does not work, how is this possible, they use the same import (android.media.MediaRecorder). Have they rewritten the whole code at a system level?
Is it possible to take the input stream of the second video (while recording it), and directly append this data to my first video?
for my concatenate method, i use 2 parameters (the 2 videos, which both are FileInputStream), is it possible to take the InputStream from the recording function and pass it as the second parameter?
If I try this.mMediaRecorder.pause();
The MediaRecorder class does not have a pause() function, so this is obvious that there is a custom MediaRecorder class on this specific device. This is not something unusual, as the only thing required from the OEMs is to pass the "android compatability tests" on the device; there is no restriction on adding functionality.
Is it possible to take the input stream of the second video (while
recording it), and directly append this data to my first video?
I am not sure if you can do this, because the video stream is encoded data (codec header, key frames, and so on), and just combining 2 streams into 1 file will not produce a valid video file in my opinion.
Basically what you can do:
get raw data images from camera preview surface (see Camera.setPreviewCallback())
use a android.media.MediaCodec to encode the video
and then use an OutputFilStream to write to the file.
This will give you the flexability you want, as in this case you in you app decide which frames get into encoder, and which do not.
However, it maybe an overkill for your specific project, as well as some performance issues may rise.
PS. Oh, an by the way, try taking a look at the MediaMuxer - maybe it can help you too. developer.android.com/reference/android/media/MediaMuxer.html