前言
AudioRecord 和 MediaRecorder 两种都可以录制音频,MediaRecorder 已实现大量的封装,操作起来更加简单,而 AudioRecord 使用起来更加灵活,能实现更多的功能。
1. AudioRecord(基于字节流录音)
- 优点:可以实现语音的实时处理,进行边录边播,对音频的实时处理。
- 缺点:输出是PCM的语言数据,如果保存成音频文件是不能被播放器播放的。要用到AudioTrack这个去进行处理。
2. MediaRecorder(基于文件录音)
- 优点:封装度很高,操作简单
- 缺点:无法实现实时处理音频,输出的音频格式少。
主要函数
- setAudioChannels(int numChannels) 设置录制的音频通道数
- setAudioEncoder(int audio_encoder) 设置audio的编码格式
- setAudioEncodingBitRate(int bitRate) 设置录制的音频编码比特率
- setAudioSamplingRate(int samplingRate) 设置录制的音频采样率
- setAudioSource(int audio_source) 设置用于录制的音源
- setAuxiliaryOutputFile(String path) 辅助时间的推移视频文件的路径传递
- setAuxiliaryOutputFile(FileDescriptor fd)在文件描述符传递的辅助时间的推移视频
- setCamera(Camera c) 设置一个recording的摄像头
- setCaptureRate(double fps) 设置视频帧的捕获率
- setMaxDuration(int max_duration_ms) 设置记录会话的最大持续时间(毫秒)
- setMaxFileSize(long max_filesize_bytes) 设置记录会话的最大大小(以字节为单位)
- setOutputFile(FileDescriptor fd) 传递要写入的文件的文件描述符
- setOutputFile(String path) 设置输出文件的路径
- setOutputFormat(int output_format) 设置在录制过程中产生的输出文件的格式
- setPreviewDisplay(Surface sv) 表面设置显示记录媒体(视频)的预览
- setVideoEncoder(int video_encoder) 设置视频编码器,用于录制
- setVideoEncodingBitRate(int bitRate) 设置录制的视频编码比特率
- setVideoFrameRate(int rate) 设置要捕获的视频帧速率
- setVideoSize(int width, int height) 设置要捕获的视频的宽度和高度
- setVideoSource(int video_source) 开始捕捉和编码数据到setOutputFile(指定的文件)
- setLocation(float latitude, float longitude) 设置并存储在输出文件中的地理数据(经度和纬度)
- setProfile(CamcorderProfile profile) 指定CamcorderProfile对象
- setOrientationHint(int degrees)设置输出的视频播放的方向提示
- setOnErrorListener(MediaRecorder.OnErrorListener l)注册一个用于记录录制时出现的错误的监听器
- setOnInfoListener(MediaRecorder.OnInfoListener listener)注册一个用于记录录制时出现的信息事件
- getMaxAmplitude() 获取在前一次调用此方法之后录音中出现的最大振幅
- prepare()准备录制。
- release()释放资源
- reset()将MediaRecorder设为空闲状态
- start()开始录制
- stop()停止录制
配置参数:
1.)视频编码格式MediaRecorder.VideoEncoder
default,H263,H264,MPEG_4_SP,VP8
2.)音频编码格式MediaRecorder.AudioEncoder
default,AAC,HE_AAC,AAC_ELD,AMR_NB,AMR_WB,VORBIS
3.)视频资源获取方式MediaRecorder.VideoSource
default,CAMERA,SURFACE
4.)音频资源获取方式MediaRecorder.AudioSource
defalut,camcorder,mic,voice_call,voice_communication,voice_downlink,voice_recognition, voice_uplink
5.)资源输出格式MediaRecorder.OutputFormat
amr_nb,amr_wb,default,mpeg_4,raw_amr,three_gpp,aac_adif, aac_adts, output_format_rtp_avp,
output_format_mpeg2ts ,webm
实现代码
1. 在清单文件中,添加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
2. 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/btn_record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始录音"
android:layout_margin="10dp"/>
</LinearLayout>
3. 逻辑代码
public class MainActivity extends BaseActivity {
@BindView(R.id.btn_record)
Button mStartRecord;
private boolean isStart = false;
private MediaRecorder mRecorder = null;
@Override
protected int getLayoutId() {
return R.layout.activity_main;
}
@Override
protected void initView() {
checkPermission();
}
@OnClick(R.id.btn_record)
public void clicked() {
if(!isStart){
startRecord();
mStartRecord.setText("停止录制");
isStart = true;
}else{
stopRecord();
mStartRecord.setText("开始录制");
isStart = false;
}
}
//开始录制
private void startRecord(){
if(mRecorder == null){
File dir = new File(Environment.getExternalStorageDirectory(),"sounds");
if(!dir.exists()){
dir.mkdirs();
}
File soundFile = new File(dir,System.currentTimeMillis() +".amr");
if(!soundFile.exists()){
try {
soundFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); //音频输入源
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_WB); //设置输出格式
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB); //设置编码格式
mRecorder.setOutputFile(soundFile.getAbsolutePath());
try {
mRecorder.prepare();
mRecorder.start(); //开始录制
} catch (IOException e) {
e.printStackTrace();
}
}
}
//停止录制,资源释放
private void stopRecord(){
if(mRecorder != null){
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
}
/**
* 权限申请
*/
private void checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String[] permissions = new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE};
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, permissions, 200);
return;
}
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]
grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && requestCode == 200) {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, 200);
return;
}
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == 200) {
checkPermission();
}
}
}