Android CameraX录制视频触发ERROR_NO_VALID_DATA错误的排查与解决
问题描述
我正在使用CameraX在Android应用中实现视频录制功能,应用能正常显示相机预览,但尝试启动录制时出现以下错误:
error:Sending VideoRecordEvent Finalize [error: ERROR_NO_VALID_DATA]build.gradle中的依赖如下:
implementation ("androidx.camera:camera-camera2:1.3.0-rc01") implementation ("androidx.camera:camera-lifecycle:1.3.0-rc01") implementation ("androidx.camera:camera-view:1.3.0-rc01") implementation ("androidx.camera:camera-video:1.3.0-rc01")相关函数代码如下:
private fun initializeVideoCapture() { val recorder = Recorder.Builder() .setQualitySelector(QualitySelector.from(Quality.HIGHEST)) .build() videoCapture = VideoCapture.withOutput(recorder) } @SuppressLint("MissingPermission") private fun startRecording() { val videoCapture = this.videoCapture ?: return val videoFile = File( outputDirectory, "${System.currentTimeMillis()}.mp4" ) val outputOptions = FileOutputOptions.Builder(videoFile).build() recording = videoCapture.output .prepareRecording(this, outputOptions) .withAudioEnabled() .start(ContextCompat.getMainExecutor(this)) { recordEvent -> when (recordEvent) { is VideoRecordEvent.Start -> { Toast.makeText(this, "Recording started", Toast.LENGTH_SHORT).show() } is VideoRecordEvent.Finalize -> { if (recordEvent.hasError()) { Toast.makeText(this, "Recording error", Toast.LENGTH_SHORT).show() } else { Toast.makeText(this, "Recording succeeded", Toast.LENGTH_SHORT).show() } recording?.close() recording = null } } } } private fun stopRecording() { recording?.stop() recording = null } private fun allPermissionsGranted() = ActivityCompat.checkSelfPermission( this, Manifest.permission.CAMERA ) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( this, Manifest.permission.RECORD_AUDIO ) == PackageManager.PERMISSION_GRANTED private fun createOutputDirectory(): File { val mediaDir = externalMediaDirs.firstOrNull()?.let { File(it, resources.getString(R.string.app_name)).apply { mkdirs() } } return if (mediaDir != null && mediaDir.exists()) mediaDir else filesDir }已确保申请并授予必要的权限(CAMERA、RECORD_AUDIO),应用能正确初始化相机并显示预览,但启动视频录制时失败。请问是什么原因导致了ERROR_NO_VALID_DATA错误,如何解决以成功录制并保存视频?
排查方向及解决方法
1. 未绑定VideoCapture到Lifecycle
CameraX的VideoCapture组件必须绑定到Activity/Fragment的Lifecycle才能正常工作,否则无法持续获取相机帧数据,直接触发ERROR_NO_VALID_DATA。你的代码仅初始化了videoCapture,但未完成绑定步骤。
解决代码:
在initializeVideoCapture函数末尾添加绑定逻辑,如果同时使用预览组件,需一并绑定:
// 假设preview是已初始化的Preview对象 CameraX.bindToLifecycle(this as LifecycleOwner, preview, videoCapture)
2. 质量选择器无降级策略
直接使用QualitySelector.from(Quality.HIGHEST)可能选择当前设备不支持的分辨率或编码格式,导致录制无法生成有效数据。
解决代码:
为质量选择器添加自动降级策略:
val qualitySelector = QualitySelector.from(Quality.HIGHEST, FallbackStrategy.lowerQuality()) val recorder = Recorder.Builder() .setQualitySelector(qualitySelector) .build()
也可以指定设备更易支持的质量列表:
val qualitySelector = QualitySelector.from( listOf(Quality.FHD, Quality.HD, Quality.SD), FallbackStrategy.lowerQuality() )
3. 输出目录或文件权限异常
虽然创建了输出目录,但部分设备可能存在目录创建失败、外部存储访问限制等问题,导致录制文件无法写入。
排查与解决:
- 添加日志确认目录创建状态:
private fun createOutputDirectory(): File { val mediaDir = externalMediaDirs.firstOrNull()?.let { File(it, resources.getString(R.string.app_name)).apply { val isCreated = mkdirs() Log.d("VideoRecord", "Directory created: $isCreated, path: $absolutePath") } } return if (mediaDir != null && mediaDir.exists()) mediaDir else filesDir } - Android 13+需额外申请
READ_MEDIA_VIDEO权限(若需读取录制后的视频);Android 12及以下若使用非外部媒体目录,需申请WRITE_EXTERNAL_STORAGE权限。
4. 相机未完全就绪时启动录制
若在预览刚启动就触发录制,相机可能未完成初始化,无法提供有效帧数据。
解决方法:
监听相机状态,在STATE_ACTIVE时启动录制:
// 假设preview是已初始化的Preview对象 preview.cameraInfo.cameraState.observe(this) { state -> if (state.type == CameraState.Type.ACTIVE) { // 相机就绪,可安全调用startRecording() } }
5. 依赖版本为候选版
你使用的是CameraX 1.3.0-rc01候选版本,可能存在已知bug。
解决方法:
升级至稳定版本:
implementation ("androidx.camera:camera-camera2:1.3.0") implementation ("androidx.camera:camera-lifecycle:1.3.0") implementation ("androidx.camera:camera-view:1.3.0") implementation ("androidx.camera:camera-video:1.3.0")
内容的提问来源于stack exchange,提问作者ka hei tong

