MediaRecorder类详解
手机一般都有麦克风和摄像头,而Android系统就可以利用这些硬件来录制音视频了。
为了增加对录制音视频的支持,Android系统提供了一个MediaRecorder的类。该类的使用也非常简单,下面让我们来了解一下这个类:
一、类结构:
java.lang.Object | |
? | android.media.MediaRecorder |
二、类概述:
用于录制音频和视频的一个类。
三、状态图:
<img src="http://www.2cto.com/uploadfile/Collfiles/20140815/2014081509185897.jpg" alt="mediarecZ喎�" http:="" www.2cto.com="" kf="" ware="" vc="" "="" target="_blank" class="keylink" style="border-width: 0px; padding: 0px 0px 4px; margin: 0px; list-style: none; height: 560px; width: 504.854px;">vcmRlcl9zdGF0ZV9kaWFncmFt">
说明:
与MediaPlayer类非常相似MediaRecorder也有它自己的状态图。下面是关于MediaRecorder的各个状态的介绍:
Initial:初始状态,当使用new()方法创建一个MediaRecorder对象或者调用了reset()方法时,该MediaRecorder对象处于Initial状态。在设定视频源或者音频源之后将转换为Initialized状态。另外,在除Released状态外的其它状态通过调用reset()方法都可以使MediaRecorder进入该状态。
Initialized:已初始化状态,可以通过在Initial状态调用setAudioSource()或setVideoSource()方法进入该状态。在这个状态可以通过setOutputFormat()方法设置输出格式,此时MediaRecorder转换为DataSourceConfigured状态。另外,通过reset()方法进入Initial状态。
DataSourceConfigured:数据源配置状态,这期间可以设定编码方式、输出文件、屏幕旋转、预览显示等等。可以在Initialized状态通过setOutputFormat()方法进入该状态。另外,可以通过reset()方法回到Initial状态,或者通过prepare()方法到达Prepared状态。
Prepared:就绪状态,在DataSourceConfigured状态通过prepare()方法进入该状态。在这个状态可以通过start()进入录制状态。另外,可以通过reset()方法回到Initialized状态。
Recording:录制状态,可以在Prepared状态通过调用start()方法进入该状态。另外,它可以通过stop()方法或reset()方法回到Initial状态。
Released:释放状态(官方文档给出的词叫做Idle state 空闲状态),可以通过在Initial状态调用release()方法来进入这个状态,这时将会释放所有和MediaRecorder对象绑定的资源。
Error:错误状态,当错误发生的时候进入这个状态,它可以通过reset()方法进入Initial状态。
提示:与MediaPlayer相似使用MediaRecorder录音录像时需要严格遵守状态图说明中的函数调用先后顺序,在不同的状态调用不同的函数,否则会出现异常。
下面一个实例描述了的创建过程:
MediaRecorder recorder=newMediaRecorder(); |
四、构造方法和公有方法
Public Constructors | |
MediaRecorder() Default constructor. |
Public Methods | |
final static int | getAudioSourceMax() 获取音频源的最大值。 |
int | getMaxAmplitude() 获取在前一次调用此方法之后录音中出现的最大振幅。 |
void | prepare() 准备录制。 |
void | release() 释放资源。 |
void | reset() 将MediaRecorder设为空闲状态,即Initial状态。 |
void | setAudioChannels(int numChannels) 设置录制的音频通道数。 |
void | setAudioEncoder(int audio_encoder) 设置所录制的声音的编码格式。 |
void | setAudioEncodingBitRate(int bitRate) 设置所录制的声音的编码位率。 |
void | setAudioSamplingRate(int samplingRate) 设置所录制的声音的采样率。 |
void | setAudioSource(int audio_source) 设置声音来源,一般传入 MediaRecorder. AudioSource.MIC参数指定录制来自麦克风的声音。 |
void | setCamera(Camera c) 设置一个摄像头用于录制。 |
void | setCaptureRate(double fps) 设置视频帧捕获率。 |
void | setLocation(float latitude, float longitude) 设置并存储在输出文件中的地理数据(经度和纬度)。 |
void | setMaxDuration(int max_duration_ms) 设置录制会话的最长持续时间(以ms为单位)。 |
void | setMaxFileSize(long max_filesize_bytes) 设置录制文件的最大文件大小。 |
void | setOnErrorListener(MediaRecorder.OnErrorListener l) 注册一个用于记录录制时出现的错误的监听器。 |
void | setOnInfoListener(MediaRecorder.OnInfoListener listener) 注册一个用于记录录制时出现的信息事件。 |
void | setOrientationHint(int degrees) 设置输出的视频播放的方向提示。 |
void | setOutputFile(FileDescriptor fd) 设置录制的音频文件的保存位置。 |
void | setOutputFile(String path) 设置录制的音频文件的保存位置。 |
void | setOutputFormat(int output_format) 设置所录制的音视频文件的格式。 |
void | setPreviewDisplay(Surface sv) 设置使用哪个SurfaceView来显示视频预览。 |
void | setProfile(CamcorderProfile profile) 指定CamcorderProfile对象。 |
void | setVideoEncoder(int video_encoder) 设置所录制视频的编码格式。 |
void | setVideoEncodingBitRate(int bitRate) 设置所录制视频的编码位率。 |
void | setVideoFrameRate(int rate) 设置录制视频的捕获帧速率。 |
void | setVideoSize(int width, int height) 设置要拍摄的宽度和视频的高度。 |
void | setVideoSource(int video_source) 设置用于录制的视频来源。 |
void | start() 开始录制。 |
void | stop() 停止录制。 |
五、应用实例
MediaRecorder除了可以用于录制音频,还可用于录制视频。关于MediaRecorder的详解大家可以参考《Android开发之MediaRecorder类详解》。使用MediaRecorder录制视频与录制音频的步骤基本相同。只是录制视频时不仅需要采集声音,还需要采集图像。为了让MediaRecorder录制时采集图像,应该在调用setAudioSource(int audio source)方法时再调用setVideoSource(int video source)方法来设置图像来源。
除此之外,还需在调用setOutputFormat()设置输出文件格式之后进行如下步骤:
1) 调用MediaRecorder 对象的setVideoEncoder()、setVideoEncodingBitRate(intbitRate)、setVideoFrameRate设置所录制的视频的编码格式、编码位率、每秒多少帧等,这些参数将可以控制所录制的视频的品质、文件的大小。一般来说,视频品质越好,视频文件越大。
2) 调用 MediaRecorder的setPreviewDisplay(Surfacesv)方法设置使用哪个SurfaceView来显示视频预览。
剩下的代码则与录制音频的代码基本相同:
实例使用MediaRecorder录制视频:
1.RecordVideo类:
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
|
package
com.jph.recordvideo;
import
java.io.File;
import
android.app.Activity;
import
android.content.pm.ActivityInfo;
import
android.graphics.PixelFormat;
import
android.media.MediaRecorder;
import
android.os.Bundle;
import
android.os.Environment;
import
android.view.SurfaceView;
import
android.view.View;
import
android.view.View.OnClickListener;
import
android.view.Window;
import
android.view.WindowManager;
import
android.widget.ImageButton;
import
android.widget.Toast;
/**
* Description:
* 使用MediaRecorder录制视频
* @author jph
* Date:2014.08.14
* <br>
*/
public
class
RecordVideo
extends
Activity
implements
OnClickListener
{
// 程序中的两个按钮
ImageButton record , stop;
// 系统的视频文件
File videoFile ;
MediaRecorder mRecorder;
// 显示视频预览的SurfaceView
SurfaceView sView;
// 记录是否正在进行录制
private
boolean
isRecording =
false
;
@Override
public
void
onCreate(Bundle savedInstanceState)
{
super
.onCreate(savedInstanceState);
// 去掉标题栏 ,必须放在setContentView之前
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
// 设置横屏显示
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// 设置全屏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 选择支持半透明模式,在有surfaceview的activity中使用。
getWindow().setFormat(PixelFormat.TRANSLUCENT);
// 获取程序界面中的两个按钮
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);
// 设置分辨率
sView.getHolder().setFixedSize(
1280
,
720
);
// 设置该组件让屏幕不会自动关闭
sView.getHolder().setKeepScreenOn(
true
);
}
@Override
public
void
onClick(View source)
{
switch
(source.getId())
{
// 单击录制按钮
case
R.id.record:
if
(!Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED))
{
Toast.makeText(RecordVideo.
this
,
"SD卡不存在,请插入SD卡!"
, Toast.LENGTH_SHORT).show();
return
;
}
try
{
// 创建保存录制视频的视频文件
videoFile =
new
File(Environment
.getExternalStorageDirectory()
.getCanonicalFile() +
"/testvideo.3gp"
);
// 创建MediaPlayer对象
mRecorder =
new
MediaRecorder();
mRecorder.reset();
// 设置从麦克风采集声音(或来自录像机的声音AudioSource.CAMCORDER)
mRecorder.setAudioSource(MediaRecorder
.AudioSource.MIC);
// 设置从摄像头采集图像
mRecorder.setVideoSource(MediaRecorder
.VideoSource.CAMERA);
// 设置视频文件的输出格式
// 必须在设置声音编码格式、图像编码格式之前设置
mRecorder.setOutputFormat(MediaRecorder
.OutputFormat.THREE_GPP);
// 设置声音编码的格式
mRecorder.setAudioEncoder(MediaRecorder
.AudioEncoder.AMR_NB);
// 设置图像编码的格式
mRecorder.setVideoEncoder(MediaRecorder
.VideoEncoder.H264);
mRecorder.setVideoSize(
1280
,
720
);
// 每秒 4帧
mRecorder.setVideoFrameRate(
20
);
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
;
// 单击停止按钮
case
R.id.stop:
// 如果正在进行录制
if
(isRecording)
{
// 停止录制
mRecorder.stop();
// 释放资源
mRecorder.release();
mRecorder =
null
;
// 让record按钮可用。
record.setEnabled(
true
);
// 让stop按钮不可用。
stop.setEnabled(
false
);
}
break
;
}
}
}
|
1
2
3
4
5
6
7
8
9
|
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<relativelayout xmlns:android=
"http://schemas.android.com/apk/res/android"
android:orientation=
"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 android:orientation=
"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=
"66dp"
android:layout_height=
"66dp"
android:scaletype=
"fitCenter"
android:src=
"@drawable/recored"
>
<imagebutton android:id=
"@+id/stop"
android:layout_width=
"66dp"
android:layout_height=
"66dp"
android:scaletype=
"fitCenter"
android:src=
"@drawable/stop"
>
</imagebutton></imagebutton></linearlayout>
</surfaceview></relativelayout>
|
3.为程序添加相应权限:
1
2
3
4
5
6
7
|
<!-- 授予该程序录制声音的权限 -->
<uses-permission android:name=
"android.permission.RECORD_AUDIO"
>
<!-- 授予该程序使用摄像头的权限 -->
<uses-permission android:name=
"android.permission.CAMERA"
>
<uses-permission android:name=
"android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
>
<!-- 授予使用外部存储器的权限 -->
<uses-permission android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
></uses-permission></uses-permission></uses-permission></uses-permission>
|
4.程序运行预览:
为了在 Android 应用中录制声音,Android提供了 MediaRecorder 类,关于MediaRecorder的详解大家可以参考《Android开发之MediaRecorder类详解》。
使用MediaRecorder录制声音的步骤:
1) 创建 MediaRecorder 对象。
2) 调用MediaRecorder对象的setAudioSource()方法设置声音来源,一般传入 MediaRecorder. AudioSource.MIC参数指定录制来自麦克风的声音。
3) 调用MediaRecorder对象的setOutputFormat()设置所录制的音频文件的格式。
4) 调用MediaRecorder 对象的setAudioEncoder()、setAudioEncodingBitRate(intbitRate)、 setAudioSamplingRate(int samplingRate)设置所录制的声音的编码格式、编码位率、采样率等, 这些参数将可以控制所录制的声音的品质、文件的大小。一般来说,声音品质越好,声音文件越大。
5) 调用MediaRecorder的setOutputFile(Stringpath)方法设置录制的音频文件的保存位置。
6) 调用MediaRecorder的prepare()方法准备录制。
7) 调用MediaRecorder对象的start()方法开始录制。
8) 录制完成,调用MediaRecorder对象的stop()方法停止录制,并调用release()方法释放资源。
提示:1.上面的步骤中第3和第4两个步骤千万不能搞反,否则程序将会抛出lllegalStateException 异常。
2. 设置声音编码格式要和声音的输出格式相对应,不然录制的音频文件不标准。如果编码格式和输出格式不对应,录制出的音频文件虽然可以播放,但是将多个这类音频文件合并之后,会出现只播放合并文件中的部分文件。
应用实例
使用MediaRecorder录制声音:
实例代码:
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
|
<span style=
"font-size:18px;"
>
package
com.jph.recordsound;
import
java.io.File;
import
org.crazyit.sound.R;
import
android.app.Activity;
import
android.media.MediaRecorder;
import
android.os.Bundle;
import
android.os.Environment;
import
android.view.View;
import
android.view.View.OnClickListener;
import
android.widget.ImageButton;
import
android.widget.Toast;
public
class
RecordSound
extends
Activity
implements
OnClickListener
{
// 定义界面上的两个按钮
ImageButton record, stop;
// 系统的音频文件
File soundFile;
MediaRecorder mRecorder;
@Override
public
void
onCreate(Bundle savedInstanceState)
{
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取程序界面中的两个按钮
record = (ImageButton) findViewById(R.id.record);
stop = (ImageButton) findViewById(R.id.stop);
// 为两个按钮的单击事件绑定监听器
record.setOnClickListener(
this
);
stop.setOnClickListener(
this
);
}
@Override
public
void
onDestroy()
{
if
(soundFile !=
null
&& soundFile.exists())
{
// 停止录音
mRecorder.stop();
// 释放资源
mRecorder.release();
mRecorder =
null
;
}
super
.onDestroy();
}
@Override
public
void
onClick(View source)
{
switch
(source.getId())
{
// 单击录音按钮
case
R.id.record:
if
(!Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED))
{
Toast.makeText(RecordSound.
this
,
"SD卡不存在,请插入SD卡!"
,
Toast.LENGTH_SHORT).show();
return
;
}
try
{
// 创建保存录音的音频文件
soundFile =
new
File(Environment
.getExternalStorageDirectory().getCanonicalFile()
+
"/sound.amr"
);
mRecorder =
new
MediaRecorder();
// 设置录音的声音来源
mRecorder.setAudioSource(MediaRecorder
.AudioSource.MIC);
// 设置录制的声音的输出格式(必须在设置声音编码格式之前设置)
mRecorder.setOutputFormat(MediaRecorder
.OutputFormat.AMR_NB);
// 设置声音编码的格式
mRecorder.setAudioEncoder(MediaRecorder
.AudioEncoder.AMR_NB);
mRecorder.setOutputFile(soundFile.getAbsolutePath());
mRecorder.prepare();
// 开始录音
mRecorder.start();
//①
}
catch
(Exception e)
{
e.printStackTrace();
}
break
;
// 单击停止按钮
case
R.id.stop:
if
(soundFile !=
null
&& soundFile.exists())
{
// 停止录音
mRecorder.stop();
//②
// 释放资源
mRecorder.release();
//③
mRecorder =
null
;
}
break
;
}
}
}</span>
|
程序运行效果图: