如何使用ARCore捕获Android设备的相机画面(视频/静态图片)
Hey there! 作为ARCore新手,要捕获相机画面并做后续处理其实没你想的那么复杂,我来给你梳理下核心API和具体的实现示例,不管是单帧静态图还是连续视频都能搞定~
核心ARCore API选择
你主要需要用到这几个核心类的API:
Frame类:ARCore的帧数据容器,每帧画面的核心信息都在这里,用来获取相机原始图像CameraImage类:封装了YUV格式的原始相机像素数据,支持直接处理或转成BitmapConfig类:用来配置ARCore会话,比如添加自定义Surface实现视频录制Session类:管理ARCore的整个会话流程,关联相机输出目标
静态图片捕获(单帧画面)
如果只需要捕获单帧静态图,用Frame.acquireCameraImage()就能获取原始相机图像,之后可以转成Bitmap或者直接处理YUV像素数据。下面是Kotlin的实现示例:
import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Rect import android.graphics.YuvImage import android.media.ImageFormat import android.util.Log import com.google.ar.core.CameraImage import com.google.ar.core.CameraImageNotAvailableException import com.google.ar.core.Frame // 在ARCore的帧更新回调中捕获画面 override fun onUpdateFrame(frame: Frame) { // 检查当前帧是否可用相机图像 if (frame.hasDisplayGeometry() && frame.cameraImageAvailable) { try { // 使用use{}块自动释放CameraImage资源,避免内存泄漏 frame.acquireCameraImage().use { cameraImage -> // 将YUV格式的相机图像转成Bitmap val capturedBitmap = convertYuvToBitmap(cameraImage) // 这里写你自己的画面处理逻辑,比如滤镜、特征识别等 processCapturedImage(capturedBitmap) } } catch (e: CameraImageNotAvailableException) { Log.e("ARCoreCapture", "Failed to get camera image", e) } } } // 辅助方法:将CameraImage的YUV数据转成Bitmap private fun convertYuvToBitmap(cameraImage: CameraImage): Bitmap { val yPlane = cameraImage.planes[0] val yuvImage = YuvImage( yPlane.buffer, ImageFormat.NV21, cameraImage.width, cameraImage.height, null ) val outputStream = ByteArrayOutputStream() yuvImage.compressToJpeg(Rect(0, 0, cameraImage.width, cameraImage.height), 90, outputStream) val imageBytes = outputStream.toByteArray() return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size) } // 自定义的画面处理方法示例 private fun processCapturedImage(bitmap: Bitmap) { // 比如:给图片加个灰度滤镜,或者提取特征点 // ... 你的处理逻辑 ... }
注意点:
acquireCameraImage()必须及时释放,用use{}块是最安全的方式- 如果追求性能,建议直接处理YUV格式的原始数据,不用转成Bitmap(避免额外的内存开销)
视频捕获(连续画面)
ARCore本身没有内置视频录制功能,但可以结合Android的MediaRecorder来实现,通过给ARCore配置自定义Surface,让相机帧直接输出到MediaRecorder的输入源,效率很高。示例代码如下:
import android.media.MediaRecorder import android.os.Environment import com.google.ar.core.Config import com.google.ar.core.Session import java.io.File import java.io.IOException private lateinit var mediaRecorder: MediaRecorder private var isRecording = false // 初始化MediaRecorder配置 private fun initVideoRecorder() { mediaRecorder = MediaRecorder().apply { setAudioSource(MediaRecorder.AudioSource.MIC) setVideoSource(MediaRecorder.VideoSource.SURFACE) setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) // 设置视频保存路径(这里示例存在外部存储) setOutputFile(getVideoOutputPath()) setVideoEncodingBitRate(10 * 1024 * 1024) // 10Mbps码率 setVideoFrameRate(30) // 30帧每秒 setVideoSize(1920, 1080) // 1080P分辨率 setVideoEncoder(MediaRecorder.VideoEncoder.H264) setAudioEncoder(MediaRecorder.AudioEncoder.AAC) try { prepare() } catch (e: IOException) { Log.e("ARCoreVideo", "Failed to init MediaRecorder", e) } } } // 配置ARCore会话,关联MediaRecorder的Surface private fun setupARSession(session: Session) { val config = Config(session) // 获取MediaRecorder的Surface,让ARCore把相机帧输出到这里 val recorderSurface = mediaRecorder.surface config.addCameraTextureTarget(recorderSurface) session.configure(config) } // 开始录制 fun startRecording() { if (!isRecording) { mediaRecorder.start() isRecording = true } } // 停止录制 fun stopRecording() { if (isRecording) { try { mediaRecorder.stop() } catch (e: IllegalStateException) { Log.e("ARCoreVideo", "Stop recording failed", e) } finally { mediaRecorder.reset() isRecording = false } } } // 生成视频保存路径 private fun getVideoOutputPath(): String { val videoDir = File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), "ARCoreCaptures" ) if (!videoDir.exists()) videoDir.mkdirs() return "${videoDir.absolutePath}/AR_${System.currentTimeMillis()}.mp4" }
注意点:
- 需要申请
CAMERA、RECORD_AUDIO、WRITE_EXTERNAL_STORAGE权限(Android 13+权限规则有变化,记得适配) - 如果需要在视频中叠加AR元素(比如虚拟物体),可以用OpenGL的帧缓冲(FBO)先渲染AR内容,再把结果输出到MediaRecorder的Surface
额外提示
- 性能优化:画面处理逻辑尽量放在后台线程执行,避免阻塞UI线程导致AR画面卡顿
- 内部应用用途:ARCore的API对内部使用没有特殊限制,只要遵守Google的ARCore服务条款即可
- 调试建议:可以先从静态图片捕获开始调试,确认画面能正常获取和处理后,再扩展到视频录制
内容的提问来源于stack exchange,提问作者hutanrimba
相关产品推荐
相关产品推荐

