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

使用CameraX VideoCapture API录制视频时遇错误,求解决方法

解决CameraX VideoCapture录制视频时的"Albums cannot be directly modified"错误

错误原因

从日志关键信息collectionUri=content://media/external/audio/albums可以看出:你创建MediaStoreOutputOptions时传入了音频专辑的URI,但录制视频需要使用视频媒体对应的存储URI,导致系统尝试修改音频专辑目录,触发了UnsupportedOperationException。

修复步骤

1. 替换正确的MediaStore URI

将创建MediaStoreOutputOptions时的EXTERNAL_CONTENT_URI替换为MediaStore.Video.Media.EXTERNAL_CONTENT_URI,这是视频文件的合法存储URI。

修复后的关键代码片段:

val options = MediaStoreOutputOptions.Builder(requireContext().contentResolver, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
    .setContentValues(contentValues)
    .build()

2. 检查权限配置

确保AndroidManifest.xml中声明了必要权限:

<!-- Android 10及以下需要 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Android 13+需单独声明视频权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- 如果需要录制带音频的视频,添加此权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />

运行时需动态申请这些权限(Android 10+使用Scoped Storage可自动处理部分存储权限,但低版本仍需手动申请)。

3. 可选:修正日期格式

你使用的SimpleDateFormat格式"yyy-MM-dd-HH-mm-ss-SSS"少一个y,会导致年份显示错误,建议改为"yyyy-MM-dd-HH-mm-ss-SSS"。

完整修复后的recordVideo函数

private fun recordVideo() {
    binding.buttonCapture.setImageResource(R.drawable.baseline_stop_24)

    val currentRecording = recording
    if (currentRecording != null) {
        // 停止正在进行的录制
        currentRecording.stop()
        recording = null
        binding.buttonCapture.setImageResource(R.drawable.baseline_camera_24)
        return
    }

    val name: String = SimpleDateFormat(
        "yyyy-MM-dd-HH-mm-ss-SSS", // 修正年份格式
        Locale.getDefault()
    ).format(System.currentTimeMillis())
    val contentValues = ContentValues().apply {
        put(MediaStore.MediaColumns.DISPLAY_NAME, name)
        put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")
        put(MediaStore.MediaColumns.RELATIVE_PATH, "Movies/CameraX-Recorder")
    }

    // 使用视频对应的MediaStore URI
    val options = MediaStoreOutputOptions.Builder(requireContext().contentResolver, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
        .setContentValues(contentValues)
        .build()

    recording = videoCapture?.output?.prepareRecording(requireContext(), options)
        ?.start(ContextCompat.getMainExecutor(requireContext())) { videoRecordEvent -> 
            when (videoRecordEvent) {
                is VideoRecordEvent.Start -> {
                    binding.buttonCapture.setImageResource(R.drawable.baseline_stop_24)
                }
                is VideoRecordEvent.Pause -> {
                    // 处理暂停逻辑
                }
                is VideoRecordEvent.Resume -> {
                    // 处理恢复逻辑
                }
                is VideoRecordEvent.Finalize -> {
                    val finalizeEvent = videoRecordEvent as VideoRecordEvent.Finalize
                    val error = finalizeEvent.error
                    if (error != VideoRecordEvent.Finalize.ERROR_NONE) {
                        Toast.makeText(
                            requireContext(),
                            "视频录制完成时出错: ${videoRecordEvent.error}",
                            Toast.LENGTH_SHORT
                        ).show()
                    } else {
                        Toast.makeText(
                            requireContext(),
                            "视频录制成功",
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                    binding.buttonCapture.setImageResource(R.drawable.baseline_camera_24)
                }
            }
            val recordingStats = videoRecordEvent.recordingStats
        }
}

内容的提问来源于stack exchange,提问作者Patrick Renaud

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 22:35:46