mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-18 14:55:26 +02:00
feat: Add custom date file format support
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
This commit is contained in:
parent
ee4529a9dc
commit
8fcd5ca487
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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<RecordingInformation, AudioBatchesFolder>() {
|
||||
@ -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,
|
||||
)
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user