mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-11-22 09:04:32 +01:00
FFmpeg-android Timeout Impl
This commit is contained in:
parent
e8cec6d873
commit
6f013d85da
@ -103,7 +103,6 @@ dependencies {
|
|||||||
implementation(project(":common:data-models"))
|
implementation(project(":common:data-models"))
|
||||||
implementation(project(":common:core-components"))
|
implementation(project(":common:core-components"))
|
||||||
implementation(project(":common:providers"))
|
implementation(project(":common:providers"))
|
||||||
implementation(project(":ffmpeg:android-ffmpeg"))
|
|
||||||
|
|
||||||
// Koin
|
// Koin
|
||||||
implementation(Koin.android)
|
implementation(Koin.android)
|
||||||
|
@ -54,12 +54,10 @@ import com.google.accompanist.insets.statusBarsPadding
|
|||||||
import com.shabinder.common.core_components.ConnectionLiveData
|
import com.shabinder.common.core_components.ConnectionLiveData
|
||||||
import com.shabinder.common.core_components.analytics.AnalyticsManager
|
import com.shabinder.common.core_components.analytics.AnalyticsManager
|
||||||
import com.shabinder.common.core_components.file_manager.FileManager
|
import com.shabinder.common.core_components.file_manager.FileManager
|
||||||
import com.shabinder.common.core_components.media_converter.AndroidMediaConverter
|
|
||||||
import com.shabinder.common.core_components.preference_manager.PreferenceManager
|
import com.shabinder.common.core_components.preference_manager.PreferenceManager
|
||||||
import com.shabinder.common.di.observeAsState
|
import com.shabinder.common.di.observeAsState
|
||||||
import com.shabinder.common.models.*
|
import com.shabinder.common.models.*
|
||||||
import com.shabinder.common.models.PlatformActions.Companion.SharedPreferencesKey
|
import com.shabinder.common.models.PlatformActions.Companion.SharedPreferencesKey
|
||||||
import com.shabinder.common.models.event.coroutines.success
|
|
||||||
import com.shabinder.common.providers.FetchPlatformQueryResult
|
import com.shabinder.common.providers.FetchPlatformQueryResult
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot
|
import com.shabinder.common.root.SpotiFlyerRoot
|
||||||
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
||||||
@ -77,7 +75,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
|||||||
import kotlinx.coroutines.flow.conflate
|
import kotlinx.coroutines.flow.conflate
|
||||||
import kotlinx.coroutines.flow.emitAll
|
import kotlinx.coroutines.flow.emitAll
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import nl.bravobit.ffmpeg.*
|
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -108,39 +105,6 @@ class MainActivity : ComponentActivity() {
|
|||||||
// This app draws behind the system bars, so we want to handle fitting system windows
|
// This app draws behind the system bars, so we want to handle fitting system windows
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
rootComponent = spotiFlyerRoot(defaultComponentContext())
|
rootComponent = spotiFlyerRoot(defaultComponentContext())
|
||||||
val ffmpeg = FFmpeg.getInstance(this@MainActivity)
|
|
||||||
val ffprobe = FFprobe.getInstance(this@MainActivity)
|
|
||||||
lifecycleScope.launch {
|
|
||||||
Log.d("FFmpeg", "init")
|
|
||||||
FFmpegConfig.versionFFmpeg(this@MainActivity)
|
|
||||||
FFmpegConfig.codecsFFmpeg(this@MainActivity)
|
|
||||||
FFmpegConfig.versionFFprobe(this@MainActivity)
|
|
||||||
Log.d("FFmpeg Support", ffmpeg.isSupported.toString())
|
|
||||||
val inputFilePath = "/storage/emulated/0/Music/SpotiFlyer/Playlists/Sing-along_Punjabi/Kya_Baat_Ay.mp3"
|
|
||||||
val outputFilePath = "/storage/emulated/0/Music/SpotiFlyer/Playlists/Sing-along_Punjabi/Kya_Baat_Ay.temp.mp3"
|
|
||||||
val kbpsArg = "-b:a 192k"
|
|
||||||
ffmpeg.execute(arrayOf("-i", inputFilePath, "-y", /*"-acodec", "libmp3lame",*/ "-vn", outputFilePath),object : ExecuteBinaryResponseHandler() {
|
|
||||||
override fun onSuccess(message: String?) {
|
|
||||||
Log.d("FFmpeg Command", "Success $message")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onProgress(message: String?) {
|
|
||||||
Log.d("FFmpeg Command", "Progress $message")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(message: String?) {
|
|
||||||
Log.d("FFmpeg Command", "Failed $message")
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
/* AndroidMediaConverter().convertAudioFile("/storage/emulated/0/Music/SpotiFlyer/Playlists/Sing-along_Punjabi/Kya_Baat_Ay.mp3","/storage/emulated/0/Music/SpotiFlyer/Playlists/Sing-along_Punjabi/Kya_Baat_Ay.temp.mp3").fold({
|
|
||||||
Log.d("FFmpeg Success",it)
|
|
||||||
}){
|
|
||||||
it.printStackTrace()
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
/*FFmpeg.testInit()*/
|
|
||||||
setContent {
|
setContent {
|
||||||
SpotiFlyerTheme {
|
SpotiFlyerTheme {
|
||||||
Surface(contentColor = colorOffWhite) {
|
Surface(contentColor = colorOffWhite) {
|
||||||
|
@ -20,8 +20,6 @@ kotlin {
|
|||||||
implementation(Extras.mp3agic)
|
implementation(Extras.mp3agic)
|
||||||
implementation(Extras.Android.countly)
|
implementation(Extras.Android.countly)
|
||||||
implementation(project(":ffmpeg:android-ffmpeg"))
|
implementation(project(":ffmpeg:android-ffmpeg"))
|
||||||
// implementation("com.arthenica:ffmpeg-kit-audio:4.4.LTS")
|
|
||||||
//api(files("$rootDir/libs/mobile-ffmpeg.aar"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
desktopMain {
|
desktopMain {
|
||||||
|
@ -140,19 +140,19 @@ class AndroidFileManager(
|
|||||||
.setId3v2TagsAndSaveFile(trackDetails, trackDetails.outputFilePath)
|
.setId3v2TagsAndSaveFile(trackDetails, trackDetails.outputFilePath)
|
||||||
|
|
||||||
addToLibrary(trackDetails.outputFilePath)
|
addToLibrary(trackDetails.outputFilePath)
|
||||||
File(convertedFilePath).delete()
|
|
||||||
}.fold(
|
}.fold(
|
||||||
success = {},
|
success = {},
|
||||||
failure = {
|
failure = {
|
||||||
throw it
|
throw it
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
File(convertedFilePath).delete()
|
||||||
} else throw e
|
} else throw e
|
||||||
}
|
}
|
||||||
SuspendableEvent.success(trackDetails.outputFilePath)
|
SuspendableEvent.success(trackDetails.outputFilePath)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
//if (songFile.exists()) songFile.delete()
|
if (songFile.exists()) songFile.delete()
|
||||||
logger.e { "${songFile.absolutePath} could not be created" }
|
logger.e { "${songFile.absolutePath} could not be created" }
|
||||||
SuspendableEvent.error(e)
|
SuspendableEvent.error(e)
|
||||||
}
|
}
|
||||||
|
@ -1,48 +1,68 @@
|
|||||||
package com.shabinder.common.core_components.media_converter
|
package com.shabinder.common.core_components.media_converter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
import com.shabinder.common.models.AudioQuality
|
import com.shabinder.common.models.AudioQuality
|
||||||
|
import com.shabinder.common.models.SpotiFlyerException
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import nl.bravobit.ffmpeg.ExecuteBinaryResponseHandler
|
||||||
|
import nl.bravobit.ffmpeg.FFmpeg
|
||||||
import org.koin.dsl.bind
|
import org.koin.dsl.bind
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
|
|
||||||
class AndroidMediaConverter : MediaConverter() {
|
class AndroidMediaConverter(private val appContext: Context) : MediaConverter() {
|
||||||
|
|
||||||
override suspend fun convertAudioFile(
|
override suspend fun convertAudioFile(
|
||||||
inputFilePath: String,
|
inputFilePath: String,
|
||||||
outputFilePath: String,
|
outputFilePath: String,
|
||||||
audioQuality: AudioQuality,
|
audioQuality: AudioQuality,
|
||||||
progressCallbacks: (Long) -> Unit,
|
progressCallbacks: (Long) -> Unit,
|
||||||
) = executeSafelyInPool {
|
) = executeSafelyInPool {
|
||||||
|
var progressing = true
|
||||||
|
var timeout = 600_000L * 2 // 20 min
|
||||||
|
val progressDelayCheck = 500L
|
||||||
// 192 is Default
|
// 192 is Default
|
||||||
val audioBitrate =
|
val audioBitrate =
|
||||||
if (audioQuality == AudioQuality.UNKNOWN) 192 else audioQuality.kbps.toIntOrNull()
|
if (audioQuality == AudioQuality.UNKNOWN) 192 else audioQuality.kbps.toIntOrNull()
|
||||||
?: 192
|
?: 192
|
||||||
|
FFmpeg.getInstance(appContext).execute(
|
||||||
""
|
arrayOf(
|
||||||
//runTranscode(inputFilePath,outputFilePath,audioBitrate).toString()
|
"-i",
|
||||||
/*val kbpsArg = if (audioQuality == AudioQuality.UNKNOWN) {
|
inputFilePath,
|
||||||
val mediaInformation = FFprobeKit.getMediaInformation(inputFilePath)
|
"-y", /*"-acodec", "libmp3lame",*/
|
||||||
val bitrate = ((mediaInformation.mediaInformation.bitrate).toFloat()/1000).roundToInt()
|
"-b:a",
|
||||||
Log.d("MEDIA-INPUT Bit", bitrate.toString())
|
"${audioBitrate}k",
|
||||||
"-b:a ${bitrate}k"
|
"-vn",
|
||||||
} else "-b:a ${audioQuality.kbps}k"
|
|
||||||
// -acodec libmp3lame
|
|
||||||
val session = FFmpegKit.execute(
|
|
||||||
"-i $inputFilePath -y $kbpsArg -acodec libmp3lame -vn $outputFilePath"
|
|
||||||
)
|
|
||||||
|
|
||||||
when (session.returnCode.value) {
|
|
||||||
ReturnCode.SUCCESS -> {
|
|
||||||
//FFMPEG task Completed
|
|
||||||
outputFilePath
|
outputFilePath
|
||||||
|
), object : ExecuteBinaryResponseHandler() {
|
||||||
|
override fun onSuccess(message: String?) {
|
||||||
|
//Log.d("FFmpeg Command", "Success $message")
|
||||||
|
progressing = false
|
||||||
}
|
}
|
||||||
ReturnCode.CANCEL -> {
|
|
||||||
throw SpotiFlyerException.MP3ConversionFailed("FFmpeg Conversion Canceled for $inputFilePath")
|
override fun onProgress(message: String?) {
|
||||||
|
super.onProgress(message)
|
||||||
|
Log.d("FFmpeg Progress", "Progress $message --- $inputFilePath")
|
||||||
}
|
}
|
||||||
else -> throw SpotiFlyerException.MP3ConversionFailed("FFmpeg Conversion Failed for $inputFilePath")
|
|
||||||
}*/
|
override fun onFailure(message: String?) {
|
||||||
|
Log.d("FFmpeg Command", "Failed $message")
|
||||||
|
progressing = false
|
||||||
|
throw SpotiFlyerException.MP3ConversionFailed(message = "Android FFmpeg Failed: $message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
while (progressing) {
|
||||||
|
if (timeout < 0) throw SpotiFlyerException.MP3ConversionFailed("Conversion Timeout for $inputFilePath")
|
||||||
|
delay(progressDelayCheck)
|
||||||
|
timeout -= progressDelayCheck
|
||||||
|
}
|
||||||
|
// Return output file path after successful conversion
|
||||||
|
outputFilePath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal actual fun mediaConverterModule() = module {
|
internal actual fun mediaConverterModule() = module {
|
||||||
single { AndroidMediaConverter() } bind MediaConverter::class
|
single { AndroidMediaConverter(get()) } bind MediaConverter::class
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user