debug: current stand trying to make ffmpeg to work

This commit is contained in:
Myzel394 2023-11-28 18:59:01 +01:00
parent 1eb7a7dd9a
commit fe9d9d7298
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
12 changed files with 80 additions and 69 deletions

View File

@ -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))!!)
}

View File

@ -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)
}
}

View File

@ -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 +

View File

@ -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))!!
)

View File

@ -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)

View File

@ -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

View File

@ -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()
}

View File

@ -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())

View File

@ -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() {

View File

@ -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) {

View File

@ -178,7 +178,7 @@ fun AudioRecorderScreen(
audioRecorder.onError = {
saveAsLastRecording()
audioRecorder.stopRecording(context)
//audioRecorder.stopRecording(context)
showRecorderError = true
}

View File

@ -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