Just_audio: Webm not playing on iOS

Created on 5 Nov 2020  Â·  4Comments  Â·  Source: ryanheise/just_audio


Which API doesn't behave as documented, and how does it misbehave?
So my app gets links dynamically, some are _webm_ files from YouTube (I don't know if this matters but when you try to preview the url it forces the download of the file). The name of the file is always _videoplayback_, no extension or nothing.

An example of the url is: https://r1---sn-8vq54voxn25po-cjoz.googlevideo.com/videoplayback?expire=1604559693&ei=7U6jX9m4CaSPxN8PyviTmAQ&ip=31.4.243.97&id=o-ADdpFkAM7rsg_VijJ5hWunLORlKBsLpT_xU2JS16vW44&itag=251&source=youtube&requiressl=yes&mh=Si&mm=31%2C29&mn=sn-8vq54voxn25po-cjoz%2Csn-h5q7dnlk&ms=au%2Crdu&mv=m&mvi=1&pcm2cms=yes&pl=24&initcwndbps=818750&vprv=1&mime=audio%2Fwebm&gir=yes&clen=3422454&dur=200.021&lmt=1599850528510078&mt=1604537912&fvip=1&keepalive=yes&c=WEB&txp=5511222&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRAIgRhFhyxsVHEdiRIAJOtufcOgKfKDTJY3Te__Q6VN1wc4CICaj_i0bTmNsBIpZKe99rHG5ciV2p4GjVEn9bO0zsm17&sig=AOq0QJ8wRAIgFghKnxbY_freCTvMuq1d5ujBiigxh7HH6-rYYRf5RnUCIFotwdQqQM0Z6-tj6QKmkTAvh0Ive5hF0wg8WM_qKYHH

Minimal reproduction project
I've created a function inside the AudioPlayerTask class that fetches the url before playing it:

String _url = myurl;
int _closest = urlTiming;
// Here we get the current mediaItem from the class to update it
trackMetaData = mediaItem;
      // Here I set the url and the duration in the player
      _player.setUrl(_url).then((dur) {
        trackMetaData = trackMetaData.copyWith(
          duration: Duration(milliseconds: _closest),
        );
        // Here I update the mediaItem object
        AudioServiceBackground.setMediaItem(trackMetaData);
        _player.setAutomaticallyWaitsToMinimizeStalling(false);
      });
      // Here I pre-load the audio
      await _player.load(ConcatenatingAudioSource(
        children:
        queue.map((item) => AudioSource.uri(Uri.parse(_url))).toList(),
      ));
      _player.play();
  }

To Reproduce (i.e. user steps, not code)
The user clicks on a button and then it calls onCustomAction that then runs the upper code.

Error messages

[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: PlatformException(abort, Connection aborted, null, null)
[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: PlatformException(abort, Connection aborted, null, null)
flutter: #0      AudioPlayer._load (package:just_audio/just_audio.dart:498:9)
<asynchronous suspension>
#1      AudioPlayer.load (package:just_audio/just_audio.dart:456:30)
#2      AudioPlayerTask.getTrack (package:lainke_music/functions/music.dart:137:21)
<asynchronous suspension>

This upper line makes reference to the .load function I've put in the "minimal reproduction project" part.

#3      AudioPlayerTask.onCustomAction (package:lainke_music/functions/music.dart:85:15)
<asynchronous suspension>

This upper line makes reference to the whole function in the "minimal reproduction project" part.

#4      AudioServiceBackground.run.<anonymous closure> (package:audio_service/audio_service.dart:1319:42)
#5      MethodChannel._handleAsMethodCall (package:flutter/src/services/platform_channel.dart:430:55)
#6      MethodChannel.setMethodCallHandler.<anonymous closure> (package:flutter/src/services/platform_channel.dart:383:34)
#7      _DefaultBinaryMessenger.handlePlatformMessage (package:flutter/src/services/binding.dart:283:33)
#8      BinaryMessages.handlePlatformMessage (package:flutter/src/services/platform_messages.dart:58:29)
#9      _invoke3.<anonymous closure> (dart:ui/hooks.dart:280:15)
#10  <…>
[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: PlatformException(-11828, Cannot Open, null, null)
[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: PlatformException((-11828) Cannot Open, null, null, null)
#0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:582:7)
#1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:159:18)
<asynchronous suspension>
#2      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:332:12)
#3      AudioService.customAction (package:audio_service/audio_service.dart:1064:27)
#4      updateQueue (package:lainke_music/functions/music.dart:351:22)

This upper line makes reference to "onCustomAction" function which calls the function I've put in the "minimal reproduction project" part.

#5      playTrack (package:lainke_music/functions/handlers.dart:32:9)
#6      trackHorizontalList.<anonymous closure>.<anonymous closure> (package:lainke_music/widgets/widgets.dart:72:29)
#7      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:183:24)
#8      TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:598:11)
#9      BaseTapGestureRecognizer._checkUp (package:flutter<…>

Expected behavior
The url should play as it does on Android.

Screenshots
Not necessary.

Smartphone (please complete the following information):

  • Device: iPhone SE – 2nd generation (Simulator) it doesn't work on a real iPhone (6s Plus) either.
  • OS: 14.1 (also on the physical iPhone).

Flutter SDK version

[✓] Flutter (Channel stable, 1.22.3, on Mac OS X 10.15.7 19H2, locale es-ES)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
[✓] Xcode - develop for iOS and macOS (Xcode 12.1)
[!] Android Studio (version 4.1)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.

These both upper lines are a bug as I do have the plugins installed for Android Studio.

[✓] Connected device (1 available)
    ! Error: Apple TV is busy: Waiting for Device. Xcode will continue when Apple TV is finished. (code -10)

This upper line is a bug because I'm also working on an Apple TV app.

! Doctor found issues in 1 category.

Additional context

  • It does work on Android.
  • I can't change the file name.
  • I always know the extension beforehand.
  • I'm using the audio_service plugin as well as the audio_session.
1 backlog bug

All 4 comments

The iOS APIs unfortunately don't support all codecs, particularly ones associated with Google ;-)

I'll leave this issue open, since theoretically this is possible to implement (e.g. OGVKit).

However, in the meantime, you might try requesting the audio from YouTube in a different format (assuming you have a license to use YouTube in this way), or using a server-side solution to transcode audio formats that iOS's libraries don't support.

I am keeping this open for the reason stated above.

youtube webm file using the opus format.
The voice performance of opus is much better than MP3, and the file is half smaller.
It is strongly recommended to support playing OPUS, thank you.


https://github.com/sbooth/SFBAudioEngine
FLAC, Ogg Opus, and MP3 are natively supported by Core Audio, however SFBAudioEngine provides its own encoders and decoders for these formats.


https://github.com/ap4y/OrigamiEngine/blob/0bbdc3c5344b631e039a67a0aff481746e1aded3/OrigamiEngine/Plugins/OpusFileDecoder.m


https://github.com/dooboolab/flutter_sound/search?q=opus&type=code

@zxl777 thank you for the useful link. While this isn't at the top of my priority list, it is helpful to collect useful resources here so that someone can eventually take up the challenge using one of these libraries.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tcerven picture tcerven  Â·  10Comments

ryanheise picture ryanheise  Â·  7Comments

sigjak picture sigjak  Â·  12Comments

slimyTextBox picture slimyTextBox  Â·  3Comments

ryanheise picture ryanheise  Â·  6Comments