ryanheise / just_audio

Audio Player
1.03k stars 655 forks source link

Can't play short (sub-second) audio files if play() is called a while (1 or 2 seconds) after initialize() #298

Open llucax opened 3 years ago

llucax commented 3 years ago

Which API doesn't behave as documented, and how does it misbehave?

I can't play a short audio file (0.2 seconds) if I call play 2 or more seconds after the initialization (loading) is done. If I use longer audio files, it works, if I play them right after initialization, it works.

Minimal reproduction project

Because this is the same bug found in video_player (although it was rejected there because it doesn't officially support playing audio), I will include the same example as for video_player so it can be easily compared, in case it provides any extra information. I guess this is a bug in ExoPlayer, which AFAIK is used by both as the backend for Android. But I will also provide a fork of the example:

Test case based on the video_player issue:

Click to expand
  1. Run `flutter create bug2`.
  2. Add `just_audio: ^0.6.12` to the `dependencies:` in `pubspec.yaml`.
  3. Replace `lib/main.dart` with this:
      ```dart import 'package:flutter/material.dart'; import 'package:just_audio/just_audio.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State { final _controller = AudioPlayer(); @override void initState() { super.initState(); print('initialize()'); final initFuture = _controller.setUrl( // 5 seconds audio 'https://soundbible.com/grab.php?id=1634&type=mp3', // 0.2 seconds audio // 'https://soundbible.com/grab.php?id=2067&type=mp3', ); // Start playing if this is the first media initFuture.then((_) { print('initialize() DONE, refreshing UI'); setState(() {}); // so the player is shown final delay = 2; print('scheduling play() in $delay seconds'); Future.delayed(Duration(seconds: delay), () { print('play()'); setState(() {}); _controller.play().then((_) { print('play() future DONE'); setState(() {}); }); }); }); } @override void dispose() { print('dispose()'); _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.play_arrow), onPressed: () {}, ), body: Center( child: _controller.processingState == ProcessingState.ready ? const Text('WAITING') : _controller.playing ? const Text('PLAYING') : const Text('LOADING'), ), ); } } ```

Fork: https://github.com/llucax/just_audio_bug_1.

To Reproduce (i.e. user steps, not code)

Steps to reproduce the behavior:

  1. Test case based on the video_player issue

    1. Run the app
    2. Wait 2 seconds for the sound
    3. No sound
  2. Fork

    1. Run the app
    2. Wait 2 (or more) seconds after initialization (if you press play right after the play button appears, it works!)
    3. Press Play
    4. No sound

~Error messages~

Expected behavior The short audio should play.

~Screenshots~

Desktop (please complete the following information):

Smartphone (please complete the following information):

Flutter SDK version

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, 1.26.0-17.3.pre, on Linux, locale en_IE.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
[✓] Chrome - develop for the web
[✓] Android Studio
[✓] Connected device (2 available)

• No issues found!
Detailed (`flutter doctor -v`) ``` [✓] Flutter (Channel beta, 1.26.0-17.3.pre, on Linux, locale en_IE.UTF-8) • Flutter version 1.26.0-17.3.pre at /home/luca/software/flutter • Framework revision 4b50ca7f7f (4 days ago), 2021-02-04 19:44:27 -0800 • Engine revision 2c527d6c7e • Dart version 2.12.0 (build 2.12.0-259.8.beta) [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2) • Android SDK at /home/luca/Android/Sdk • Platform android-30, build-tools 30.0.2 • Java binary at: /home/luca/software/android-studio/jre/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593) • All Android licenses accepted. [✓] Chrome - develop for the web • CHROME_EXECUTABLE = chromium [✓] Android Studio • Android Studio at /home/luca/software/android-studio • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • android-studio-dir = /home/luca/software/android-studio • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593) [✓] Connected device (2 available) • LG H870 (mobile) • LGH8701d9f7a4 • android-arm64 • Android 9 (API 28) • Chrome (web) • chrome • web-javascript • Chromium 83.0.4103.116 built on Debian bullseye/sid, running on Debian bullseye/sid • No issues found! ```

Additional context

I investigated this issue quite a bit and all I can think of is this is a bug in ExoPlayer, because the same happens using the video_player package too and it only happens on Android (not in web at least, I never tried with iOS or any other platform).

Some other interesting information:

Logs:

All for the forked example and the flutter run command, not including the building process

Successful play ``` Launching lib/main.dart on LG H870 in debug mode... Running Gradle task 'assembleDebug'... Running Gradle task 'assembleDebug'... Done 4.9s ✓ Built build/app/outputs/flutter-apk/app-debug.apk. Syncing files to device LG H870... 136ms Flutter run key commands. r Hot reload. 🔥🔥🔥 R Hot restart. h Repeat this help message. d Detach (terminate "flutter run" but leave application running). c Clear the screen q Quit (terminate the application on the device). An Observatory debugger and profiler on LG H870 is available at: http://127.0.0.1:34135/N-XzSYfI25Y=/ Flutter DevTools, a Flutter debugger and profiler, on LG H870 is available at: http://127.0.0.1:9102?uri=http%3A%2F%2F127.0.0.1%3A34135%2FN-XzSYfI25Y%3D%2F Running with unsound null safety For more information see https://dart.dev/null-safety/unsound-null-safety W/t_audio_exampl(30046): Accessing hidden method Landroid/media/AudioTrack;->getLatency()I (light greylist, reflection) I/ExoPlayerImpl(30046): Init e3c2366 [ExoPlayerLib/2.12.2] [lucye, LG-H870, LGE, 28] D/AudioManager(30046): getStreamVolume() streamType= 3 Request Package= com.ryanheise.just_audio_example I/ViewRootImpl(30046): ViewRoot's Touch Event : ACTION_DOWN I/ViewRootImpl(30046): ViewRoot's Touch Event : ACTION_UP W/AudioCapabilities(30046): Unsupported mime audio/lg-ac3 W/AudioCapabilities(30046): Unsupported mime audio/adpcm W/AudioCapabilities(30046): Unsupported mime audio/x-lg-alac W/AudioCapabilities(30046): Unsupported mime audio/lg-eac3 W/AudioCapabilities(30046): Unsupported mime audio/x-lg-flac W/AudioCapabilities(30046): Unsupported mime audio/g726 W/AudioCapabilities(30046): Unsupported mime audio/x-lg-ms-wma W/AudioCapabilities(30046): Unsupported mime audio/lg-wma-voice W/AudioCapabilities(30046): Unsupported mime audio/x-lg-flac W/VideoCapabilities(30046): Unsupported mime video/dolby-vision W/VideoCapabilities(30046): Unsupported mime video/dolby-vision W/VideoCapabilities(30046): Unrecognized profile 4 for video/hevc W/VideoCapabilities(30046): Unsupported mime video/mjpg W/VideoCapabilities(30046): Unsupported mime video/theora I/VideoCapabilities(30046): Unsupported profile 4 for video/mp4v-es D/MediaCodec(30046): CreateByComponentName name=OMX.google.mp3.decoder D/MediaCodec(30046): Mediacodec create pid=30046 D/MediaCodec(30046): init()++ name=OMX.google.mp3.decoder,nameIsType=0 V/LGCodecAdapter(30046): LG Codec Adapter start V/LGCodecAdapter(30046): load libLGCodecOSAL library V/LGCodecOSAL(30046): Just Validatation check function I/ACodec (30046): Now uninitialized D/MediaCodec(30046): kWhatInit received I/ACodec (30046): onAllocateComponent I/OMXClient(30046): IOmx service obtained D/MediaCodec(30046): onComponentAllocated() componentName=OMX.google.mp3.decoder I/ACodec (30046): [OMX.google.mp3.decoder] Now Loaded D/MediaCodec(30046): kWhatComponentAllocated received D/MediaCodec(30046): init()-- D/MediaCodec(30046): kWhatConfigure received V/LGCodecAdapter(30046): called getLGCodecSpecificData V/LGCodecOSAL(30046): Called LGgetCodecSpecificDataMSG I/ACodec (30046): codec does not support config priority (err -2147483648) V/LGCodecOSAL(30046): Called LGconfigureCodecMSG V/LGCodecOSAL(30046): Not support LGCodec I/ACodec (30046): codec does not support config priority (err -2147483648) I/ACodec (30046): codec does not support config operating rate (err -2147483648) W/ExtendedACodec(30046): Failed to get extension for extradata parameter D/MediaCodec(30046): onComponentConfigured() D/MediaCodec(30046): kWhatComponentConfigured received D/MediaCodec(30046): start() D/MediaCodec(30046): kWhatStart received I/ACodec (30046): [OMX.google.mp3.decoder] Now Idle->Executing I/ACodec (30046): [OMX.google.mp3.decoder] Now Executing W/t_audio_exampl(30046): Accessing hidden method Landroid/media/AudioTrack$Builder;->setOffloadedPlayback(Z)Landroid/media/AudioTrack$Builder; (dark greylist, linking) W/t_audio_exampl(30046): Accessing hidden method Landroid/media/AudioTrack$Builder;->setOffloadedPlayback(Z)Landroid/media/AudioTrack$Builder; (dark greylist, linking) V/AudioSystem(30046): ioConfigChanged() event 0 V/AudioTrack(30046): getMinFrameCount=3844: afFrameCount=1920, afSampleRate=48000, afLatency=80 V/AudioSystem(30046): ioConfigChanged() event 0 V/AudioSystem(30046): ioConfigChanged() event 0 V/AudioTrack(30046): set(): streamType -1, sampleRate 48000, format 0x1, channelMask 0x3, frameCount 15376, flags #0, notificationFrames 0, sessionId 0, transferType 3, uid -1, pid -1 V/AudioTrack(30046): Building AudioTrack with attributes: usage=1 content=1 flags=0x0 tags=[] I/ViewRootImpl(30046): ViewRoot's Touch Event : ACTION_DOWN I/ViewRootImpl(30046): ViewRoot's Touch Event : ACTION_UP ```
Unsuccessful play ``` Launching lib/main.dart on LG H870 in debug mode... Running Gradle task 'assembleDebug'... Running Gradle task 'assembleDebug'... Done 5.6s ✓ Built build/app/outputs/flutter-apk/app-debug.apk. Syncing files to device LG H870... 245ms Flutter run key commands. r Hot reload. 🔥🔥🔥 R Hot restart. h Repeat this help message. d Detach (terminate "flutter run" but leave application running). c Clear the screen q Quit (terminate the application on the device). An Observatory debugger and profiler on LG H870 is available at: http://127.0.0.1:34629/uSwF0DRTfv8=/ Flutter DevTools, a Flutter debugger and profiler, on LG H870 is available at: http://127.0.0.1:9102?uri=http%3A%2F%2F127.0.0.1%3A34629%2FuSwF0DRTfv8%3D%2F Running with unsound null safety For more information see https://dart.dev/null-safety/unsound-null-safety W/t_audio_exampl(29840): Accessing hidden method Landroid/media/AudioTrack;->getLatency()I (light greylist, reflection) I/ExoPlayerImpl(29840): Init e3c2366 [ExoPlayerLib/2.12.2] [lucye, LG-H870, LGE, 28] D/AudioManager(29840): getStreamVolume() streamType= 3 Request Package= com.ryanheise.just_audio_example W/AudioCapabilities(29840): Unsupported mime audio/lg-ac3 W/AudioCapabilities(29840): Unsupported mime audio/adpcm W/AudioCapabilities(29840): Unsupported mime audio/x-lg-alac W/AudioCapabilities(29840): Unsupported mime audio/lg-eac3 W/AudioCapabilities(29840): Unsupported mime audio/x-lg-flac W/AudioCapabilities(29840): Unsupported mime audio/g726 W/AudioCapabilities(29840): Unsupported mime audio/x-lg-ms-wma W/AudioCapabilities(29840): Unsupported mime audio/lg-wma-voice W/AudioCapabilities(29840): Unsupported mime audio/x-lg-flac W/VideoCapabilities(29840): Unsupported mime video/dolby-vision W/VideoCapabilities(29840): Unsupported mime video/dolby-vision W/VideoCapabilities(29840): Unrecognized profile 4 for video/hevc W/VideoCapabilities(29840): Unsupported mime video/mjpg W/VideoCapabilities(29840): Unsupported mime video/theora I/VideoCapabilities(29840): Unsupported profile 4 for video/mp4v-es D/MediaCodec(29840): CreateByComponentName name=OMX.google.mp3.decoder D/MediaCodec(29840): Mediacodec create pid=29840 D/MediaCodec(29840): init()++ name=OMX.google.mp3.decoder,nameIsType=0 V/LGCodecAdapter(29840): LG Codec Adapter start V/LGCodecAdapter(29840): load libLGCodecOSAL library V/LGCodecOSAL(29840): Just Validatation check function I/ACodec (29840): Now uninitialized D/MediaCodec(29840): kWhatInit received I/ACodec (29840): onAllocateComponent I/OMXClient(29840): IOmx service obtained D/MediaCodec(29840): onComponentAllocated() componentName=OMX.google.mp3.decoder I/ACodec (29840): [OMX.google.mp3.decoder] Now Loaded D/MediaCodec(29840): kWhatComponentAllocated received D/MediaCodec(29840): init()-- D/MediaCodec(29840): kWhatConfigure received V/LGCodecAdapter(29840): called getLGCodecSpecificData V/LGCodecOSAL(29840): Called LGgetCodecSpecificDataMSG I/ACodec (29840): codec does not support config priority (err -2147483648) V/LGCodecOSAL(29840): Called LGconfigureCodecMSG V/LGCodecOSAL(29840): Not support LGCodec I/ACodec (29840): codec does not support config priority (err -2147483648) I/ACodec (29840): codec does not support config operating rate (err -2147483648) W/ExtendedACodec(29840): Failed to get extension for extradata parameter D/MediaCodec(29840): onComponentConfigured() D/MediaCodec(29840): kWhatComponentConfigured received D/MediaCodec(29840): start() D/MediaCodec(29840): kWhatStart received I/ACodec (29840): [OMX.google.mp3.decoder] Now Idle->Executing I/ACodec (29840): [OMX.google.mp3.decoder] Now Executing W/t_audio_exampl(29840): Accessing hidden method Landroid/media/AudioTrack$Builder;->setOffloadedPlayback(Z)Landroid/media/AudioTrack$Builder; (dark greylist, linking) W/t_audio_exampl(29840): Accessing hidden method Landroid/media/AudioTrack$Builder;->setOffloadedPlayback(Z)Landroid/media/AudioTrack$Builder; (dark greylist, linking) V/AudioSystem(29840): ioConfigChanged() event 0 V/AudioSystem(29840): ioConfigChanged() event 0 V/AudioSystem(29840): ioConfigChanged() event 0 V/AudioTrack(29840): getMinFrameCount=3844: afFrameCount=1920, afSampleRate=48000, afLatency=80 V/AudioTrack(29840): set(): streamType -1, sampleRate 48000, format 0x1, channelMask 0x3, frameCount 15376, flags #0, notificationFrames 0, sessionId 0, transferType 3, uid -1, pid -1 V/AudioTrack(29840): Building AudioTrack with attributes: usage=1 content=1 flags=0x0 tags=[] I/ViewRootImpl(29840): ViewRoot's Touch Event : ACTION_DOWN I/ViewRootImpl(29840): ViewRoot's Touch Event : ACTION_UP ```
After I pressing replay (successful play) ``` I/ViewRootImpl(29840): ViewRoot's Touch Event : ACTION_DOWN I/ViewRootImpl(29840): ViewRoot's Touch Event : ACTION_UP D/MediaCodec(29840): kWhatFlush received I/ACodec (29840): [OMX.google.mp3.decoder] ExecutingState flushing now (codec owns 0/4 input, 3/4 output). I/ACodec (29840): [OMX.google.mp3.decoder] Now Flushing D/MediaCodec(29840): onFlushCompleted() I/ACodec (29840): [OMX.google.mp3.decoder] Now Executing D/MediaCodec(29840): kWhatFlushCompleted received V/AudioTrack(29840): ~AudioTrack, releasing session id 769 from 29840 on behalf of 29840 W/MediaAnalyticsItem(29840): Unable to record: [1:audiotrack:0:-1::0:-1:1:0:4:android.media.audiotrack.type=AUDIO_CONTENT_TYPE_SPEECH:android.media.audiotrack.usage=AUDIO_USAGE_MEDIA:android.media.audiotrack.samplerate=48000:android.media.audiotrack.channelmask=3:] [forcenew=0] V/AudioTrack(29840): set(): streamType -1, sampleRate 48000, format 0x1, channelMask 0x3, frameCount 15376, flags #0, notificationFrames 0, sessionId 769, transferType 3, uid -1, pid -1 V/AudioTrack(29840): Building AudioTrack with attributes: usage=1 content=1 flags=0x0 tags=[] ```
ryanheise commented 3 years ago

I agree this is probably an ExoPlayer bug.

llucax commented 3 years ago

I'm trying to play around with ExoPlayer to see if I can reproduce it in "pure" android, but I never developed anything for Android natively, so it might take me a long while to do that (if ever). If I can get any help, it would be greatly appreciated.

ryanheise commented 3 years ago

You could try modifying the demo project:

https://exoplayer.dev/demo-application.html

llucax commented 3 years ago

OK, I I did it.

https://github.com/google/ExoPlayer/issues/8569

Not sure if I should keep this open to remember to bump the ExoPlayer version when it is fixed.

llucax commented 3 years ago

I also find a correlation between the renderedOutputBufferCount reaching 12 (the maximum in this case) as the point where the audio can't be heard anymore. Not sure if that rings any bells...

ryanheise commented 3 years ago

Thanks for that. I'm happy to leave this open until there is either a new version of ExoPlayer or some other information or workaround is available.

nt4f04uNd commented 3 years ago

@ryanheise what about supporting MediaPlayer as backend? (it should work i guess)

llucax commented 3 years ago

Yes, it does. I tried Audioplayers, which uses android media player as backend and it works. Not sure if it's a reason enough to add it as a backend though.

On 9 February 2021 16:09:25 GMT+01:00, nt4f04uNd notifications@github.com wrote:

@ryanheise what about supporting MediaPlayer as backend? (it should work i guess)

-- You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub: https://github.com/ryanheise/just_audio/issues/298#issuecomment-776009377

-- Leandro Lucarella (luca) Sent from my phone. Please excuse my brevity and any typos.

ryanheise commented 3 years ago

just_audio is a federated plugin so it would be possible for someone to create a MediaPlayer-based implementation of just_audio_platform_interface. But note that MediaPlayer doesn't support gapless playback or clipping, so at best a MediaPlayer-based implementation would have gaps and inaccurate clips. That's not a tradeoff I would personally be satisfied so I wouldn't be the one to spearhead that.

So personally I would rather wait for an ExoPlayer-based solution. In the meantime, you might consider the audioplayer or audioplayers plugins which are based on MediaPlayer.