mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-18 23:05:26 +02:00
debug: current stand trying to make ffmpeg to work
This commit is contained in:
parent
1eb7a7dd9a
commit
fe9d9d7298
@ -56,15 +56,12 @@ class AudioBatchesFolder(
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun viaInternalFolder(context: Context): BatchesFolder {
|
||||
return AudioBatchesFolder(context, BatchType.INTERNAL)
|
||||
}
|
||||
fun viaInternalFolder(context: Context) = AudioBatchesFolder(context, BatchType.INTERNAL)
|
||||
|
||||
fun viaCustomFolder(context: Context, folder: DocumentFile): BatchesFolder {
|
||||
return AudioBatchesFolder(context, BatchType.CUSTOM, folder)
|
||||
}
|
||||
fun viaCustomFolder(context: Context, folder: DocumentFile) =
|
||||
AudioBatchesFolder(context, BatchType.CUSTOM, folder)
|
||||
|
||||
fun importFromFolder(folder: String, context: Context): BatchesFolder = when (folder) {
|
||||
fun importFromFolder(folder: String, context: Context) = when (folder) {
|
||||
"_'internal" -> viaInternalFolder(context)
|
||||
else -> viaCustomFolder(context, DocumentFile.fromTreeUri(context, Uri.parse(folder))!!)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ abstract class BatchesFolder(
|
||||
|
||||
fun initFolders() {
|
||||
when (type) {
|
||||
BatchType.INTERNAL -> getFolder(context).mkdirs()
|
||||
BatchType.INTERNAL -> getInternalFolder().mkdirs()
|
||||
BatchType.CUSTOM -> {
|
||||
if (customFolder!!.findFile(subfolderName) == null) {
|
||||
customFolder!!.createDirectory(subfolderName)
|
||||
@ -35,7 +35,7 @@ abstract class BatchesFolder(
|
||||
}
|
||||
|
||||
fun getInternalFolder(): File {
|
||||
return getFolder(context)
|
||||
return File(context.filesDir, subfolderName)
|
||||
}
|
||||
|
||||
fun getCustomDefinedFolder(): DocumentFile {
|
||||
@ -189,9 +189,5 @@ abstract class BatchesFolder(
|
||||
INTERNAL,
|
||||
CUSTOM,
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getFolder(context: Context) = File(context.filesDir, RECORDER_SUBFOLDER_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,9 +67,9 @@ class MediaConverter {
|
||||
val listFile = createTempFile(inputFiles.joinToString("\n", prefix = "file "))
|
||||
|
||||
val command =
|
||||
"-protocol_whitelist saf,concat,content,file,subfile" +
|
||||
" -f concat" +
|
||||
" -f concat" +
|
||||
" -y" +
|
||||
" -safe 0" +
|
||||
" -i ${listFile.absolutePath}" +
|
||||
" -c copy" +
|
||||
extraCommand +
|
||||
|
@ -53,17 +53,14 @@ class VideoBatchesFolder(
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun viaInternalFolder(context: Context): BatchesFolder {
|
||||
return VideoBatchesFolder(context, BatchType.INTERNAL)
|
||||
}
|
||||
fun viaInternalFolder(context: Context) = VideoBatchesFolder(context, BatchType.INTERNAL)
|
||||
|
||||
fun viaCustomFolder(context: Context, folder: DocumentFile): BatchesFolder {
|
||||
return VideoBatchesFolder(context, BatchType.CUSTOM, folder)
|
||||
}
|
||||
fun viaCustomFolder(context: Context, folder: DocumentFile) =
|
||||
VideoBatchesFolder(context, BatchType.CUSTOM, folder)
|
||||
|
||||
fun importFromFolder(folder: String, context: Context): BatchesFolder = when (folder) {
|
||||
"_'internal" -> AudioBatchesFolder.viaInternalFolder(context)
|
||||
else -> AudioBatchesFolder.viaCustomFolder(
|
||||
fun importFromFolder(folder: String, context: Context) = when (folder) {
|
||||
"_'internal" -> viaInternalFolder(context)
|
||||
else -> viaCustomFolder(
|
||||
context,
|
||||
DocumentFile.fromTreeUri(context, Uri.parse(folder))!!
|
||||
)
|
||||
|
@ -162,12 +162,14 @@ abstract class RecorderService : LifecycleService() {
|
||||
changeState(RecorderState.RECORDING)
|
||||
}
|
||||
|
||||
fun stopRecording() {
|
||||
changeState(RecorderState.IDLE)
|
||||
stop()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
stop()
|
||||
changeState(RecorderState.IDLE)
|
||||
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
NotificationManagerCompat.from(this)
|
||||
.cancel(NotificationHelper.RECORDER_CHANNEL_NOTIFICATION_ID)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package app.myzel394.alibi.services
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.util.Range
|
||||
import androidx.camera.core.Camera
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||
@ -38,6 +39,8 @@ class VideoRecorderService :
|
||||
// Used to listen and check if the camera is available
|
||||
private var _cameraAvailableListener = CompletableDeferred<Unit>()
|
||||
|
||||
private var selectedCamera: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
||||
|
||||
// Runs a function in the main thread
|
||||
private fun runInMain(callback: () -> Unit) {
|
||||
val mainHandler = ContextCompat.getMainExecutor(this)
|
||||
@ -45,6 +48,23 @@ class VideoRecorderService :
|
||||
mainHandler.execute(callback)
|
||||
}
|
||||
|
||||
private fun buildRecorder() = Recorder.Builder()
|
||||
.setQualitySelector(settings.quality)
|
||||
.apply {
|
||||
if (settings.targetVideoBitRate != null) {
|
||||
setTargetVideoEncodingBitRate(settings.targetVideoBitRate!!)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
|
||||
private fun buildVideoCapture(recorder: Recorder) = VideoCapture.Builder(recorder)
|
||||
.apply {
|
||||
if (settings.targetFrameRate != null) {
|
||||
setTargetFrameRate(Range(settings.targetFrameRate!!, settings.targetFrameRate!!))
|
||||
}
|
||||
}
|
||||
.build()
|
||||
|
||||
// Open the camera.
|
||||
// Used to open it for a longer time, shouldn't be called when pausing / resuming.
|
||||
// This should only be called when starting a recording.
|
||||
@ -53,16 +73,13 @@ class VideoRecorderService :
|
||||
ProcessCameraProvider.getInstance(this@VideoRecorderService).get()
|
||||
}
|
||||
|
||||
val recorder = Recorder.Builder()
|
||||
.setQualitySelector(settings.quality)
|
||||
.build()
|
||||
videoCapture = VideoCapture.Builder(recorder)
|
||||
.build()
|
||||
val recorder = buildRecorder()
|
||||
videoCapture = buildVideoCapture(recorder)
|
||||
|
||||
runInMain {
|
||||
camera = cameraProvider!!.bindToLifecycle(
|
||||
this,
|
||||
CameraSelector.DEFAULT_BACK_CAMERA,
|
||||
selectedCamera,
|
||||
videoCapture
|
||||
)
|
||||
|
||||
@ -74,7 +91,7 @@ class VideoRecorderService :
|
||||
// Used to close it finally, shouldn't be called when pausing / resuming.
|
||||
// This should only be called after recording has finished.
|
||||
private fun closeCamera() {
|
||||
clearOldVideoRecording()
|
||||
stopActiveRecording()
|
||||
|
||||
runCatching {
|
||||
cameraProvider?.unbindAll()
|
||||
@ -99,10 +116,8 @@ class VideoRecorderService :
|
||||
closeCamera()
|
||||
}
|
||||
|
||||
private fun clearOldVideoRecording() {
|
||||
runCatching {
|
||||
activeRecording?.stop()
|
||||
}
|
||||
private fun stopActiveRecording() {
|
||||
activeRecording?.stop()
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@ -143,11 +158,13 @@ class VideoRecorderService :
|
||||
type = RecordingInformation.Type.VIDEO,
|
||||
)
|
||||
|
||||
// TODO: Save camera selector as it doesn't make sense to change the camera midway
|
||||
data class Settings(
|
||||
override val maxDuration: Long,
|
||||
override val intervalDuration: Long,
|
||||
val folder: String? = null,
|
||||
val targetVideoBitRate: Int? = null,
|
||||
val targetFrameRate: Int? = null,
|
||||
val quality: QualitySelector = QualitySelector.from(Quality.HIGHEST),
|
||||
) : IntervalRecorderService.Settings(
|
||||
maxDuration = maxDuration,
|
||||
@ -172,6 +189,7 @@ class VideoRecorderService :
|
||||
intervalDuration = appSettings.audioRecorderSettings.intervalDuration,
|
||||
folder = appSettings.audioRecorderSettings.saveFolder,
|
||||
targetVideoBitRate = appSettings.videoRecorderSettings.targetedVideoBitRate,
|
||||
targetFrameRate = appSettings.videoRecorderSettings.targetFrameRate,
|
||||
quality = appSettings.videoRecorderSettings.getQualitySelector()
|
||||
?: QualitySelector.from(
|
||||
Quality.HIGHEST
|
||||
|
@ -26,7 +26,6 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.myzel394.alibi.dataStore
|
||||
import app.myzel394.alibi.db.AppSettings
|
||||
import app.myzel394.alibi.helpers.AudioRecorderExporter
|
||||
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.DeleteButton
|
||||
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneDisconnectedDialog
|
||||
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneReconnectedDialog
|
||||
@ -106,7 +105,7 @@ fun RecordingStatus(
|
||||
) {
|
||||
DeleteButton(
|
||||
onDelete = {
|
||||
audioRecorder.stopRecording(context)
|
||||
//audioRecorder.stopRecording(context)
|
||||
audioRecorder.batchesFolder!!.deleteRecordings();
|
||||
}
|
||||
)
|
||||
@ -136,7 +135,7 @@ fun RecordingStatus(
|
||||
SaveButton(
|
||||
onSave = {
|
||||
runCatching {
|
||||
audioRecorder.stopRecording(context)
|
||||
//audioRecorder.stopRecording(context)
|
||||
}
|
||||
audioRecorder.onRecordingSave()
|
||||
}
|
||||
|
@ -1,32 +1,20 @@
|
||||
package app.myzel394.alibi.ui.models
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.net.Uri
|
||||
import android.os.IBinder
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.lifecycle.ViewModel
|
||||
import app.myzel394.alibi.db.AppSettings
|
||||
import app.myzel394.alibi.db.RecordingInformation
|
||||
import app.myzel394.alibi.enums.RecorderState
|
||||
import app.myzel394.alibi.helpers.AudioBatchesFolder
|
||||
import app.myzel394.alibi.helpers.AudioRecorderExporter
|
||||
import app.myzel394.alibi.helpers.BatchesFolder
|
||||
import app.myzel394.alibi.services.AudioRecorderService
|
||||
import app.myzel394.alibi.services.IntervalRecorderService
|
||||
import app.myzel394.alibi.services.RecorderNotificationHelper
|
||||
import app.myzel394.alibi.services.RecorderService
|
||||
import kotlinx.serialization.json.Json
|
||||
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
||||
|
||||
class AudioRecorderModel :
|
||||
BaseRecorderModel<AudioRecorderService.Settings, RecordingInformation, AudioRecorderService>() {
|
||||
BaseRecorderModel<AudioRecorderService.Settings, RecordingInformation, AudioRecorderService, AudioBatchesFolder?>() {
|
||||
override var batchesFolder: AudioBatchesFolder? = null
|
||||
override val intentClass = AudioRecorderService::class.java
|
||||
|
||||
var amplitudes by mutableStateOf<List<Int>>(emptyList())
|
||||
|
@ -19,9 +19,10 @@ import app.myzel394.alibi.services.AudioRecorderService
|
||||
import app.myzel394.alibi.services.IntervalRecorderService
|
||||
import app.myzel394.alibi.services.RecorderNotificationHelper
|
||||
import app.myzel394.alibi.services.RecorderService
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
abstract class BaseRecorderModel<S : IntervalRecorderService.Settings, I, T : IntervalRecorderService<S, I>> :
|
||||
abstract class BaseRecorderModel<S : IntervalRecorderService.Settings, I, T : IntervalRecorderService<S, I>, B : BatchesFolder?> :
|
||||
ViewModel() {
|
||||
protected abstract val intentClass: Class<T>
|
||||
|
||||
@ -44,7 +45,7 @@ abstract class BaseRecorderModel<S : IntervalRecorderService.Settings, I, T : In
|
||||
|
||||
var onRecordingSave: () -> Unit = {}
|
||||
var onError: () -> Unit = {}
|
||||
var batchesFolder: BatchesFolder? = null
|
||||
abstract var batchesFolder: B
|
||||
|
||||
private var notificationDetails: RecorderNotificationHelper.NotificationDetails? = null
|
||||
|
||||
@ -69,6 +70,8 @@ abstract class BaseRecorderModel<S : IntervalRecorderService.Settings, I, T : In
|
||||
|
||||
if (batchesFolder != null) {
|
||||
recorder.batchesFolder = batchesFolder!!
|
||||
} else {
|
||||
batchesFolder = recorder.batchesFolder as B
|
||||
}
|
||||
|
||||
// Rest should be initialized from the child class
|
||||
@ -123,15 +126,9 @@ abstract class BaseRecorderModel<S : IntervalRecorderService.Settings, I, T : In
|
||||
context.bindService(intent, connection, Context.BIND_AUTO_CREATE)
|
||||
}
|
||||
|
||||
fun stopRecording(context: Context) {
|
||||
runCatching {
|
||||
context.unbindService(connection)
|
||||
}
|
||||
suspend fun stopRecording(context: Context) {
|
||||
recorderService!!.stopRecording()
|
||||
|
||||
val intent = Intent(context, intentClass)
|
||||
context.stopService(intent)
|
||||
|
||||
reset()
|
||||
}
|
||||
|
||||
fun pauseRecording() {
|
||||
|
@ -1,10 +1,12 @@
|
||||
package app.myzel394.alibi.ui.models
|
||||
|
||||
import app.myzel394.alibi.db.RecordingInformation
|
||||
import app.myzel394.alibi.helpers.VideoBatchesFolder
|
||||
import app.myzel394.alibi.services.VideoRecorderService
|
||||
|
||||
class VideoRecorderModel :
|
||||
BaseRecorderModel<VideoRecorderService.Settings, RecordingInformation, VideoRecorderService>() {
|
||||
BaseRecorderModel<VideoRecorderService.Settings, RecordingInformation, VideoRecorderService, VideoBatchesFolder?>() {
|
||||
override var batchesFolder: VideoBatchesFolder? = null
|
||||
override val intentClass = VideoRecorderService::class.java
|
||||
|
||||
override fun onServiceConnected(service: VideoRecorderService) {
|
||||
|
@ -178,7 +178,7 @@ fun AudioRecorderScreen(
|
||||
audioRecorder.onError = {
|
||||
saveAsLastRecording()
|
||||
|
||||
audioRecorder.stopRecording(context)
|
||||
//audioRecorder.stopRecording(context)
|
||||
showRecorderError = true
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
@ -16,6 +17,8 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.myzel394.alibi.db.AppSettings
|
||||
import app.myzel394.alibi.ui.models.VideoRecorderModel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Composable
|
||||
@ -29,6 +32,8 @@ fun POCVideo(
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
@ -38,9 +43,19 @@ fun POCVideo(
|
||||
if (!started) {
|
||||
videoRecorder.startRecording(context, settings)
|
||||
} else {
|
||||
videoRecorder.stopRecording(context)
|
||||
scope.launch {
|
||||
val information = videoRecorder.recorderService!!.getRecordingInformation()
|
||||
val batchesFolder = videoRecorder.batchesFolder!!
|
||||
videoRecorder.stopRecording(context)
|
||||
|
||||
val folder = "content://media/external/video/media/DCIM/Recordings"
|
||||
delay(5000)
|
||||
|
||||
batchesFolder.concatenate(
|
||||
recordingStart = information.recordingStart,
|
||||
extension = information.fileExtension,
|
||||
disableCache = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
started = !started
|
||||
|
Loading…
x
Reference in New Issue
Block a user