LexiLabs-App / basic

KMP Libraries for images, logging, and sound. Supports Apple, Android, Javascript, Wasm, JVM, Linux, and Windows
https://basic.lexilabs.app/
MIT License
3 stars 0 forks source link

Full audio is not playing from URL #14

Open ziarashid opened 2 weeks ago

ziarashid commented 2 weeks ago

I am trying to play audio from URL but it plays 3 to 4 seconds and stopped. Audio is almost 2 minutes long but it is playing only 3 to 4 seconds. Please let me know where is the issue. Thanks

Following is my Code implementation: try { val audio = Audio(mp3Url, false) audio.play() } catch (e: Exception) { e.printStackTrace() }

robertjamison commented 1 week ago

I'm attempting to recreate the issue now. Which platform did you encounter the issue on? E.g. Android, iOS, JS

ziarashid commented 1 week ago

I'm attempting to recreate the issue now. Which platform did you encounter the issue on? E.g. Android, iOS, JS

Ok Thanks. it is occurring on ios emulator

robertjamison commented 1 week ago

I've been playing around for a few minutes, and from what I can tell, it's because the AVPlayer (which is overkill for audio playback) is running on the main thread. Here's an example of one of the errors I got while tinkering:

[CFNetwork] __delegate_identifier__:Performance Diagnostics__:::____message__:Synchronous URL loading of https://dare.wisc.edu/wp-content/uploads/sites/1051/2008/11/MS072.mp3 should not occur on this application's main thread as it may lead to UI unresponsiveness. Please switch to an asynchronous networking API such as URLSession.

The simple answer is to instead use "stateful" loading of the player. In version 0.1.6, I'm going to add it to the documentation and switch the player to "AVAudioPlayer" to decrease latency and computational requirements.

Here's an example of how you could load a larger audio file in compose without the risk of it playing before fully loaded:

// Other dependencies are omitted for brevity
import app.lexilabs.basic.sound.Audio
import app.lexilabs.basic.sound.AudioState
import app.lexilabs.basic.sound.ExperimentalBasicSound

val audioPlayer = Audio()
val audioState by audioPlayer.audioState.collectAsState()

Button(onClick = {
    audioPlayer.url = "https://dare.wisc.edu/wp-content/uploads/sites/1051/2008/11/MS072.mp3"
    when (audioState) {
        is AudioState.NONE -> audioPlayer.load()
        is AudioState.READY -> audioPlayer.play()
        is AudioState.ERROR -> println((audioState as AudioState.ERROR).message)
        is AudioState.PAUSED -> audioPlayer.play()
        is AudioState.PLAYING -> audioPlayer.pause()
        else -> { /** DO NOTHING **/ }
    }
}) {
    when (audioState) {
        is AudioState.ERROR -> Text("Error")
        AudioState.LOADING -> Text("Loading")
        AudioState.NONE -> Text("None")
        AudioState.READY -> Text("Ready")
        AudioState.PAUSED -> Text("Paused")
        AudioState.PLAYING -> Text("Playing")
    }
}

Please let me know if this works for you.