Michael Job
08/11/2025, 11:15 AMimplementation("org.bytedeco:javacv-platform:1.5.12")
implementation("org.bytedeco:opencv:4.9.0-1.5.10:macosx-arm64")
but it crashes with Error "long org.opencv.videoio.VideoCapture.VideoCapture_5(int)" - I tried several things... now I'm stuck.אליהו הדס
08/11/2025, 11:50 AMMichael Job
08/11/2025, 12:20 PMCaused by: java.lang.UnsatisfiedLinkError: /private/var/folders/kb/0qn585y97qs23g3mffq_918c0000gn/T/BridJExtractedLibraries13560179568080315218/libbridj.dylib: dlopen(/private/var/folders/kb/0qn585y97qs23g3mffq_918c0000gn/T/BridJExtractedLibraries13560179568080315218/libbridj.dylib, 0x0001): tried: '/opt/homebrew/Cellar/opencv/4.12.0_1/lib/libbridj.dylib' (no such file), '/private/var/folders/kb/0qn585y97qs23g3mffq_918c0000gn/T/BridJExtractedLibraries13560179568080315218/libbridj.dylib' (fat file, but missing compatible architecture (have 'x86_64,i386', need 'arm64e' or 'arm64')), '/System/Volumes/Preboot/Cryptexes/OS/private/var/folders/kb/0qn585y97qs23g3mffq_918c0000gn/T/BridJExtractedLibraries13560179568080315218/libbridj.dylib' (no such file), '/private/var/folders/kb/0qn585y97qs23g3mffq_918c0000gn/T/BridJExtractedLibraries13560179568080315218/libbridj.dylib' (fat file, but missing compatible architecture (have 'x86_64,i386', need 'arm64e' or 'arm64'))
אליהו הדס
08/11/2025, 12:23 PMgalex
08/11/2025, 3:54 PMEgor228000
08/12/2025, 11:31 AMimplementation( "com.github.sarxos:webcam-capture:0.3.12")
It is multiplatform.
val imageState = remember { mutableStateOf<androidx.compose.ui.graphics.ImageBitmap?>(null) }
val isRunning = remember { mutableStateOf(false) }
val coroutineScope = rememberCoroutineScope()
var webcamRef by remember { mutableStateOf<Webcam?>(null) }
Column(modifier = Modifier.padding(8.dp)) {
Box(
modifier = Modifier
.weight(1f)
.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
val img = imageState.value
if (img != null) {
Image(bitmap = img, contentDescription = "Camera preview", modifier = Modifier.fillMaxSize())
} else {
Text("Camera start")
}
}
Spacer(Modifier.height(8.dp))
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(onClick = {
if (!isRunning.value) {
isRunning.value = true
coroutineScope.launch {
val cam = Webcam.getDefault()
if (cam == null) {
isRunning.value = false
return@launch
}
webcamRef = cam
cam.viewSize = cam.viewSizes.maxByOrNull { it.width * it.height } ?: cam.viewSize
cam.open(true)
while (isActive && isRunning.value && cam.isOpen) {
val bimg: BufferedImage? = try {
cam.image
} catch (e: Exception) {
null
}
if (bimg != null) {
withContext(Dispatchers.Main) {
imageState.value = bimg.toComposeImageBitmap()
}
}
delay(33L) // ~30 FPS
}
try { cam.close() } catch (_: Exception) {}
webcamRef = null
isRunning.value = false
}
}
}) {
Text(if (isRunning.value) "Play" else "Start")
}
Button(onClick = {
isRunning.value = false
webcamRef?.let {
try { it.close() } catch (_: Exception) {}
webcamRef = null
}
imageState.value = null
}) {
Text("Stop")
}
}
}
If you want to use this library, you can also implement
implementation("org.bytedeco:javacv-platform:1.5.8")
val imageState = remember { mutableStateOf<ImageBitmap?>(null) }
val isRunning = remember { mutableStateOf(false) }
val coroutineScope = rememberCoroutineScope()
var grabber by remember { mutableStateOf<OpenCVFrameGrabber?>(null) }
Column(modifier = Modifier.fillMaxSize().padding(8.dp)) {
Box(
modifier = Modifier
.weight(1f)
.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
val img = imageState.value
if (img != null) {
Image(bitmap = img, contentDescription = "Camera", modifier = Modifier.fillMaxSize())
} else {
Text("No image")
}
}
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(onClick = {
if (!isRunning.value) {
isRunning.value = true
coroutineScope.launch(Dispatchers.IO) {
try {
val g = OpenCVFrameGrabber.createDefault(0)
grabber = g
g.start()
val converter = Java2DFrameConverter()
while (isActive && isRunning.value) {
val frame = g.grab()
if (frame != null) {
val bImage: BufferedImage? = converter.convert(frame)
if (bImage != null) {
withContext(Dispatchers.Main) {
imageState.value = bImage.toComposeImageBitmap()
}
}
}
delay(33L) // ~30 FPS
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
try { grabber?.stop() } catch (_: Exception) {}
try { grabber?.release() } catch (_: Exception) {}
grabber = null
isRunning.value = false
}
}
}
}) {
Text("Start")
}
Button(onClick = {
isRunning.value = false
coroutineScope.launch {
try { grabber?.stop() } catch (_: Exception) {}
try { grabber?.release() } catch (_: Exception) {}
grabber = null
imageState.value = null
}
}) {
Text("Stop")
}
}
}
It seemed to me that the implementation( "com.github.sarxos:webcam-capture:0.3.12"), displays the image faster on the screen
Egor228000
08/12/2025, 11:43 AMModifier.graphicsLayer(rotationY = 180f)
– to mirror it 🙂Michael Job
08/12/2025, 6:25 PMMichael Job
08/15/2025, 10:47 AMEgor228000
08/15/2025, 11:25 AM