diff --git a/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt b/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt index 37bb9c7..aa37cdc 100644 --- a/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt +++ b/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt @@ -162,6 +162,7 @@ data class RecordingInformation( val folderPath: String, @Serializable(with = LocalDateTimeSerializer::class) val recordingStart: LocalDateTime, + val batchesAmount: Int, val maxDuration: Long, val intervalDuration: Long, val fileExtension: String, @@ -176,6 +177,21 @@ data class RecordingInformation( .hasRecordingsAvailable() } + fun getStartDateForFilename(filenameFormat: AppSettings.FilenameFormat): LocalDateTime { + return when (filenameFormat) { + AppSettings.FilenameFormat.DATETIME_ABSOLUTE_START -> recordingStart + AppSettings.FilenameFormat.DATETIME_RELATIVE_START -> LocalDateTime.now().minusSeconds( + getFullDuration() / 1000 + ) + } + } + + fun getFullDuration(): Long { + // This is not accurate, since the last batch may be shorter than the others + // but it's good enough + return intervalDuration * batchesAmount - (intervalDuration * 0.5).toLong() + } + enum class Type { AUDIO, VIDEO, diff --git a/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt b/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt index ba394ef..42887aa 100644 --- a/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt +++ b/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt @@ -18,6 +18,7 @@ import androidx.annotation.RequiresApi import androidx.core.net.toUri import androidx.documentfile.provider.DocumentFile import app.myzel394.alibi.db.AppSettings +import app.myzel394.alibi.db.RecordingInformation import app.myzel394.alibi.ui.MEDIA_RECORDINGS_PREFIX import app.myzel394.alibi.ui.RECORDER_INTERNAL_SELECTED_VALUE import app.myzel394.alibi.ui.RECORDER_MEDIA_SELECTED_VALUE @@ -249,19 +250,22 @@ abstract class BatchesFolder( abstract fun cleanup() suspend fun concatenate( - recordingStart: LocalDateTime, - extension: String, + recording: RecordingInformation, + filenameFormat: AppSettings.FilenameFormat, disableCache: Boolean? = null, onNextParameterTry: (String) -> Unit = {}, - durationPerBatchInMilliseconds: Long = 0, onProgress: (Float?) -> Unit = {}, ): String { val disableCache = disableCache ?: (type != BatchType.INTERNAL) - if (!disableCache && checkIfOutputAlreadyExists(recordingStart, extension)) { + if (!disableCache && checkIfOutputAlreadyExists( + recording.recordingStart, + recording.fileExtension + ) + ) { return getOutputFileForFFmpeg( - date = recordingStart, - extension = extension, + date = recording.recordingStart, + extension = recording.fileExtension, ) } @@ -271,34 +275,12 @@ abstract class BatchesFolder( onProgress(null) try { + val fullTime = recording.getFullDuration().toFloat(); val filePaths = getBatchesForFFmpeg() - // Casting here to float so it doesn't need to redo it on every progress update - var fullTime: Float? = null - - runCatching { - // `fullTime` is not accurate as the last batch might be shorter, - // but it's good enough for the progress bar - - // Using the code below results in a nasty bug: - // since we use ffmpeg to extract the duration, the saf parameter is already - // "used up" and we can't use it again for the actual concatenation - // Since an accurate progress bar is less important than speed, - // we currently don't use this code - /* - val lastBatchTime = (FFprobeKit.execute( - "-i ${filePaths.last()} -show_entries format=duration -v quiet -of csv=\"p=0\"", - ).output.toFloat() * 1000).toLong() - fullTime = - ((durationPerBatchInMilliseconds * (filePaths.size - 1)) + lastBatchTime).toFloat() - */ - // We use an approximation for the duration of the batches - fullTime = (durationPerBatchInMilliseconds * filePaths.size).toFloat() - } - val outputFile = getOutputFileForFFmpeg( - date = recordingStart, - extension = extension, + date = recording.getStartDateForFilename(filenameFormat), + extension = recording.fileExtension, ) concatenationFunction( @@ -308,11 +290,7 @@ abstract class BatchesFolder( ) { time -> // The progressbar for the conversion is calculated based on the // current time of the conversion and the total time of the batches. - if (fullTime != null) { - onProgress(time / fullTime!!) - } else { - onProgress(null) - } + onProgress(time / fullTime) }.await() return outputFile } catch (e: MediaConverter.FFmpegException) { diff --git a/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt b/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt index ee39570..ced8302 100644 --- a/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt +++ b/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt @@ -16,9 +16,7 @@ import app.myzel394.alibi.db.RecordingInformation import app.myzel394.alibi.enums.RecorderState import app.myzel394.alibi.helpers.AudioBatchesFolder import app.myzel394.alibi.helpers.BatchesFolder -import app.myzel394.alibi.ui.SUPPORTS_SCOPED_STORAGE import app.myzel394.alibi.ui.utils.MicrophoneInfo -import java.lang.IllegalStateException class AudioRecorderService : IntervalRecorderService() { @@ -304,12 +302,14 @@ class AudioRecorderService : } // ==== Settings ==== - override fun getRecordingInformation() = RecordingInformation( - folderPath = batchesFolder.exportFolderForSettings(), - recordingStart = recordingStart, - maxDuration = settings.maxDuration, - fileExtension = settings.audioRecorderSettings.fileExtension, - intervalDuration = settings.intervalDuration, - type = RecordingInformation.Type.AUDIO, - ) + override fun getRecordingInformation() = + RecordingInformation( + folderPath = batchesFolder.exportFolderForSettings(), + recordingStart = recordingStart, + maxDuration = settings.maxDuration, + batchesAmount = batchesFolder.getBatchesForFFmpeg().size, + fileExtension = settings.audioRecorderSettings.fileExtension, + intervalDuration = settings.intervalDuration, + type = RecordingInformation.Type.AUDIO, + ) } \ No newline at end of file diff --git a/app/src/main/java/app/myzel394/alibi/services/VideoRecorderService.kt b/app/src/main/java/app/myzel394/alibi/services/VideoRecorderService.kt index 4cfc641..4889333 100644 --- a/app/src/main/java/app/myzel394/alibi/services/VideoRecorderService.kt +++ b/app/src/main/java/app/myzel394/alibi/services/VideoRecorderService.kt @@ -304,14 +304,16 @@ class VideoRecorderService : this } - override fun getRecordingInformation(): RecordingInformation = RecordingInformation( - folderPath = batchesFolder.exportFolderForSettings(), - recordingStart = recordingStart, - maxDuration = settings.maxDuration, - fileExtension = settings.videoRecorderSettings.fileExtension, - intervalDuration = settings.intervalDuration, - type = RecordingInformation.Type.VIDEO, - ) + override fun getRecordingInformation() = + RecordingInformation( + folderPath = batchesFolder.exportFolderForSettings(), + recordingStart = recordingStart, + maxDuration = settings.maxDuration, + batchesAmount = batchesFolder.getBatchesForFFmpeg().size, + fileExtension = settings.videoRecorderSettings.fileExtension, + intervalDuration = settings.intervalDuration, + type = RecordingInformation.Type.VIDEO, + ) companion object { const val CAMERA_CLOSE_TIMEOUT = 20000L diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/RecorderEventsHandler.kt b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/RecorderEventsHandler.kt index ce137e9..5040e45 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/RecorderEventsHandler.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/RecorderEventsHandler.kt @@ -162,6 +162,7 @@ fun RecorderEventsHandler( // When recording is loaded from lastRecording ?: settings.lastRecording ?: throw Exception("No recording information available") + val batchesFolder = when (recorder.javaClass) { AudioRecorderModel::class.java -> AudioBatchesFolder.importFromFolder( recording.folderPath, @@ -177,9 +178,8 @@ fun RecorderEventsHandler( } batchesFolder.concatenate( - recording.recordingStart, - recording.fileExtension, - durationPerBatchInMilliseconds = settings.intervalDuration, + recording, + filenameFormat = settings.filenameFormat, onProgress = { percentage -> processingProgress = percentage }