我正在尝试使用计时器实现录像机。
当我开始CountDownTimer
并且我将最长时间限制为30秒时,我的录音开始了。因此,在30秒后将调用onFinish()
方法。在onFinish()
方法中,我停止了视频录制。所以理想的录制视频应该是30秒。 但是现在当我打开录制的视频时,它不是30秒。这是28秒。计时器和录音机相差2秒。 那么请你帮我解决这个问题吗?
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import butterknife.BindView;
import butterknife.ButterKnife;
public class VideoRecordActivity extends AppCompatActivity implements View.OnClickListener {
private Camera mCamera;
private CameraPreview mPreview;
private MediaRecorder mediaRecorder;
@BindView(R.id.ivRecord)
ImageView ivRecord;
@BindView(R.id.ivChangeCamera)
ImageView ivChangeCamera;
private Context myContext;
private LinearLayout cameraPreview;
private boolean cameraFront = false;
private CountDownTimer mCountDownTimer;
private TextView tvTimer;
private SeekBar mSeekBar;
private boolean isStarted;
@BindView(R.id.tvTotalTimer)
TextView tvTotalTimer;
public static final int VIDEO_TRIMMER_REQUEST_CODE = 1010;
private Random random;
private String randomVideoFileName = "ABCDEFGHIJKLMNOP";
private String videoRecordingPath;
int AUDIO_RECORD_LIMIT_MILLI_SECOND = 30000;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_record);
ButterKnife.bind(this);
random = new Random();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
myContext = this;
initialize();
}
public void onResume() {
super.onResume();
if (!hasCamera(myContext)) {
Toast toast = Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG);
toast.show();
finish();
}
if (mCamera == null) {
// if the front facing camera does not exist
if (findFrontFacingCamera() < 0) {
Toast.makeText(this, "No front facing camera found.", Toast.LENGTH_LONG).show();
ivChangeCamera.setVisibility(View.GONE);
}
mCamera = Camera.open(findBackFacingCamera());
setCameraOritentation(mCamera);
mPreview.refreshCamera(mCamera);
}
}
@Override
protected void onPause() {
super.onPause();
// when on Pause, release camera in order to be used from other
// applications
releaseCamera();
}
private int findFrontFacingCamera() {
int cameraId = -1;
// Search for the front facing camera
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
cameraId = i;
cameraFront = true;
break;
}
}
return cameraId;
}
private int findBackFacingCamera() {
int cameraId = -1;
// Search for the back facing camera
// get the number of cameras
int numberOfCameras = Camera.getNumberOfCameras();
// for every camera check
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
cameraFront = false;
break;
}
}
return cameraId;
}
public void initialize() {
cameraPreview = (LinearLayout) findViewById(R.id.camera_preview);
mPreview = new CameraPreview(myContext, mCamera);
cameraPreview.addView(mPreview);
ivRecord.setOnClickListener(this);
ivChangeCamera.setOnClickListener(this);
tvTimer = (TextView) findViewById(R.id.tvTimer);
tvTotalTimer.setText("" + CommonUtilities.milliSecondsToTimer(AUDIO_RECORD_LIMIT_MILLI_SECOND - 1000));
mSeekBar = (SeekBar) findViewById(R.id.seekBar);
mSeekBar.setMax(30);
mSeekBar.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return true;
}
});
mCountDownTimer = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
if (!isStarted) {
isStarted = true;
}
int timeRemaining = (int) ((AUDIO_RECORD_LIMIT_MILLI_SECOND / 1000) - (millisUntilFinished / 1000));
mSeekBar.setProgress(timeRemaining);
tvTimer.setText("" + CommonUtilities.milliSecondsToTimer(AUDIO_RECORD_LIMIT_MILLI_SECOND - millisUntilFinished));
}
public void onFinish() {
tvTimer.setText("" + CommonUtilities.milliSecondsToTimer(AUDIO_RECORD_LIMIT_MILLI_SECOND - 1000));
mSeekBar.setProgress(AUDIO_RECORD_LIMIT_MILLI_SECOND / 1000);
onRecordingStopped(); // release the MediaRecorder object
}
};
}
public void chooseCamera() {
// if the camera preview is the front
if (cameraFront) {
int cameraId = findBackFacingCamera();
if (cameraId >= 0) {
// open the backFacingCamera
// set a picture callback
// refresh the preview
mCamera = Camera.open(cameraId);
setCameraOritentation(mCamera);
mPreview.refreshCamera(mCamera);
}
} else {
int cameraId = findFrontFacingCamera();
if (cameraId >= 0) {
// open the backFacingCamera
// set a picture callback
// refresh the preview
mCamera = Camera.open(cameraId);
setCameraOritentation(mCamera);
mPreview.refreshCamera(mCamera);
}
}
}
private boolean hasCamera(Context context) {
// check if the device has camera
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
boolean recording = false;
private void onRecordingStopped() {
if (mediaRecorder != null) {
isStarted = false;
ivChangeCamera.setVisibility(View.VISIBLE);
ivRecord.clearAnimation();
mediaRecorder.stop();
mediaRecorder.reset(); // clear recorder configuration
mediaRecorder.release(); // release the recorder object
mediaRecorder = null;
mCamera.lock(); // lock camera for later use
Toast.makeText(VideoRecordActivity.this, "Video captured!", Toast.LENGTH_LONG).show();
recording = false;
Intent intent = new Intent(VideoRecordActivity.this, TrimmerActivity.class);
intent.putExtra("path", videoRecordingPath);
startActivityForResult(intent,VIDEO_TRIMMER_REQUEST_CODE);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == VIDEO_TRIMMER_REQUEST_CODE && resultCode == RESULT_OK) {
setResult(RESULT_OK,data);
finish();
}
}
private boolean prepareMediaRecorder() {
mediaRecorder = new MediaRecorder();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (!cameraFront) {
if (display.getRotation() == Surface.ROTATION_0) {
mediaRecorder.setOrientationHint(90);
}
if (display.getRotation() == Surface.ROTATION_270) {
mediaRecorder.setOrientationHint(180);
}
} else {
if(display.getRotation() == Surface.ROTATION_0)
{
mediaRecorder.setOrientationHint(270);
}
}
mCamera.unlock();
mediaRecorder.setCamera(mCamera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
//mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_720P));
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_480P));
mediaRecorder.setOutputFile(videoRecordingPath);
//mediaRecorder.setMaxFileSize(10000000); // Set max file size 50M
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
onRecordingStopped();
return false;
} catch (IOException e) {
onRecordingStopped();
return false;
}
return true;
}
private void releaseCamera() {
// stop and release camera
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
private void setCameraOritentation(Camera mCamera) {
Camera.Parameters parameters = mCamera.getParameters();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
mCamera.setDisplayOrientation(90);
}
if (display.getRotation() == Surface.ROTATION_270) {
mCamera.setDisplayOrientation(180);
}
mCamera.setParameters(parameters);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ivRecord:
if (recording) {
// stop recording and release camera
mCountDownTimer.cancel();
onRecordingStopped(); // release the MediaRecorder object
} else {
if (!new File(LOCAL_VIDEO_STORAGE_DIRECTORY_PATH).exists())
new File(LOCAL_VIDEO_STORAGE_DIRECTORY_PATH).mkdirs();
videoRecordingPath = LOCAL_VIDEO_STORAGE_DIRECTORY_PATH +
CreateRandomAudioFileName(5) + "VideoRecording.mp4";
if (!prepareMediaRecorder()) {
Toast.makeText(VideoRecordActivity.this, "Fail in prepareMediaRecorder()!\n - Ended -", Toast.LENGTH_LONG).show();
finish();
}
try {
Animation rotation = AnimationUtils.loadAnimation(VideoRecordActivity.this, R.anim.rotateimage);
rotation.setFillAfter(true);
ivRecord.startAnimation(rotation);
ivChangeCamera.setVisibility(View.GONE);
mediaRecorder.start();
mCountDownTimer.start();
} catch (final Exception ex) {
// Log.i("---","Exception in thread");
}
/*// work on UiThread for better performance
runOnUiThread(new Runnable() {
public void run() {
// If there are stories, add them to the table
try {
Animation rotation = AnimationUtils.loadAnimation(VideoRecordActivity.this, R.anim.rotateimage);
rotation.setFillAfter(true);
ivRecord.startAnimation(rotation);
ivChangeCamera.setVisibility(View.GONE);
mCountDownTimer.start();
} catch (final Exception ex) {
// Log.i("---","Exception in thread");
}
}
});*/
recording = true;
}
break;
case R.id.ivChangeCamera:
if (!recording) {
int camerasNumber = Camera.getNumberOfCameras();
if (camerasNumber > 1) {
// release the old camera instance
// switch camera, from the front and the back and vice versa
releaseCamera();
chooseCamera();
} else {
Toast toast = Toast.makeText(myContext, "Sorry, your phone has only one camera!", Toast.LENGTH_LONG);
toast.show();
}
}
break;
}
}
public String CreateRandomAudioFileName(int string) {
StringBuilder stringBuilder = new StringBuilder(string);
int i = 0;
while (i < string) {
stringBuilder.append(randomVideoFileName.
charAt(random.nextInt(randomVideoFileName.length())));
i++;
}
return stringBuilder.toString();
}
}