Desktop FFmpeg Handling

This commit is contained in:
shabinder 2021-09-05 18:18:34 +05:30
parent 3a93cd5f91
commit 3f4008e2be
6 changed files with 49 additions and 7 deletions

View File

@ -12,7 +12,7 @@ actual fun Dialog(
content: @Composable () -> Unit
) {
AnimatedVisibility(isVisible) {
androidx.compose.ui.window.v1.Dialog(onDismiss) {
androidx.compose.ui.window.Dialog(onDismiss) {
content()
}
}

View File

@ -19,6 +19,7 @@ package com.shabinder.common.core_components.file_manager
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import co.touchlab.kermit.Kermit
import com.github.kokorin.jaffree.JaffreeException
import com.mpatric.mp3agic.InvalidDataException
import com.mpatric.mp3agic.Mp3File
import com.shabinder.common.core_components.media_converter.MediaConverter
@ -35,6 +36,7 @@ import com.shabinder.common.models.dispatcherIO
import com.shabinder.common.models.event.coroutines.SuspendableEvent
import com.shabinder.common.models.event.coroutines.failure
import com.shabinder.common.models.event.coroutines.map
import com.shabinder.common.models.methods
import com.shabinder.database.Database
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableSharedFlow
@ -152,13 +154,18 @@ class DesktopFileManager(
.setId3v2TagsAndSaveFile(trackDetails, trackDetails.outputFilePath)
addToLibrary(trackDetails.outputFilePath)
}.failure {
throw it
}
}.fold(
success = {},
failure = {
throw it
}
)
File(convertedFilePath).delete()
} else throw e
}
SuspendableEvent.success(trackDetails.outputFilePath)
} catch (e: Throwable) {
if(e is JaffreeException) methods.value.showPopUpMessage("No FFmpeg found at path.")
if (songFile.exists()) songFile.delete()
logger.e { "${songFile.absolutePath} could not be created" }
SuspendableEvent.error(e)

View File

@ -6,6 +6,7 @@ import com.github.kokorin.jaffree.ffmpeg.UrlOutput
import com.shabinder.common.models.AudioQuality
import org.koin.dsl.bind
import org.koin.dsl.module
import kotlin.io.path.Path
class DesktopMediaConverter : MediaConverter() {
@ -15,11 +16,14 @@ class DesktopMediaConverter : MediaConverter() {
audioQuality: AudioQuality,
progressCallbacks: (Long) -> Unit,
) = executeSafelyInPool {
val audioBitrate =
if (audioQuality == AudioQuality.UNKNOWN) 192 else audioQuality.kbps.toIntOrNull()
?: 192
FFmpeg.atPath().run {
addInput(UrlInput.fromUrl(inputFilePath))
setOverwriteOutput(true)
if (audioQuality != AudioQuality.UNKNOWN) {
addArguments("-b:a", "${audioQuality.kbps}k")
addArguments("-b:a", "${audioBitrate}k")
}
addArguments("-acodec", "libmp3lame")
addArgument("-vn")

View File

@ -61,11 +61,26 @@ actual suspend fun downloadTracks(
)
}
is DownloadResult.Success -> { // Todo clear map
fileManager.saveFileWithMetadata(it.byteArray, trackDetails) {}
DownloadProgressFlow.emit(
DownloadProgressFlow.replayCache.getOrElse(
0
) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Downloaded) }
) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Converting) }
)
fileManager.saveFileWithMetadata(it.byteArray, trackDetails).fold(
failure = {
DownloadProgressFlow.emit(
DownloadProgressFlow.replayCache.getOrElse(
0
) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Failed(it)) }
)
},
success = {
DownloadProgressFlow.emit(
DownloadProgressFlow.replayCache.getOrElse(
0
) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Downloaded) }
)
}
)
}
}

View File

@ -44,6 +44,7 @@ kotlin {
implementation(project(":common:compose"))
implementation(project(":common:providers"))
implementation(project(":common:root"))
implementation("com.github.kokorin.jaffree:jaffree:2021.08.16")
// Decompose
implementation(Decompose.decompose)

View File

@ -20,6 +20,7 @@ import androidx.compose.material.Surface
import androidx.compose.ui.Modifier
import androidx.compose.ui.awt.ComposeWindow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
@ -30,6 +31,8 @@ import com.arkivanov.decompose.ExperimentalDecomposeApi
import com.arkivanov.decompose.extensions.compose.jetbrains.lifecycle.LifecycleController
import com.arkivanov.essenty.lifecycle.LifecycleRegistry
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
import com.github.kokorin.jaffree.JaffreeException
import com.github.kokorin.jaffree.ffmpeg.FFmpeg
import com.shabinder.common.di.*
import com.shabinder.common.core_components.analytics.AnalyticsManager
import com.shabinder.common.core_components.file_manager.DownloadProgressFlow
@ -39,6 +42,7 @@ import com.shabinder.common.core_components.utils.isInternetAccessible
import com.shabinder.common.models.Actions
import com.shabinder.common.models.PlatformActions
import com.shabinder.common.models.TrackDetails
import com.shabinder.common.models.methods
import com.shabinder.common.providers.FetchPlatformQueryResult
import com.shabinder.common.root.SpotiFlyerRoot
import com.shabinder.common.translations.Strings
@ -89,10 +93,19 @@ fun main() {
) {
val root: SpotiFlyerRoot = SpotiFlyerRootContent(rootComponent)
showToast = root.callBacks::showToast
// FFmpeg WARNING
try {
FFmpeg.atPath().addArgument("-version").execute();
} catch (e: Exception) {
if (e is JaffreeException) methods.value.showPopUpMessage("WARNING!\nFFmpeg not found at path")
}
}
}
}
}
// Download Tracking for Desktop Apps for Now will be measured using `GitHub Releases`
// https://tooomm.github.io/github-release-stats/?username=Shabinder&repository=SpotiFlyer
}
@ -108,6 +121,8 @@ private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot =
override val analyticsManager: AnalyticsManager = koin.get()
override val preferenceManager: PreferenceManager = koin.get<PreferenceManager>().also {
it.analyticsManager = analyticsManager
// Allow Analytics for Desktop
analyticsManager.giveConsent()
}
override val downloadProgressFlow = DownloadProgressFlow
override val actions: Actions = object : Actions {