Android录制视频 图片看不了?点击切换HTTP 返回上层
视频录制也可以通过 MediaRecorder 类完成,其步骤与音频录制基本相同,只是添加了一些对视频进行处理的操作。
视频录制的基本步骤如下:
1) 调用Camera.open()方法打开摄像头。
2) 调用 Camera.setPreviewDisplay() 连接预览窗口
以便将从摄像头获取的图像放置到预览窗口中显示出来。
3) 调用 Camera.startPreview()启动预览
显示摄像头拍摄到的图像。
4) 使用 MediaRecorder 进行视频录制。
1.使用 Camera.unlock() 方法解锁摄像头,以使 MediaRecorder 获得对摄像头的使用权。
2.配置 MediaRecorder。
1)建立 MediaRecorder 类的对象,并设置音频源和视频源:
CamcorderProfile 为预先定义好的一组视频录制相关配置信息。
Android SDK 共定义了 14 种 CamcorderProfile 配置,如 CamcorderProfile. QUALITY_HIGH、CamcorderProfile. QUALITY_LOW、CamcorderProfile. QUALITY_TIME_LAPSE_1080P 等。其中,QUALITY_LOW 和 QUALITY_HIGH 两种配置是所有的摄像头都支持的,其他配置则根据硬件性能决定。
每一种配置都涉及文件输出格式、视频编码格式、视频比特率、视频帧率、视频的高和宽、音频编码格式、音频的比特率、音频采样率和音频录制的通道数几个方面。通过使用这些预定义配置能够降低代码复杂度,提高编码效率。
3)设置录制的视频文件的保存位置及文件名:
4)使用 MediaRecorder.setPreviewDisplay() 方法指定 MediaRecorder 的视频预览窗口。
需要注意的是,以上配置过程必须按照顺序进行,否则会发生错误。
3.将录像器置于准备状态:
4.启动录像器:
5.进行视频录制:
5) 视频录制完成后,可使用以下方法停止视频录制。
1.停止录像器:
2.重置录像器的相关配置:
3.释放录像器对象:
4.调用 Camera.lock() 方法锁定摄像头。从 Android N 开始,该调用也不再必需,除非 MediaRecorder.prepare() 方法失败。
6) 调用Camera.stopPreview()方法停止预览。
7) 调用Camera.release()方法释放摄像头 。
另外,在 Android N 系统下,Camera.unlock() 方法和 Camera.lock() 方法可由 Android 框架来完成。
实例 VideoRecorderDemo 演示了使用 MediaRecorder 进行视频录制的过程,该实例的运行效果如图 1 所示。

