您的位置:首页 > 移动开发 > Android开发

Android视频录制

2016-08-26 00:57 239 查看
今天呢介绍一个简单的预览拍摄例子,也是项目中用到的,在Android 4.4以上的手机都是可以支持的,并且支持切换前后置摄像头,开关闪光灯,自动对焦。

下面正式开始:

1.首先我们自定义一个控件,它继承于LinearLayout:

public class RecorderView extends LinearLayout implements MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener {
/*这里是代码*/
}


实现上面几个接口要重写以下几个方法,

@Override
public void onInfo(MediaRecorder mr, int what, int extra) {
try {

} catch (Exception e) {

}
}
@Override
public void onError(MediaRecorder mr, int what, int extra) {
try {

if (mr != null)
mr.reset();
} catch (Exception e) {

}
}


上面两个方法一个是视频录制时得到的信息函数,一个是录制过程中出现error时的回调函数,具体处理也很简单直接reset掉就可以了

下面来就是预览控件了

private SurfaceView surfaceView;
private SurfaceHolder surfaceHoler;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RecorderView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
this.context = context;
init();
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RecorderView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
}
private void init() {        LayoutInflater.from(context).inflate(R.layout.ui_recorder, this);
surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
surfaceHoler = surfaceView.getHolder();
surfaceHoler.addCallback(new VideoCallBack());        surfaceHoler.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceView.setFocusable(true);
surfaceHoler.setKeepScreenOn(true);
}


这个SurfaceView就是我们需要的,里面获得的suerfaceHolder就是用来预览拍摄视频,

那么怎么把Camera捕捉到的画面放到surfaceView里面去呢,对了就是这个addCallback方法:

class VideoCallBack implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder holder) {
switchCamera(false);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
startPreView();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder{
freeCameraResource();
}
}


里面重写了三方方法,对应着调用他们应该打开Camera,设置Camera参数,和释放Camera,很好理解

//选择打开前置还是后置摄像头
@TargetApi(Build
4000
.VERSION_CODES.GINGERBREAD)
public void switchCamera(boolean isFroCam) {
freeCameraResource();
try {
if (!isFroCam) {
camera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
} else {
camera = Camera.open(CameraInfo.CAMERA_FACING_FRONT);
isFrontCamera = true;
}
} catch (Exception e) {
e.printStackTrace();
}
}


//设置camera参数,这里无论是前置还是后置摄像头都要转90度
public void startPreView(){
camera.stopPreview();
if (camera == null)
return;
try {
camera.setDisplayOrientation(90);
cameraParameters = camera.getParameters();
cameraParameters.setPreviewSize(1280, 720);
camera.setPreviewDisplay(surfaceHoler);
getAutoFocus();
camera.setParameters(cameraParameters);
camera.setPreviewDisplay(surfaceHoler);
camera.startPreview();
camera.unlock();
} catch (IOException e) {
e.printStackTrace();
}
}


突然间我们发现一个函数叫做getAutoFocus,干嘛的?看名字就明白了是用来自动对焦的,这种方法在4.4到6.0上的手机都是有效的

