You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android CameraX录制视频触发ERROR_NO_VALID_DATA错误的排查与解决

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 10:45:55