图 1 VideoRecorderDemo
实例 VideoRecorderDemo 使用的布局文件 main.xml 的内容如下:
其对应的资源文件 strings.xml 的内容如下:
由于实例 VideoRecorderDemo 中涉及音频录制、使用摄像头、向 SD 卡写文件等操作,因此需要在该工程的 AndroidManifest.xml 文件中声明相应权限。该文件内容如下:
实例 VideoRecorderDemo 的主 Activity 为 VideoRecorderDemoActivity,其代码如下:
该实例中,在对 MediaRecorder 进行设置时,没有使用:
视频录制的基本步骤如下:
1) 调用Camera.open()方法打开摄像头。
2) 调用 Camera.setPreviewDisplay() 连接预览窗口
以便将从摄像头获取的图像放置到预览窗口中显示出来。
3) 调用 Camera.startPreview()启动预览
显示摄像头拍摄到的图像。
4) 使用 MediaRecorder 进行视频录制。
1.使用 Camera.unlock() 方法解锁摄像头,以使 MediaRecorder 获得对摄像头的使用权。
2.配置 MediaRecorder。
1)建立 MediaRecorder 类的对象,并设置音频源和视频源:
MediaRecorder recorder=new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
其中,MediaRecorder.setProfile() 方法为 Android 2.2(API Level 8)之后 MediaRecorder 类新提供的方法,通过 CamcorderProfile 对象可用于对 MediaRecorder 进行相关设置。CamcorderProfile 为预先定义好的一组视频录制相关配置信息。
Android SDK 共定义了 14 种 CamcorderProfile 配置,如 CamcorderProfile. QUALITY_HIGH、CamcorderProfile. QUALITY_LOW、CamcorderProfile. QUALITY_TIME_LAPSE_1080P 等。其中,QUALITY_LOW 和 QUALITY_HIGH 两种配置是所有的摄像头都支持的,其他配置则根据硬件性能决定。
每一种配置都涉及文件输出格式、视频编码格式、视频比特率、视频帧率、视频的高和宽、音频编码格式、音频的比特率、音频采样率和音频录制的通道数几个方面。通过使用这些预定义配置能够降低代码复杂度,提高编码效率。
3)设置录制的视频文件的保存位置及文件名:
MediaRecorder.setOutputFile(PATH_NAME);
4)使用 MediaRecorder.setPreviewDisplay() 方法指定 MediaRecorder 的视频预览窗口。
需要注意的是,以上配置过程必须按照顺序进行,否则会发生错误。
3.将录像器置于准备状态:
MediaRecorder.prepare();
4.启动录像器:
MediaRecorder.start();
5.进行视频录制:
5) 视频录制完成后,可使用以下方法停止视频录制。
1.停止录像器:
MediaRecorder.stop();
2.重置录像器的相关配置:
MediaRecorder.reset()
3.释放录像器对象:
MediaRecorder.release();
4.调用 Camera.lock() 方法锁定摄像头。从 Android N 开始,该调用也不再必需,除非 MediaRecorder.prepare() 方法失败。
6) 调用Camera.stopPreview()方法停止预览。
7) 调用Camera.release()方法释放摄像头 。
另外,在 Android N 系统下,Camera.unlock() 方法和 Camera.lock() 方法可由 Android 框架来完成。
实例 VideoRecorderDemo 演示了使用 MediaRecorder 进行视频录制的过程,该实例的运行效果如图 1 所示。
图 1 VideoRecorderDemo
实例 VideoRecorderDemo 使用的布局文件 main.xml 的内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" > <TextView android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:text= "@string/hello" /> <SurfaceView android:id= "@+id/surfaceView1" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:layout_weight= "0.58" /> <LinearLayout android:id= "@+id/linearLayout1" android:layout_width= "match_parent" android:layout_height= "wrap_content" android:gravity= "center" > <Button android:id= "@+id/button1" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "@string/opBtn" /> <Button android:id= "@+id/button2" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "@string/play" /> <Button android:id= "@+id/button3" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "@string/cloBtn" /> </LinearLayout> </LinearLayout> |
1 2 3 4 5 6 7 | <resources> <string name = "hello" >使用MediaRecorder进行视频录制实例</string> <string name = "app_name" >VideoRecorder</string> <string name = "opBtn" >打开摄像头</string> <string name = "play" >录制</string> <string name = "cloBtn" >关闭摄像头</string> </resources> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?xml version= "1.0" encoding= "utf-8" ?> <manifest xmlns:android= "http://schemas.android.com/apk/res/android" package= "introduction.android.mycamerademo" android:versionCode= "1" android:versionName= "1.0" > <uses-sdk android:minSdkVersion= "14" /> <uses-feature android: name = "android.hardware.camera.autofocus" /> <uses-feature android: name = "android.permission.CAMERA" /> <uses-permission android: name = "android.permission.CAMERA" /> <uses-permission android: name = "android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:allowBackup= "true" android:icon= "@mipmap/ic_launcher" android:label= "@string/app_name" android:roundIcon= "@mipmap/ic_launcher_round" android:supportsRtl= "true" android:theme= "@style/AppTheme" > <activity android: name = ".MainActivity" > <intent-filter> < action android: name = "android.intent.action.MAIN" /> <category android: name = "android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | package introduction.android.mycamerademo; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PixelFormat; import android.hardware.Camera; import android.hardware.Camera.Parameters; import android.hardware.Camera.PictureCallback; import android.media.MediaRecorder; import android.os.Bundle; import android.util.Log; import android. view .SurfaceHolder; import android. view .SurfaceView; import android. view . View ; import android. view . View .OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private Button opbtn; private Button playbtn; private Button clobtn; private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; private Camera camera; private MediaRecorder videoRecorder; private String myVideofilepath = "sdcard/myvideo.3gp" ; /** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); opbtn = (Button) this.findViewById(R.id.button1); playbtn = (Button) this.findViewById(R.id.button2); clobtn = (Button) this.findViewById(R.id.button3); videoRecorder = new MediaRecorder(); surfaceView = (SurfaceView) this.findViewById(R.id.surfaceView1); surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub Log.i( "camera" , "surface destroyed." ); surfaceHolder = null ; stopRecording(); releaseCamera(); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub Log.i( "camera" , "surface destroyed" ); surfaceHolder = holder; } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub Log.i( "camera" , "surface changed." ); surfaceHolder = holder; } }); opbtn.setOnClickListener(new OnClickListener() { @Override public void onClick( View argO) { // TODO Auto-generated method stub openCamera(); } }); playbtn.setOnClickListener(new OnClickListener() { @Override public void onClick( View v) { // TODO Auto-generated method stub benginRecording(); } }); clobtn.setOnClickListener(new OnClickListener() { @Override public void onClick( View v) { // TODO Auto-generated method stub stopRecording(); } }); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); stopRecording(); releaseCamera(); } protected void stopRecording() { // TODO Auto-generated method stub Log.i( "videoRecorder" , "stopRecording..." ); if (videoRecorder != null ) { videoRecorder.stop(); videoRecorder.reset(); videoRecorder.release(); videoRecorder = null ; camera.lock(); } } private void releaseCamera() { if (camera != null ) { camera.release(); camera = null ; } } protected void benginRecording() { Log.i( "videoRecorder" , "beginRecording" ); //给摄像头解锁 camera.unlock(); //MediaRecorder获取到摄像头的访问权 videoRecorder.setCamera(camera); //设置视频录制过程中所录制的音频来自手机的麦克风 videoRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); //设置视频源为摄像头 videoRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); //设置视频录制的输出文件为3gp文件 videoRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //设置音频编码方式为AAC videoRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); //设置录制的视频编码为H.264 videoRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); videoRecorder.setVideoSize(176, 144); videoRecorder.setVideoFrameRate(20); if (!checkSDCard()) { Log.e( "videoRecorder" , "未找到SD卡!" ); return ; } videoRecorder.setOutputFile(myVideofilepath); videoRecorder.setPreviewDisplay(surfaceHolder.getSurface()); try { videoRecorder. prepare (); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } videoRecorder.start(); } private void openCamera() { // TODO Auto-generated method stub Log.i( "videoRecorder" , "openCamera." ); try { camera = Camera. open (); // attempt to get a Camera instance } catch (Exception e) { // Camera is not available ( in use or does not exist) Log.e( "camera" , "open camera error!" ); e.printStackTrace(); return ; } try { camera.setPreviewDisplay(surfaceHolder); } catch (IOException e) { // TODO Auto-generated catch block Log.e( "camera" , "preview failed." ); e.printStackTrace(); } camera.startPreview(); } private boolean checkSDCard() { // 判断SD存储卡是否存在 if (android.os.Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED)) { return true ; } else { return false ; } } } |
videoRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
而是使用以下代码对 MediaRecorder 进行设置:1 2 3 4 5 6 7 8 9 10 | //设置视频录制的输出文件为3gp文件 videoRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //设置音频编码方式为AAC videoRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); //设置录制的视频编码为H.264 videoRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); //设置视频录制的分辨率,必须放在设置编码和格式的后面,否则报错 videoRecorder.setVideoSize(176, 144); //设置录制的视频的视频帧率,必须放在设置编码和格式的后面,否则报错 videoRecorder.setVideoFrameRate(20); |