Android一键音视频录制应用崩溃求助:RuntimeException start failed -22
解决Android音视频录制start failed -22异常
核心原因分析
RuntimeException: start failed -22 通常指向MediaRecorder参数配置不兼容——比如设备不支持所选的分辨率、帧率、编码格式,参数设置顺序错误,或是权限、Surface初始化未达标。
分步排查与修复方案
1. 严格遵循MediaRecorder参数设置顺序
参数初始化顺序错误是触发该异常的高频原因,正确流程必须按以下顺序执行:
mediaRecorder = new MediaRecorder(); // 1. 设置音频源 mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 2. 设置视频源 mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 3. 设置输出格式(必须在编码格式之前) mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 4. 设置音频编码格式 mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); // 5. 设置视频编码格式 mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 6. 设置视频分辨率、帧率、比特率 mediaRecorder.setVideoSize(1280, 720); // 需确认设备支持该分辨率 mediaRecorder.setVideoFrameRate(30); mediaRecorder.setVideoEncodingBitRate(2 * 1024 * 1024); // 7. 设置输出文件路径 mediaRecorder.setOutputFile(getOutputFilePath()); // 8. 设置预览Surface(如需预览) mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface()); // 9. 准备与启动 mediaRecorder.prepare(); mediaRecorder.start();
2. 验证设备支持的视频参数
不同设备支持的分辨率、帧率组合差异大,硬编码兼容性问题普遍。可通过以下代码获取设备支持的参数:
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { String[] cameraIds = manager.getCameraIdList(); for (String id : cameraIds) { CameraCharacteristics characteristics = manager.getCameraCharacteristics(id); StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); Size[] sizes = map.getOutputSizes(MediaRecorder.class); // 遍历输出尺寸,选择设备支持的参数 for (Size size : sizes) { Log.d("CameraSupport", "Supported size: " + size.getWidth() + "x" + size.getHeight()); } } } catch (CameraAccessException e) { e.printStackTrace(); }
选择列表中存在的分辨率,避免使用设备不支持的参数。
3. 检查权限配置
确保已申请并获取必要权限:
- 动态申请:
android.permission.RECORD_AUDIO、android.permission.CAMERA、android.permission.WRITE_EXTERNAL_STORAGE(Android 10及以下) - AndroidManifest.xml声明:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" />
4. 确认Surface初始化状态
若使用预览Surface,需确保Surface完全初始化后再传递给MediaRecorder。建议在SurfaceHolder.Callback的surfaceCreated或surfaceChanged回调中初始化MediaRecorder,避免Surface未就绪的情况。
5. 适配Android版本差异
- Android 10及以上使用
MediaStore存储文件,避免直接访问外部存储路径 - Android 11+需注意分区存储限制,确保输出文件路径合法
完整示例代码片段
private MediaRecorder mediaRecorder; private SurfaceHolder surfaceHolder; private void initRecorder() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, 100); return; } mediaRecorder = new MediaRecorder(); try { mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 使用设备支持的分辨率,此处以720p为例,可替换为实际支持尺寸 mediaRecorder.setVideoSize(1280, 720); mediaRecorder.setVideoFrameRate(30); mediaRecorder.setVideoEncodingBitRate(2 * 1024 * 1024); // 设置输出路径(Android 10+推荐使用应用私有目录) String outputPath = getExternalFilesDir(Environment.DIRECTORY_MOVIES) + "/record_" + System.currentTimeMillis() + ".mp4"; mediaRecorder.setOutputFile(outputPath); if (surfaceHolder != null) { mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface()); } mediaRecorder.prepare(); mediaRecorder.start(); } catch (IOException e) { e.printStackTrace(); releaseRecorder(); } catch (RuntimeException e) { e.printStackTrace(); releaseRecorder(); } } private void releaseRecorder() { if (mediaRecorder != null) { try { mediaRecorder.stop(); } catch (RuntimeException e) { // 处理录制未启动时的stop异常 } mediaRecorder.release(); mediaRecorder = null; } }
额外注意事项
- 录制完成后必须正确释放MediaRecorder资源,避免内存泄漏
- 测试时覆盖不同品牌和版本设备,兼容性问题在不同厂商设备上表现不同
- 若使用CameraX替代原生Camera API,可简化参数适配和兼容性处理
内容的提问来源于stack exchange,提问作者Priyabrata Nayak
相关产品推荐
相关产品推荐

