ryanheise / just_audio

Audio Player
1.03k stars 655 forks source link

Webm not playing on iOS #235

Open newdev8 opened 3 years ago

newdev8 commented 3 years ago

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):

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

ryanheise commented 3 years ago

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.

ryanheise commented 3 years ago

I am keeping this open for the reason stated above.

zxl777 commented 3 years ago

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

ryanheise commented 3 years ago

@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.

Coronon commented 2 years ago

Has this been resolved with the recent addition of webm to safari in iOS 15?

zxl777 commented 2 years ago

I now serve different formats of audio for iOS/Android separately.

banool commented 1 year ago

Doesn't seem to work still, at least with webm with the VP9 codec. The same video works on Android though.

GujjuFlutterGuy commented 1 year ago

Any update over .webm it's still not working with only iOS.

ryanheise commented 1 year ago

To those who are asking whether I have implemented this yet, please read my previous comment. It is an open invitation for someone who is sufficiently motivated to have this feature to become a project contributor.

It is not a particularly high priority for me personally, I am happy to just use the codecs that Apple wants me to use. Apple has started to support WebM in small ways in the past couple of years, but as for iPhone, I will leave Apple's decisions up to Apple. This means that content intended for consumption on iPhones will tend to be encoded using codecs that Apple says they officially support.

If someone wants to work around that by putting in the substantial effort to implement the codec manually within just_audio, you are certainly welcome to contribute your efforts back to the project! Although on the other hand, if the audio assets are your own and you exert some control over them, you may want to consider simply re-encoding them for Apple.

narakai commented 8 months ago

any update or work around for this webm?

s20797 commented 7 months ago

anyone find solution?