ryanheise / just_audio Goto Github PK
View Code? Open in Web Editor NEWAudio Player
Audio Player
automaticallyWaitsToMinimizeStalling
A Boolean value that indicates whether the player should automatically delay playback in order to minimize stalling.
In both iOs and Android, the following line throws an exception:
Unhandled Exception: NoSuchMethodError: The getter 'state' was called on null.
/// The current [AudioPlaybackState].
AudioPlaybackState get playbackState => _audioPlaybackEvent.state;
I took a quick look at the code, but I don't see an obvious reason why _audioPlaybackEvent is null at any point. In either case, the plugin should handle this situation, if it's a valid option, e.g.:
AudioPlaybackState get playbackState => _audioPlaybackEvent?.state;
Any suggestion on how I could play a remote files and store the files in cache for faster playing next time? One option is to use Flutter cache manager to download it too when I play it but this would mean downloading twice i.e one from the remote url (for the audioplayer) and one to store in cache for next time.
How possible is it to play the remote file while caching it for faster playing the next time?
java.lang.NullPointerException: Attempt to invoke interface method 'void io.flutter.plugin.common.EventChannel$EventSink.success(java.lang.Object)' on a null object reference
E/AndroidRuntime(20897): at com.ryanheise.just_audio.AudioPlayer.broadcastPlaybackEvent(AudioPlayer.java:229)
E/AndroidRuntime(20897): at com.ryanheise.just_audio.AudioPlayer.access$300(AudioPlayer.java:32)
E/AndroidRuntime(20897): at com.ryanheise.just_audio.AudioPlayer$1.run(AudioPlayer.java:65)
E/AndroidRuntime(20897): at android.os.Handler.handleCallback(Handler.java:883)
E/AndroidRuntime(20897): at android.os.Handler.dispatchMessage(Handler.java:100)
E/AndroidRuntime(20897): at android.os.Looper.loop(Looper.java:214)
E/AndroidRuntime(20897): at android.app.ActivityThread.main(ActivityThread.java:7356)
E/AndroidRuntime(20897): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(20897): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
E/AndroidRuntime(20897): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
This is possibly related to #34, and I believe a fix would be similar
The glitch on play is a matter of the initial data coming out of MediaExtractor
being a bit funky. I might need to grab the extractors from ExoPlayer.
I have a fix for this issue, but I need my previous pull request approved before I can submit a new one.
this library not working on some devices such as Huawei p30 lite
, samsung j7
, Galexy j3pro
, samsung j5
, Samsung Galaxy J1
, Samsong g7
and not working on Android 9
Possibilty of repeating a song after it's complete? Is it supported or should I use my custom logic for repeating it?
I am running issue where after seeking using the seek
method, the player occasionally gets into a state where it continues looping the same part (of roughly half a second). This behavior remains even after pausing and resuming the stream.
I was not able to replicate this issue with the audio in the example application, but it does seem to occur when I replace the audio in the example with something different, for example this (.m4a, MPEG-4 AAC).
Seeking seems to work fine the first 4-5 times, but any more and it usually gets stuck again.
This is on Android 10, both on an emulator as well as a physical device.
No errors appear to be thrown.
Hi @ryanheise
Can you use exoplayer at android side instead of media player.
Exoplayer is very feature rich.
D/BufferPoolAccessor(21656): bufferpool2 0x700114da20 : 6(49152 size) total buffers - 5(40960 size) used buffers - 1/7 (recycle/alloc) - 10/2983 (fetch/transfer)
D/BufferPoolAccessor(21656): bufferpool2 0x700114da20 : 6(49152 size) total buffers - 5(40960 size) used buffers - 1/7 (recycle/alloc) - 10/3205 (fetch/transfer)
D/CCodecBuffers(21656): [c2.android.aac.decoder#112:1D-Input.Impl[N]] codec released a buffer owned by client (index 3)
D/BufferPoolAccessor(21656): bufferpool2 0x700114da20 : 6(49152 size) total buffers - 5(40960 size) used buffers - 1/7 (recycle/alloc) - 10/3428 (fetch/transfer)
D/BufferPoolAccessor(21656): bufferpool2 0x700114da20 : 6(49152 size) total buffers - 5(40960 size) used buffers - 1/7 (recycle/alloc) - 10/3652 (fetch/transfer)
D/BufferPoolAccessor(21656): bufferpool2 0x700114da20 : 6(49152 size) total buffers - 5(40960 size) used buffers - 1/7 (recycle/alloc) - 10/3875 (fetch/transfer)
D/BufferPoolAccessor(21656): bufferpool2 0x700114da20 : 6(49152 size) total buffers - 5(40960 size) used buffers - 1/7 (recycle/alloc) - 10/4101 (fetch/transfer)
D/BufferPoolAccessor(21656): bufferpool2 0x700114da20 : 6(49152 size) total buffers - 5(40960 size) used buffers - 1/7 (recycle/alloc) - 10/4324 (fetch/transfer)
D/BufferPoolAccessor(21656): bufferpool2 0x700114da20 : 6(49152 size) total buffers - 5(40960 size) used buffers - 1/7 (recycle/alloc) - 10/4542 (fetch/transfer)
D/BufferPoolAccessor(21656): bufferpool2 0x700114da20 : 6(49152 size) total buffers - 5(40960 size) used buffers - 1/7 (recycle/alloc) - 10/4764 (fetch/transfer)
These logs keep getting printed out when testing on my real device (Redmi Note 3). Please do disable these logs.
Have functionality for ConcatenatingMediaSource
as in exoplayer where multiple media sources can be added.
Concatenates multiple MediaSources. The list of MediaSources can be modified during playback. It is valid for the same MediaSource instance to be present more than once in the concatenation. Access to this class is thread-safe.
This means we can setUrl/setFilePath and form even a playlist. i.e loop through queue and add media sources using the ConcatenatingMediaSource
option.
exoplayer sample has implemented the code this way:
ConcatenatingMediaSource concatenatingMediaSource = new ConcatenatingMediaSource();
for (Samples.Sample sample : SAMPLES) {
MediaSource mediaSource = new ExtractorMediaSource.Factory(cacheDataSourceFactory)
.createMediaSource(sample.uri);
concatenatingMediaSource.addMediaSource(mediaSource);
}
player.prepare(concatenatingMediaSource);
player.setPlayWhenReady(true);
sample.uri
is the url/filePath of the media/audio file.
SAMPLES
is the queue.
Hope I have been clear.
The audioplayers plugin had features such as onPlayerCompletion stream listener which would get data when the audio file fully completed playback i.e the entire audio file length was played.
I am migrating from this code setup, so having these streams is necessary.
Not only did audioplayers plugin have AudioPlaybackState.COMPLETED but also the audioplayer plugin had it which you are using in audio_service.
Migration from these existing plugins to this just_audio plugin is slightly more difficult due to this.
Hi @ryanheise
The newest version, it's not working fine with type m3u8, but the old version 0.0.2 working well.
Can you help me fix it ?
Auto get duration from audio file is really needed, the seek bar would not show if mediaItem dont have duration data right now. looks like exoplayer have method to get the duration, but I need to learn java first /sad.
Thanks for great work.
Thanks for the project.
Could you please tag your releases on github so that it is possibly to watch the repository for new releases to keep up-to-date with development without having to watch all issues?
Note to self: would like this plugin to work on the web.
Currently, when I feed the plugin a url to an online audio file in opus format, ExoPlayer throws the following exception:
E/ExoPlayerImplInternal(10334): Renderer error: index=1, type=audio, format=Format(1, null, null, audio/opus, null, -1, en, [-1, -1, -1.0], [2, 48000]), rendererSupport=YES
E/ExoPlayerImplInternal(10334): com.google.android.exoplayer2.ExoPlaybackException: android.media.MediaCodec$CodecException: Error 0x80000000
E/ExoPlayerImplInternal(10334): at com.google.android.exoplayer2.BaseRenderer.createRendererException(BaseRenderer.java:359)
E/ExoPlayerImplInternal(10334): at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:723)
E/ExoPlayerImplInternal(10334): at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:599)
E/ExoPlayerImplInternal(10334): at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:329)
E/ExoPlayerImplInternal(10334): at android.os.Handler.dispatchMessage(Handler.java:103)
E/ExoPlayerImplInternal(10334): at android.os.Looper.loop(Looper.java:214)
E/ExoPlayerImplInternal(10334): at android.os.HandlerThread.run(HandlerThread.java:67)
E/ExoPlayerImplInternal(10334): Caused by: android.media.MediaCodec$CodecException: Error 0x80000000
E/ExoPlayerImplInternal(10334): at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
E/ExoPlayerImplInternal(10334): at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:2823)
E/ExoPlayerImplInternal(10334): at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.drainOutputBuffer(MediaCodecRenderer.java:1504)
E/ExoPlayerImplInternal(10334): at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:709)
E/ExoPlayerImplInternal(10334): ... 5 more
I guess this has more something to do with ExoPlayer than just_audio, but the problem I am having is that I seem to have no way of catching this exception.
Is there any way I can handle these cases?
A number of recent issues (#10, #14, #16, and possibly #17) could be addressed by finally switching to ExoPlayer as per the suggestion of @rohansohonee . The reason for not considering it until now was the difficulty of implementing untilPosition
in ExoPlayer, however studying the APIs further, I think this should actually be possible as well.
It will take some time to read through all the documentation, but I plan to focus my attention here for the next while.
Would you consider adding support for reading ogg
files?
Thanks a lot for your package, it is very easy to use.
Note to self: there is a slight lag between the time an event is broadcast from the platform side and the time it is received on the flutter side, which may create surprises for flutter-side state processing. For example, after await setUrl(...)
completes on the flutter side, the state transition to stopped
may lag slightly, and for a brief moment querying player.playbackState
may still report connecting
.
At some point, this code should be improved so that events are categorised into flutter-side initiated events which should update on the flutter side immediately, and asynchronous events which originate on the platform side, such as when buffering is detected, and for which the lag is not a problem.
How possible is it to cancel a loading audio i.e an audio in "AudioPlaybackState.connecting" state as neither dispose or stop work on it as shown on the usage tips in the IDE. So if the audio is still connecting and the user cancels, how can I Stop the loading of this file as right now, it continues loading and plays thereafter.
Some podcast providers (e.g. Soundcloud) provides url to online stream, that is cross-protocol redirected (original url returns 302 response) to audio file. ExoPlayer doesn't follow cross-protocol redirects by default. Since I do not have final url, I can't play this file.
Please add an option to enable cross-protocol redirecting
Thank you
While buffering, the song's current position updates while listening to getPositionStream
stream but with no sound. This causes the UI progress bar to keep updating like the song is playing and the song current time updating without actually any sound. However the preloader shows its buffering. After buffering, it is updated with the current(true) time
Developer ergonomics
As I was switching to use this library, I found myself losing track of PlayerState
(i.e playerState
, playerStateStream
) and PlaybackState
(i.e playbackStateStream
). I couldn't remember which was the enum and which was the class, and had to keep on checking.
I suggest that the core issue is that state is a generic word (as in the phrase, "maintaining app state"), and differentiating is relying on the words "player" and "playback", both of which aren't so strongly associated with the data their representing.
I suggest that the API and docs be updated to use "Status" for the enum, and "Details" for the object.
My reasoning:
That would give us, perhaps
playerDetailsStream
, playbackStatus
, playbackStatusStream
, etc.
Further, I suggest that the split between "player" and "playback" is additionall information which has to be interpreted by the developer, while not adding that much additional clarity. Perhaps the "prefix" should be a standard "audio", giving
audioDetailsStream
, audioStatus
, audioStatusStream
, and class AudioDetails
and enum AudioStatus
.
This is my personal opinion, and this is more of a discussion issue (at this point at least).
If you agree, this is something I could try my hands at making a PR for, although it may be a few days until I can get around to it.
I'm seeing a crash in crashalytics. (I'm also using audio_service)
I notice that the free RAM looks limited. Do you think this is just because my app is currently RAM heavy?
Model: iPhone 6s
Version: 13.3.0 (17C54)
RAM free: 58.27 MB
Crashed: com.apple.main-thread
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000010
-[AudioPlayer broadcastPlaybackEvent]
Crashed: com.apple.main-thread
0 Runner 0x10452d220 -[AudioPlayer broadcastPlaybackEvent] + 118 (AudioPlayer.m:118)
1 AVFoundation 0x1c5f497d8 -[AVPlayerItem _unregisterInvokeAndReleasePendingSeekCompletionHandlerForSeekID:finished:] + 116
2 AVFoundation 0x1c5f5dc24 __avplayeritem_fpItemNotificationCallback_block_invoke + 6380
3 libdispatch.dylib 0x1bbbea610 _dispatch_call_block_and_release + 24
4 libdispatch.dylib 0x1bbbeb184 _dispatch_client_callout + 16
5 libdispatch.dylib 0x1bbb9d190 _dispatch_main_queue_callback_4CF$VARIANT$mp + 1044
6 CoreFoundation 0x1bbe9c5e4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
7 CoreFoundation 0x1bbe975d8 __CFRunLoopRun + 2004
8 CoreFoundation 0x1bbe96adc CFRunLoopRunSpecific + 464
9 GraphicsServices 0x1c5e1c328 GSEventRunModal + 104
10 UIKitCore 0x1bff91ae0 UIApplicationMain + 1936
11 Runner 0x1044d3834 main + 7 (main.m:7)
12 libdyld.dylib 0x1bbd20360 start + 4
What is the minimum version of Android and iOS for this plugin ?
It is working just fine on an Android 7.1.1, but when I test on an Android 5.1.1, it outputs these errors :
I/art (10305): Rejecting re-init on previously-failed class java.lang.Class<com.google.android.exoplayer2.video.MediaCodecVideoRenderer$OnFrameRenderedListenerV23>
I/art (10305): Rejecting re-init on previously-failed class java.lang.Class<com.google.android.exoplayer2.video.MediaCodecVideoRenderer$OnFrameRenderedListenerV23>
I/art (10305): Rejecting re-init on previously-failed class java.lang.Class<com.google.android.exoplayer2.video.MediaCodecVideoRenderer$OnFrameRenderedListenerV23>
I/art (10305): Rejecting re-init on previously-failed class java.lang.Class<com.google.android.exoplayer2.video.MediaCodecVideoRenderer$OnFrameRenderedListenerV23>
I/art (10305): Rejecting re-init on previously-failed class java.lang.Class<com.google.android.exoplayer2.video.MediaCodecVideoRenderer$OnFrameRenderedListenerV23>
I/Choreographer(10305): looper Looper (ChoreographerOwner:Handler, tid 606) {37441f61} hasChoreographer
I/ExoPlayerImpl(10305): Init 2f971a86 [ExoPlayerLib/2.11.1] [L5251, RAINBOW JAM 4G, WIKO, 22]
E/ExoPlayerImplInternal(10305): Source error.
It didn't work either on iOS 9.3.6.
Edit : My bad, I didn't have the WiFi turned on.
Player was using mp4 file from network in a stateful widget, the app crashed with log below after press the back button.
Everything in flutter doctor is OK
Detailed steps:
Following the debug steps, it crashed during the dispose();
Crash Log:
D/NetworkSecurityConfig(15198): No Network Security Config specified, using platform default
I/VideoCapabilities(15198): Unsupported profile 4 for video/mp4v-es
I/OMXClient(15198): IOmx service obtained
I/ACodec (15198): codec does not support config priority (err -2147483648)
D/AudioTrack(15198): getTimestamp_l(27): device stall time corrected using current time 31617190413800
W/AudioTrack(15198): getTimestamp_l(27): retrograde timestamp time corrected, 31617208557400 < 31617212458600
I/ExoPlayerImpl(15198): Release 806d62c [ExoPlayerLib/2.11.1] [generic_x86_arm, sdk_gphone_x86, Google, 29] [goog.exo.core]
I/ExoPlayerImpl(15198): Init 840da8c [ExoPlayerLib/2.11.1] [generic_x86_arm, sdk_gphone_x86, Google, 29]
I/OMXClient(15198): IOmx service obtained
I/ACodec (15198): codec does not support config priority (err -2147483648)
I/ACodec (15198): codec does not support config operating rate (err -2147483648)
D/AudioTrack(15198): getTimestamp_l(28): device stall time corrected using current time 31622562992700
I/ExoPlayerImpl(15198): Release 840da8c [ExoPlayerLib/2.11.1] [generic_x86_arm, sdk_gphone_x86, Google, 29] [goog.exo.core]
D/AndroidRuntime(15198): Shutting down VM
E/AndroidRuntime(15198): FATAL EXCEPTION: main
E/AndroidRuntime(15198): Process: com.cook.maker, PID: 15198
E/AndroidRuntime(15198): java.lang.NullPointerException: Attempt to invoke interface method 'void io.flutter.plugin.common.EventChannel$EventSink.success(java.lang.Object)' on a null object reference
E/AndroidRuntime(15198): at com.ryanheise.just_audio.AudioPlayer.broadcastPlaybackEvent(AudioPlayer.java:229)
E/AndroidRuntime(15198): at com.ryanheise.just_audio.AudioPlayer.access$300(AudioPlayer.java:32)
E/AndroidRuntime(15198): at com.ryanheise.just_audio.AudioPlayer$1.run(AudioPlayer.java:65)
E/AndroidRuntime(15198): at android.os.Handler.handleCallback(Handler.java:907)
E/AndroidRuntime(15198): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(15198): at android.os.Looper.loop(Looper.java:216)
E/AndroidRuntime(15198): at android.app.ActivityThread.main(ActivityThread.java:7506)
E/AndroidRuntime(15198): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(15198): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
E/AndroidRuntime(15198): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:956)
I/Process (15198): Sending signal. PID: 15198 SIG: 9
Android 9. I'm trying to use it to play a web radio endless stream. It seems working until screen goes black for standby.
How can I make the app playing stream also when in standby?
This is a note to self.
In the finally block of the play thread, there is code to seek back to 0. This is a blocking call, but despite being executed in a background thread, it has the effect of blocking the UI thread. This is a mystery because seeking in other circumstances does not block the UI thread. This occurs both when playback naturally reaches the end of the file and also when stop() is explicitly called.
If I cannot work out the cause, it may be easiest to just remove the seek call such that the current position remains at the end of the file after playback completes. The user of the plugin can manually make a call to seek back to the start if they wish. This may be better because seeking on a network stream is slow, and not all use cases would want to perform this expensive seek operation after reaching the end of the file particularly if there is no intention to later continue playing from the start.
Since the migration to exoplayer I think supporting all the various audio file formats should be done.
Currently in my testing I discovered that .flac files do not play.
I had been only testing using .mp3 this whole time.
Hope support for all audio formats can be added in future updates.
Hi @ryanheise
We must rely on using Playlists (ExoPlayer Android
) and AVQueuePlayer (AVPlayer iOS
).
Migrating to this approach will enable easy and straightforward approach for users to handle queue. It will also enable audio looping/repeat mode to get implemented with ease.
And lastly, it should make it way more easier to handle all the exception cases (bufferring/connecting states
).
What are your thought's?
First of all, thank you for making this plugin and audio_service, they're both great!
I'm trying to add support for Icy metadata to the Android version of the plugin, for a personal project. I've got a somewhat working solution here: https://github.com/Jei/just_audio/tree/icy-metadata.
ExoPlayer reads Icy metadata from Icecast/Shoutcast streams by default, so it doesn't require much additional code to make it work. The only problem I'm having is that I've only been able to read the IcyInfo part of the metadata, which includes the title and the URL (if supplied by the server), while I still cannot retrieve the IcyHeaders part, which contains other useful information about the stream (bitrate, genre...). If you have any insight on this issue, it would be appreciated.
I've got a couple of questions:
V/ACodec (23197): [OMX.google.mp3.decoder] calling fillBuffer 5
V/ACodec (23197): [OMX.google.mp3.decoder] onOMXEmptyBufferDone 1
V/ACodec (23197): [OMX.google.mp3.decoder] onOMXFillBufferDone 5 time 104489 us, flags = 0x00000000
V/ACodec (23197): [OMX.google.mp3.decoder] calling fillBuffer 6
V/ACodec (23197): [OMX.google.mp3.decoder] onOMXEmptyBufferDone 2
V/ACodec (23197): [OMX.google.mp3.decoder] onOMXFillBufferDone 6 time 130612 us, flags = 0x00000000
V/ACodec (23197): [OMX.google.mp3.decoder] calling fillBuffer 7
V/ACodec (23197): [OMX.google.mp3.decoder] onOMXEmptyBufferDone 3
V/ACodec (23197): [OMX.google.mp3.decoder] onOMXFillBufferDone 7 time 156734 us, flags = 0x00000000
V/ACodec (23197): [OMX.google.mp3.decoder] calling fillBuffer 8
V/ACodec (23197): [OMX.google.mp3.decoder] calling fillBuffer 5
V/ACodec (23197): [OMX.google.mp3.decoder] onOMXEmptyBufferDone 4
V/ACodec (23197): [OMX.google.mp3.decoder] onOMXFillBufferDone 8 time 182857 us, flags = 0x00000000
V/ACodec (23197): [OMX.google.mp3.decoder] calling fillBuffer 6
V/ACodec (23197): [OMX.google.mp3.decoder] calling fillBuffer 7
V/ACodec (23197): [OMX.google.mp3.decoder] calling fillBuffer 8
These logs keep getting printed out to console when playing audio. Please do disable these logs.
If I start playback from a URL, and then check the playerState.state
while it's playing, it's always AudioPlaybackState.stopped
.
I haven't tested it on Android as I'm using my own audio plugin with queue support for the platform.
First, thank you for the plugin,
I would like to have a possibility to know the exception that happened in expo player, so that I could catch a wrong url or 404 url ... (also related to #29) .
Let me know if PR are welcome (I could help with this), for now I do have two solutions in mind :
.catchError(
) ) of player.setUrl()
thanks
The example android app needs to be updated to use AndroidX or it will not compile.
File: gradle.properties
Add the following:
android.useAndroidX=true
android.enableJetifier=true
Full gradle.properties file:
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
Thanks.
When I start the audio after buffering it plays for several seconds without audio then the timer and seeker reset and start playing with audio
This happen because in android
Player.STATE_READY
is called when the player got the url data and buffered some audio and ready to play
but in iOS AVPlayerItemStatusReadyToPlay
is called when the player got the file data like duration and ready to BUFFER to begin playing when it buffer enough to play
I'm currently working on podcast player so I made a fix for this issue
there is and observer for AVPlayer called 'timeControlStatus' it's available from iOS 10 and above, It return the AVPlayerTimeControlStatus {Paused, WaitingToPlay,Playing}
I'm going to open Pull request with this fix.
I ran into one mp3 file which causes the following exception, when playing on Android:
E/ExoPlayerImplInternal(19071): Source error.
E/ExoPlayerImplInternal(19071): com.google.android.exoplayer2.source.UnrecognizedInputFormatException: None of the available extractors (MatroskaExtractor, FragmentedMp4Extractor, Mp4Extractor, Mp3Extractor, AdtsExtractor, Ac3Extractor, TsExtractor, FlvExtractor, OggExtractor, PsExtractor, WavExtractor, AmrExtractor, Ac4Extractor) could read the stream.
E/ExoPlayerImplInternal(19071): at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractorHolder.selectExtractor(ProgressiveMediaPeriod.java:1095)
E/ExoPlayerImplInternal(19071): at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:974)
E/ExoPlayerImplInternal(19071): at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:391)
E/ExoPlayerImplInternal(19071): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E/ExoPlayerImplInternal(19071): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/ExoPlayerImplInternal(19071): at java.lang.Thread.run(Thread.java:919)
The file actually starts playing and sounds normal. Unfortunately, the audio player becomes unresponsive - all further calls (setting a new file/URL) fail. The audio player appears to be permanently stuck in the .connecting state.
The same file plays with no problems on iPhone. I also ran a check to see if this is a valid mp3 file, and it is.
Any ideas why a file would play normal on iPhone (and in web browsers), but fail on Android?
Is there a way to catch such exceptions?
When i call setUrl method, i have "PlatformException (PlatformException(Error: java.lang.NullPointerException: Attempt to invoke virtual method 'long java.lang.Long.longValue()' on a null object reference"
My player class:
`import 'package:just_audio/just_audio.dart';
class RadioAudioPlayer {
AudioPlayer player;
static final RadioAudioPlayer _instance = RadioAudioPlayer._internal();
factory RadioAudioPlayer() {
return _instance;
}
RadioAudioPlayer._internal();
initialize(){
player = AudioPlayer();
}
playFromUrl(url)async{
await player?.setUrl(url);
player?.play();
}
stop() async {
await player?.stop();
}
}`
The comments in the plugin say: "It is legal to invoke this method only from the following states:"
Is this a target platform limitation? All platforms or only one/some?
In either case, the plugin can handle some of these transitions more gracefully. For example, if .stop() is called when a state is AudioPlaybackState.buffering, a plugin can chain "pause" and "stop" calls (for both or one of the platforms where this is an issue), instead of throwing an exception.
@ryanheise I would love to hear your thoughts on that before implementing this logic in my own code. My concern is that the farther away we go from the platform calls, the higher the probability of unpredictable behavior (e.g. stop() called from the app code when a status was AudioPlaybackState.playing, but by the time it reached the platform the status temporarily changed to AudioPlaybackState.buffering, resulting in a failed stop()).
A way to change the playback speed would be great.
This is a much requested feature in my app.
java.lang.IllegalStateException
android.media.MediaExtractor.getSampleTime(Native Method)
com.ryanheise.just_audio.AudioPlayer$PlayThread.run(AudioPlayer.java:458)
Happens when stopping, seeking or playing audio sometimes. The PlayThread is the main cause of this issue.
Some remote audio needs an identification to be played. Could be helpful to have setUrl take http params or create a function that takes an HttpRequest as parameter.
All features mentioned in the README as "untested" for iOS are virtually all implemented, although just not 100% confirmed through testing.
If an untested feature works for you, I would be grateful if you could report that below and I will reflect that in the README.
I just implement this plugin but i don't see function to catch event complete & error when playing audio.
Can you add features to this plugin ?
I am using the existing example but update the audio source to Flutter asset file. I have included the asset in pubspec.yaml
Device: iPhone 11 Pro Max Simulator
Flutter: v1.12.13+hotfix.7-stable
assets:
- assets/audio/sound.mp3
@OverRide
void initState() {
super.initState();
_player = AudioPlayer();
_player.setAsset('assets/audio/sound.mp3');
}
The printed log is following. Noted that 'AVPlayerItemStatusFailed' is NSLog message.
Performing hot restart...
Restarted application in 1,233ms.
AVPlayerItemStatusFailed
The end position fired by "getPositionStream()" exceeds the duration returned by the setUrl/setFile calls.
I/flutter (22305): position: 229886, duration: 229877
It's a very small discrepancy, but it's enough to break the UI code which does not expect a progress value to exceed the maximum value.
The problem is caused by firing position events every 200ms, which means that the last fire is almost guaranteed to be after the recording finished.
It appears that if you finish "// TODO: emit periodically only in playing state.", it may resolve this issue with plenty of other benefits.
This may also be related to #21
NB: As a side-note, you may want to rename .getPositionStream() into positionStream to make it consistent with playbackStateStream.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.