https://www.cnblogs.com/zhujiabin/p/9035883.html
音视频同步原理讲的清楚: https://blog.csdn.net/zhuweigangzwg/article/details/25815851
package com.example.recordvideo; import android.Manifest; import android.app.Activity; import android.content.pm.PackageManager; import android.graphics.Camera; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageButton; import android.widget.Toast; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import java.io.File; import java.io.FileOutputStream; import java.nio.charset.StandardCharsets; public class MainActivity extends Activity implements OnClickListener { private static final String TAG = "MainActivity"; // 程序中的两个按钮 Button record, stop; // 系统的视频文件 File videoFile; MediaRecorder mRecorder; // 显示视频预览的SurfaceView SurfaceView sView; // 记录是否正在进行录制 private boolean isRecording = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取程序界面中的两个按钮 record = (Button) findViewById(R.id.record); stop = (Button) 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(1920, 1080); // 1080P // 设置该组件让屏幕不会自动关闭 //sView.getHolder().setKeepScreenOn(true); verifyStoragePermissions(this); } @Override public void onClick(View v) { // 单击录制按钮 if (v.getId() == R.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() + "/my_video.mp4"); videoFile = new File(getExternalFilesDir(""),"0919.mp4"); // videoFile = new File("data/data/com.example.recordvideo/0919.mp4"); // 创建MediaPlayer对象 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.AAC); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); // .AudioEncoder.DEFAULT); // 设置图像编码的格式 //mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mRecorder.setOrientationHint(90); //mRecorder.setVideoSize(1920, 1080); // 1080P mRecorder.setVideoSize(640, 480); // 1080P // 每秒16帧 已加入帧数就出错 // mRecorder.setVideoFrameRate(20); mRecorder.setMaxDuration(10*1000); //mRecorder.setVideoFrameRate(30); //mRecorder.setVideoEncodingBitRate(1024*1024*20); mRecorder.setOutputFile(videoFile.getAbsolutePath()); Log.i(TAG, "---------------->: "+videoFile.getAbsolutePath()); // 指定使用SurfaceView来预览视频 mRecorder.setPreviewDisplay(sView.getHolder().getSurface()); // ① mRecorder.prepare(); // 开始录制 mRecorder.start(); Log.d(TAG, "---recording---"); // 让record按钮不可用 record.setEnabled(false); // 让stop按钮可用 stop.setEnabled(true); isRecording = true; /* try{ //-- FileOutputStream txtFile = new FileOutputStream("data/data/com.example.recordvideo/0919.txt"); Log.d(TAG, "---recording---"+txtFile); txtFile.write("haha".getBytes()); txtFile.flush(); txtFile.close(); } catch (Exception e){ e.printStackTrace(); } */ // } catch (Exception e) { e.printStackTrace(); } } else if (v.getId() == R.id.stop) { // 单击停止按钮 // 如果正在进行录制 if (isRecording) { // 停止录制 mRecorder.stop(); mRecorder.reset(); // 释放资源 mRecorder.release(); Log.i(TAG, "---------------->:stop" ); mRecorder = null; // 让record按钮可用 record.setEnabled(true); // 让stop按钮不可用 stop.setEnabled(false); } } } private final int REQUEST_EXTERNAL_STORAGE = 1; private String[] PERMISSIONS_STORAGE = { Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE }; public void verifyStoragePermissions(Activity activity) { // Check if we have write permission // int permission = ActivityCompat.checkSelfPermission(activity, // Manifest.permission.WRITE_EXTERNAL_STORAGE); //if (permission != PackageManager.PERMISSION_GRANTED) { // We don't have permission so prompt the user ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE); } } }
<uses-feature android:name="android.hardware.camera"/> <uses-feature android:name="android.hardware.camera.autofocus"/> <uses-permission android:name="android.permission.CAMERA" > </uses-permission> <uses-permission android:name="android.permission.RECORD_AUDIO" > </uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" > </uses-permission>