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

基于Kotlin Jetpack Compose的CameraX连拍模式优化需求

解决方案

一、核心问题分析

你的当前实现存在两个关键瓶颈:

  1. 串行调用takePicture,每个捕获请求需等待前一个完成才会触发,导致整体速度极慢;
  2. 主线程处理Bitmap转换,引发相机卡顿;
  3. 未利用CameraX的高速连拍特性,手动循环的方式效率低下。

二、优化连拍速度(30张压缩至3秒)

1. 重新配置ImageCapture

优先低延迟模式,搭配合理的分辨率、质量设置,减少相机处理开销:

val imageCapture = remember {
    ImageCapture.Builder()
        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY) // 优先低延迟,适配高速连拍
        .setZslEnabled(true) // 强制开启零快门延迟
        .setTargetResolution(Size(1920, 1080)) // 降低分辨率提升速度,按需调整
        .setJpegQuality(80) // 适度降低JPEG质量,减少文件处理时间
        .setBufferSize(3) // 增加缓冲区,减少丢帧概率
        .setTargetRotation(ROTATION_0)
        .setFlashMode(if(torchState) ImageCapture.FLASH_MODE_ON else ImageCapture.FLASH_MODE_OFF)
        .build()
}

2. 异步并发捕获+后台Bitmap处理

用循环并发提交捕获请求,控制间隔保证3秒内完成30张,同时把Bitmap转换移到后台线程:

val vibesList = remember { mutableStateListOf<Bitmap>() }
var isBurstActive by remember { mutableStateOf(false) }
var capturedCount by remember { mutableStateOf(0) }
val maxBurstCount = 30
val coroutineScope = rememberCoroutineScope()

fun startBurstCapture(context: Context) {
    capturedCount = 0
    isBurstActive = true
    coroutineScope.launch(Dispatchers.IO) {
        while (isBurstActive && capturedCount < maxBurstCount) {
            val executor = ContextCompat.getMainExecutor(context)
            imageCapture.takePicture(executor, object : ImageCapture.OnImageCapturedCallback() {
                override fun onCaptureSuccess(image: ImageProxy) {
                    super.onCaptureSuccess(image)
                    // 后台线程处理Bitmap转换,避免主线程卡顿
                    coroutineScope.launch(Dispatchers.IO) {
                        val bitmap = image.toBitmap()
                        withContext(Dispatchers.Main) {
                            vibesList.add(bitmap)
                            capturedCount++
                            // 达到数量自动停止
                            if (capturedCount >= maxBurstCount) {
                                isBurstActive = false
                            }
                        }
                        image.close()
                    }
                }

                override fun onError(exception: ImageCaptureException) {
                    super.onError(exception)
                    Log.e("Camera", "连拍失败: ", exception)
                    isBurstActive = false
                    capturedCount = 0
                }
            })
            delay(100) // 控制连拍间隔,100ms/张,30张约3秒
        }
    }
}

fun stopBurstCapture() {
    isBurstActive = false
}

三、实现长按启动/松开停止连拍

用Compose的pointerInput监听长按事件,替换原clickable:

Text(
    text = if (isBurstActive) "拍摄中 ($capturedCount/$maxBurstCount)" else "长按连拍",
    fontFamily = FontFamily(listOf(Font(R.font.damion))),
    fontSize = 28.sp,
    fontWeight = FontWeight.Bold,
    color = Color(0xFF000000),
    modifier = Modifier
        .pointerInput(Unit) {
            detectTapGestures(
                onPress = {
                    // 按下启动连拍
                    startBurstCapture(context)
                    // 等待用户松开手指
                    tryAwaitRelease()
                    // 松开停止连拍
                    stopBurstCapture()
                }
            )
        }
)

四、额外优化建议

  • 关闭不必要的闪光灯,闪光灯会增加单帧拍摄延迟;
  • 保证相机预览分辨率与ImageCapture目标分辨率一致,减少格式转换开销;
  • 避免在捕获回调中直接操作UI状态,所有状态更新必须切换到主线程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:43:11