android camera2 详解说明(二)
2 录制视频短片
MediaRecorder除了可用于录制音频之外,还可用于录制视频。使用MediaRecorder录制视频与录制音频的步骤基本相同。只是录制视频时不仅需要采集声音,还需要采集图像。为了让MediaRecorder录制时采集图像,应该在调用setAudioSource(int audio_source)方法时再调用setVideoSource(int video_source)方法来设置图像来源。
除此之外,还需要在调用setOutputFormat()方法设置输出文件格式之后执行如下步骤。
file:///C:\Users\sxs\AppData\Local\Temp\msohtmlclip1\01\clip_image002.png 调用MediaRecorder对象的setVideoEncoder()、setVideoEncodingBitRate(int bitRate)、setVideoFrameRate()方法设置所录制的视频编码格式、编码位率、每秒多少帧等,这些参数可以控制所录制的视频品质、文件大小。一般来说,视频品质越好,视频文件越大。
file:///C:\Users\sxs\AppData\Local\Temp\msohtmlclip1\01\clip_image004.png 调用MediaRecorder的setPreviewDisplay(Surface sv)方法设置使用哪个SurfaceView来显示视频预览。
剩下的代码则与录制音频的代码基本相同。
实例:录制生活短片
本实例示范了如何录制视频。该程序的界面中提供了两个按钮用于控制开始、结束录制;除此之外,程序界面中还提供了一个SurfaceView来显示视频预览。该程序的界面布局文件如下。
程序清单:codes\11\3\RecordVideo\app\src\main\res\layout\main.xml
<?xml version="1.0"encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
androidrientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 显示视频预览的SurfaceView -->
<SurfaceView
android:id="@+id/sView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
androidrientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true">
<ImageButton
android:id="@+id/record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/record"/>
<ImageButton
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/stop"/>
</LinearLayout>
</RelativeLayout>
提供了上面所示的界面布局文件之后,接下来就可以在程序中使用MediaRecorder来录制视频了。录制视频与录制音频的步骤基本相似,只是需要额外设置视频的图像来源、视频格式等。除此之外,还需要设置使用SurfaceView显示视频预览。录制视频的程序代码如下。
程序清单:codes\11\3\RecordVideo\app\src\main\java\org\crazyit\media\MainActivity.java
public class MainActivity extends Activity
implementsOnClickListener
{
// 程序中的两个按钮
ImageButtonrecord , stop;
// 系统的视频文件
FilevideoFile ;
MediaRecordermRecorder;
// 显示视频预览的SurfaceView
SurfaceView sView;
// 记录是否正在进行录制
privateboolean isRecording = false;
@Override
publicvoid onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取程序界面中的两个按钮
record= (ImageButton) findViewById(R.id.record);
stop= (ImageButton) findViewById(R.id.stop);
// 让stop按钮不可用
stop.setEnabled(false);
// 为两个按钮的单击事件绑定监听器
record.setOnClickListener(this);
stop.setOnClickListener(this);
// 获取程序界面中的SurfaceView
sView= (SurfaceView) this.findViewById(R.id.sView);
// 设置Surface不需要自己维护缓冲区
sView.getHolder().setType(SurfaceHolder
.SURFACE_TYPE_PUSH_BUFFERS);
// 设置分辨率
sView.getHolder().setFixedSize(320,280);
// 设置该组件让屏幕不会自动关闭
sView.getHolder().setKeepScreenOn(true);
}
@Override
publicvoid onClick(View source)
{
switch(source.getId())
{
//单击录制按钮
caseR.id.record:
if (!Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED))
{
Toast.makeText(MainActivity.this
, "SD卡不存在,请插入SD卡!"
,Toast.LENGTH_SHORT).show();
return;
}
try
{
// 创建保存录制视频的视频文件
videoFile = new File(Environment
.getExternalStorageDirectory()
.getCanonicalFile() +"/myvideo.mp4");
// 创建MediaRecorder对象
mRecorder = new MediaRecorder();
mRecorder.reset();
// 设置从麦克风采集声音
mRecorder.setAudioSource(MediaRecorder
.AudioSource.MIC);
// 设置从摄像头采集图像
mRecorder.setVideoSource(MediaRecorder
.VideoSource.CAMERA);
// 设置视频文件的输出格式
// 必须在设置声音编码格式、图像编码格式之前设置
mRecorder.setOutputFormat(MediaRecorder
.OutputFormat.MPEG_4);
// 设置声音编码格式
mRecorder.setAudioEncoder(MediaRecorder
.AudioEncoder.DEFAULT);
// 设置图像编码格式
mRecorder.setVideoEncoder(MediaRecorder
.VideoEncoder.MPEG_4_SP);
mRecorder.setVideoSize(320,280);
// 每秒 4帧
mRecorder.setVideoFrameRate(4);
mRecorder.setOutputFile(videoFile.getAbsolutePath());
// 指定使用SurfaceView来预览视频
mRecorder.setPreviewDisplay(sView
.getHolder().getSurface()); // ①
mRecorder.prepare();
// 开始录制
mRecorder.start();
System.out.println("---recording---");
// 让record按钮不可用
record.setEnabled(false);
// 让stop按钮可用
stop.setEnabled(true);
isRecording = true;
}
catch (Exception e)
{
e.printStackTrace();
}
break;
//单击停止按钮
caseR.id.stop:
// 如果正在进行录制
if (isRecording)
{
// 停止录制
mRecorder.stop();
// 释放资源
mRecorder.release();
mRecorder = null;
// 让record按钮可用
record.setEnabled(true);
// 让stop按钮不可用
stop.setEnabled(false);
}
break;
}
}
}
上面程序中的粗体字代码设置了视频所采集的图像来源,以及视频的压缩格式、视频分辨率等属性,程序的①号粗体字代码则用于设置使用指定SurfaceView显示指定视频预览。
运行该程序需要使用麦克风录制声音,需要使用摄像头采集图像,这些都需要授予相应的权限;不仅如此,由于录制视频时视频文件增大得较快,可能需要使用外部存储器,因此需要对应用程序授予相应的权限,也就是需要在AndroidManifest.xml文件中增加如下授权配置:
<!-- 授予该程序录制声音的权限 -->
<uses-permissionandroid:name="android.permission.RECORD_AUDIO"/>
<!-- 授予该程序使用摄像头的权限 -->
<uses-permissionandroid:name="android.permission.CAMERA"/>
<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 授予使用外部存储器的权限 -->
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
当在Genymotion模拟器上运行该程序时,由于Genymotion模拟器可以直接使用宿主电脑上的摄像头作为相机摄像头,因此在该模拟器上运行该程序可以看到如图3所示的界面。
<ignore_js_op>
图3 录制视频短片
本文摘自《疯狂Android讲义(第2版)》
<ignore_js_op>
Android学习