我们一般直接从摄像头和麦克风取数据,经过编码,保存为文件。android的视频录制需要使用到MediaRecorder,MediaRecorder除了可以用于录制音频,还可用于录制视频。
效果图如下图所示:
一个为录制过程中,可以看到屏幕上方的录制时间显示,后一个为停止录制视频。
然后录制好的视频可以在手机的SD卡中找到,如下图所示:
视频录制步骤:
1) 调用MediaRecorder 对象的setVideoEncoder()、setVideoEncodingBitRate(intbitRate)、setVideoFrameRate设置所录制的视频的编码格式、编码位率、每秒多少帧等,这些参数将可以控制所录制的视频的品质、文件的大小。一般来说,视频品质越好,视频文件越大。
2) 调用 MediaRecorder的setPreviewDisplay(Surfacesv)方法设置使用哪个SurfaceView来显示视频预览。
实例使用MediaRecorder录制视频:
import android.annotation.SuppressLint; import android.app.Activity; import android.graphics.PixelFormat; import android.hardware.Camera; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.view.*; import android.view.SurfaceHolder.Callback; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import java.io.File; import java.text.SimpleDateFormat; import java.util.Calendar; @SuppressLint("SimpleDateFormat") public class MyActivity extends Activity implements Callback { private SurfaceView mSurfaceview; private Button mBtnStartStop;// 开始停止录制按键 private boolean mStartedFlg = false; private MediaRecorder mRecorder;// 录制视频的类 private SurfaceHolder mSurfaceHolder;// 显示视频 private Camera camera; private TextView timeView;// 在屏幕顶部显示录制时间 private int time = 0; @SuppressLint("HandlerLeak") private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case 1:// 开始录制 timeView.setText(time + " s"); break; case 2:// 录制8s结束 mRecorder.stop(); mRecorder.reset(); // You can reuse the object by mBtnStartStop.setText("Start"); mStartedFlg = false; time = 0; timeView.setText(time + " s"); break; case 3:// 体检结束 time = 0; timeView.setText(time + " s"); break; } } ; }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题栏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏 getWindow().setFormat(PixelFormat.TRANSLUCENT); // 选择支持半透明模式,在有surfaceview的activity中使用。 setContentView(R.layout.main);// 加载布局 timeView = (TextView) findViewById(R.id.time); mSurfaceview = (SurfaceView) findViewById(R.id.surfaceview); mBtnStartStop = (Button) findViewById(R.id.btn); mBtnStartStop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if (!mStartedFlg) { // 开始 if (mRecorder == null) { mRecorder = new MediaRecorder(); // 创建mediarecorder的对象 } try { camera.unlock(); mRecorder.setCamera(camera); mRecorder .setAudioSource(MediaRecorder.AudioSource.CAMCORDER);// 这两项需要放在setOutputFormat之前 mRecorder .setVideoSource(MediaRecorder.VideoSource.CAMERA);// 设置录制视频源为Camera(相机) mRecorder.setOrientationHint(90); // Set output file format mRecorder .setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 设置录制完成后视频的封装格式THREE_GPP为3gp.MPEG_4为mp4 // 这两项需要放在setOutputFormat之后 mRecorder .setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mRecorder .setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);// 设置录制的视频编码h263 mRecorder.setVideoSize(800, 480);// 设置视频录制的分辨率。必须放在设置编码和格式的后面,否则报错 mRecorder.setVideoFrameRate(30);// 设置录制的视频帧率。必须放在设置编码和格式的后面,否则报错 mRecorder.setMaxDuration(8000);// 设置最大的录制时间 mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); // Set output file path String path = getSDPath(); if (path != null) { File dir = new File(path + "/recordtest"); if (!dir.exists()) { dir.mkdir(); } path = dir + "/" + getDate() + ".mp4"; Toast.makeText(MyActivity.this, path, Toast.LENGTH_LONG).show(); mRecorder.setOutputFile(path); mRecorder.prepare();// 准备录制 mRecorder.start(); // 开始录制 new Thread(new Runnable() { @Override public void run() { while (time < 8) { try { time++; Thread.sleep(1000); handler.sendEmptyMessage(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } handler.sendEmptyMessage(2); } }).start(); mStartedFlg = true; mBtnStartStop.setText("Stop"); } } catch (Exception e) { e.printStackTrace(); } } else { // stop if (mStartedFlg) { try { mRecorder.stop(); mRecorder.reset(); // You can reuse the object by // going back to // setAudioSource() step mBtnStartStop.setText("Start"); handler.sendEmptyMessageDelayed(3, 1000); } catch (Exception e) { e.printStackTrace(); } } mStartedFlg = false; // Set button status flag } } }); SurfaceHolder holder = mSurfaceview.getHolder();// 取得holder holder.addCallback(this); // holder加入回调接口 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// setType必须设置,要不出错. } /** * 使用时间对录像起名 * * @return */ public static String getDate() { Calendar ca = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss"); String date = sdf.format(ca.getTimeInMillis()); return date; } /** * 获取SD path * * @return */ public String getSDPath() { File sdDir = null; boolean sdCardExist = Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED); // 判断sd卡是否存在 if (sdCardExist) { sdDir = Environment.getExternalStorageDirectory();// 获取跟目录 // Toast.makeText(this,sdDir.toString(),Toast.LENGTH_LONG).show(); return sdDir.toString(); } else { Toast.makeText(this, "没有SD卡", Toast.LENGTH_LONG).show(); } return null; } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { camera = Camera.open(); // 获取Camera实例 try { camera.setPreviewDisplay(holder); mSurfaceview.setLayoutParams(new LinearLayout.LayoutParams(width, height)); } catch (Exception e) { // 如果出现异常,则释放Camera对象 camera.release(); } camera.setDisplayOrientation(90);// 设置预览视频时时竖屏 // 启动预览功能 camera.startPreview(); // 将holder,这个holder为开始在onCreate里面取得的holder,将它赋给mSurfaceHolder mSurfaceHolder = holder; } @Override public void surfaceCreated(SurfaceHolder holder) { // 将holder,这个holder为开始在onCreate里面取得的holder,将它赋给mSurfaceHolder mSurfaceHolder = holder; } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub // surfaceDestroyed的时候同时对象设置为null mSurfaceview = null; mSurfaceHolder = null; if (mRecorder != null) { mRecorder.release(); // Now the object cannot be reused mRecorder = null; } if (camera != null) { camera.release(); camera = null; } } }XML的布局文件为:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@android:color/white"> <TextView android:id="@+id/time" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:text="0 s" android:textColor="@android:color/background_dark"/> <SurfaceView android:id="@+id/surfaceview" android:layout_width="fill_parent" android:layout_height="0dip" android:layout_weight="1" /> <Button android:id="@+id/btn" android:layout_width="101dp" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_weight="0.02" android:text="Start" tools:context=".MainActivity" /> </LinearLayout>
原文地址:http://blog.csdn.net/a296777513/article/details/43488415