public void getAutoFocus() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) {
List<String> focusModes = cameraParameters.getSupportedFocusModes();
if (focusModes != null) {
if (((Build.MODEL.startsWith("GT-I950"))
|| (Build.MODEL.endsWith("SCH-I959")) || (Build.MODEL.endsWith("MEIZU MX3")))&& focusModes                     .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
cameraParameters.setFocusMode
(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else if (focusModes              .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
cameraParameters                            .setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
}
}
}


然后这个你用完了记得一定要释放camera也就是freeCameraResource

public void freeCameraResource() {
if (null != camera) {
camera.setPreviewCallback(null);
camera.stopPreview();
camera.lock();
camera.release();
camera = null;
}
}


这样一个简单的视频预览拍摄页面就完成了。

下面这个是打开和关闭闪光灯的方法

public void openflashlight() {
if (camera == null)
return;
camera.lock();
try {
if (!isFlashOn) {
isFlashOn = true;              cameraParameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
} else {                cameraParameters.setFlashMode(Parameters.FLASH_MODE_OFF);
isFlashOn = false;
}
camera.setParameters(cameraParameters);
} catch (Exception e) {
return;
}
camera.unlock();
}


没什么难的,看一下就明白了。

下面就是录制过程了,不多说了,直接上代码,里面设置了一些参数看名字就能猜出来个八九不离十了,

public void startRecord() {
if (isRecording)
return;
createRecordDir();
initRecord(isFrontCamera);
prepareRecord();
}


//建立一个文件夹,并给拍摄的视频起个名字
private void createRecordDir() {
File sampleDir = new File(Environment.getExternalStorageDirectory()
+ File.separator + "You_video/");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
try {
startTime = String.valueOf(System.currentTimeMillis());
fileName = "you_video_name" + startTime + ".mp4";
vecordFile = new File(sampleDir.toString(), fileName);
} catch (Exception e) {
e.printStackTrace();
}
}


//设置录制视频的各种参数,在这里前后摄像头录制时设置的旋转角度是不
//一样的
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
private void initRecord(boolean isFrontCamera) {
mediaRecorder = new MediaRecorder();
mediaRecorder.reset();
if (camera != null)
mediaRecorder.setCamera(camera);
mediaRecorder.setOnInfoListener(this);
mediaRecorder.setOnErrorListener(this);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
try {
CamcorderProfile camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
mediaRecorder.setProfile(camcorderProfile);
} catch (RuntimeException re) {
try {
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
} catch (Exception e) {

}
}
try {
mediaRecorder.setVideoSize(1280, 720);
} catch (Exception e) {

}
mediaRecorder.setVideoEncodingBitRate(2 * 1024 * 1024);
if (!isFrontCamera) {
mediaRecorder.setOrientationHint(90);
} else {
mediaRecorder.setOrientationHint(270);
}
mediaRecorder.setMaxDuration(recordMaxTime * 1000);
mediaRecorder.setOutputFile(vecordFile.getAbsolutePath());
mediaRecorder.setPreviewDisplay(surfaceHoler.getSurface());
}


//真正的开始录制是在这里
private void prepareRecord() {
try {
mediaRecorder.prepare();
mediaRecorder.start();
} catch (IOException e) {
e.printStackTrace();
} catch (RuntimeException re) {
return;
}
}


如果录制视频不满意则调用这个函数

public void cancelRecord(boolean cancel) {
surfaceView.setVisibility(View.VISIBLE);
if (!isRecording)
return;
isRecording = false;
stopRecord();
releaseRecord();
freeCameraResource();
if (vecordFile.exists())
vecordFile.delete();
}


private void stopRecord() {
if (mediaRecorder != null) {
mediaRecorder.setOnErrorListener(null);
mediaRecorder.setPreviewDisplay(null);
try {
mediaRecorder.stop();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (RuntimeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}


public void releaseRecord() {
if (mediaRecorder != null) {
mediaRecorder.setOnErrorListener(null);
try {
mediaRecorder.release();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
mediaRecorder = null;
}


如果ok拍摄的视频是合格的那么调用下面这个函数

private void completeRecord(PlayVideoListener playVideoListener) {
if (mediaRecorder != null) {
mediaRecorder.setOnErrorListener(null);
mediaRecorder.setPreviewDisplay(null);
try {
mediaRecorder.stop();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (RuntimeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}          playVideoListener.callBackToPlayVideo(vecordFile.getAbsolutePath(), startTime, fileName);
}
}


接口

public interface PlayVideoListener {
void callBackToPlayVideo(String videoPath,String startTime,String fileName);
}


在你的Activity或者fragment中implement这个接口,就可以实现对拍好的视频进行回调方法的处理。

OK,简单的视频拍摄就是这些,后面会把Demo地址更新上来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 摄像头 视频