I try video recording on front camera (selfie). when it comes to implementation, it causes no recording response instead of start recording. When I press change camera button back, video recording does not work.
Please help me review the preview setup:
Below is part of my code in jetpack compose:
fun StoryCaptureScreen(
modifier: Modifier,
photoPath: Uri,
imageLoader: ImageLoader,
isAudioPermissionGranted: Boolean,
isLabelLoaded: Boolean,
isShowAlbumPermissionScreen: Boolean,
isDeviceSupportVideo: Boolean,
....
Surface(
modifier = modifier,
color = MaterialTheme.colors.background
) {
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val standardIconSize = 36.dp
val cameraPermissionState = rememberMultiplePermissionsState(
permissions = listOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
)
)
val necessaryCameraPermissionState = rememberMultiplePermissionsState(
permissions = listOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
)
)
val tempUploadDir by lazy {
FileUtil.createFolder(
FOLDER_TEMP_UPLOAD_FOLDER,
FileManager.getExternalFilesDir(context).absolutePath
)
}
val configuration = LocalConfiguration.current
val screenHeight = configuration.screenHeightDp.dp
val screenWidth = configuration.screenWidthDp.dp
var second by remember { mutableStateOf(0.toLong()) }
var currentNanoSecond by remember { mutableStateOf(0.toLong()) }
val maxSecond by remember { mutableStateOf((1000000000.0 * maximumRecordingSecond).toLong()) } // ktlint-disable max-line-length
var recording: Recording? = remember { null }
val recordingStarted: MutableState<Boolean> = remember { mutableStateOf(false) }
val cameraSelector: MutableState<CameraSelector> = remember {
mutableStateOf(CameraSelector.DEFAULT_BACK_CAMERA)
}
val audioEnabled: MutableState<Boolean> = remember { mutableStateOf(true) }
val isAudioMenuVisible: MutableState<Boolean> = remember { mutableStateOf(false) }
val isLoading: MutableState<Boolean> = remember { mutableStateOf(false) }
val flashEnabled: MutableState<Int> =
remember { mutableStateOf(0) } // 0 off , 1 on , 2 auto
val isFlashMenuVisible: MutableState<Boolean> = remember { mutableStateOf(false) }
val animatedProgress = remember { Animatable(1f) }
val animatedLoaded = remember { mutableStateOf(isLabelLoaded) }
LaunchedEffect(Unit) {
cameraPermissionState.launchMultiplePermissionRequest()
}
var preview = Preview.Builder().build()
val previewView = remember { PreviewView(context) }
val imageCapture: ImageCapture = remember {
ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_ZERO_SHUTTER_LAG)
.build()
}
imageCapture.flashMode = when (flashEnabled.value) {
0 -> ImageCapture.FLASH_MODE_OFF
1 -> ImageCapture.FLASH_MODE_ON
2 -> ImageCapture.FLASH_MODE_AUTO
else -> ImageCapture.FLASH_MODE_OFF
}
val qualitySelector = QualitySelector.from(
Quality.UHD,
FallbackStrategy.lowerQualityThan(Quality.UHD)
)
val recorder = Recorder.Builder()
.setExecutor(context.mainExecutor)
.setQualitySelector(qualitySelector)
.build()
val videoCapture = VideoCapture.withOutput(recorder)
LaunchedEffect(cameraSelector.value) {
Timber.d("image change camera lens: ${cameraSelector.value}")
preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
val cameraProvider = context.getCameraProvider()
cameraProvider.unbindAll()
if (isDeviceSupportVideo) {
cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector.value,
preview,
imageCapture,
videoCapture
).apply {
preview.setSurfaceProvider(previewView.surfaceProvider)
}
}
else {
cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector.value,
preview,
imageCapture
).apply {
preview.setSurfaceProvider(previewView.surfaceProvider)
}
}
}
.......
// front camera button
IconButton(
onClick = {
cameraSelector.value =
if (cameraSelector.value == CameraSelector.DEFAULT_BACK_CAMERA) CameraSelector.DEFAULT_FRONT_CAMERA // ktlint-disable max-line-length
else CameraSelector.DEFAULT_BACK_CAMERA
onTracking(
if (cameraSelector.value == CameraSelector.DEFAULT_FRONT_CAMERA) FirstLookTools.FrontCamera else FirstLookTools.BackCamera // ktlint-disable max-line-length
)
if (cameraSelector.value == CameraSelector.DEFAULT_FRONT_CAMERA) {
onLabelLoaded(true)
}
},
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(bottom = 48.dp, end = 24.dp)
) {
Image(
painter = painterResource(R.drawable.ic_outline_change_source),
contentDescription = "",
modifier = Modifier.size(64.dp)
)
}
Start recording:
@SuppressLint("MissingPermission")
fun startRecordingVideo(
context: Context,
filename: String,
videoCapture: VideoCapture<Recorder>,
outputDirectory: File,
executor: Executor,
audioEnabled: Boolean,
consumer: Consumer<VideoRecordEvent>
): Recording {
val videoFile = File(
outputDirectory,
"$filename.mp4"
)
val outputOptions = FileOutputOptions.Builder(videoFile).build()
return videoCapture.output
.prepareRecording(context, outputOptions)
.apply { if (audioEnabled) withAudioEnabled() }
.start(executor, consumer)
}