I'm trying to add a watermark text to a video while recording using CameraX's OverlayEffect API.
Initially, I considered using FFmpeg for this, but:
- Significantly increases the app size.
- Requires significant processing time.
Instead, I chose CameraX Effects API because it provides more flexibility, allowing real-time rendering directly onto the preview and recorded video.
Issues I'm Facing
- Text orientation is inconsistent between the front and back cameras.
- The watermark appears rotated incorrectly.
- I'm applying sensorToBufferTransform, but it doesn't seem to correctly align the text. Do I need additional transformations?
// Simple CameraX Effect implementation
private val handler = Handler(Looper.getMainLooper())
private val overlayEffect = OverlayEffect(
VIDEO_CAPTURE or PREVIEW,
0,
handler
) {
Log.e("Error", "overlayEffect error")
}.apply {
val textPaint = Paint().apply {
color = Color.RED
textSize = 50f
}
clearOnDrawListener()
// Rendering the text on the overlay
setOnDrawListener {
it.overlayCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR) // Clear previous frame
it.overlayCanvas.setMatrix(it.sensorToBufferTransform) // Apply transformation to align with the camera sensor
val text = "Watermark 12345"
val centerX = it.overlayCanvas.width / 2f
val centerY = it.overlayCanvas.height / 2f
it.overlayCanvas.drawText(text, centerX, centerY, textPaint) // Draw text at the center
true
}
}
private val useCaseGroupBuilder = UseCaseGroup.Builder()
.addUseCase(cameraPreviewUseCase)
.addUseCase(videoCapture)
.addEffect(overlayEffect) // Attach overlay effect to the camera pipeline
// Initialize and update the camera preview surface
private val cameraPreviewUseCase = Preview.Builder()
.setTargetRotation(Surface.ROTATION_0)
.build()
.apply {
setSurfaceProvider { newSurfaceRequest ->
_state.update { it.copy(surfaceRequest = newSurfaceRequest) }
}
}
// Compose UI: Rendering surface with CameraXViewfinder
state.surfaceRequest?.let { request ->
CameraXViewfinder(
surfaceRequest = request,
modifier = modifier,
implementationMode = ImplementationMode.EMBEDDED,
)
}
Screenshots: Back Camera Front Camera
What I'm Looking For: How can I correctly position and orient the text on both front and back cameras?