Go to file
Ryan Heise ebc8584b97 Reuse audio source in setClip on iOS 2020-08-01 02:07:09 +10:00
.github Clarify bug report instructions. 2020-07-02 01:53:04 +10:00
android Playists, looping, shuffling for Android and web 2020-07-09 13:27:53 +10:00
darwin/Classes Reuse audio source in setClip on iOS 2020-08-01 02:07:09 +10:00
example Rename audioSources/audioSource to children/child. 2020-07-29 17:02:46 +10:00
ios Reuse audio source in setClip on iOS 2020-08-01 02:07:09 +10:00
lib Rename audioSources/audioSource to children/child. 2020-07-29 17:02:46 +10:00
macos Playlists, looping, shuffling for iOS 2020-07-28 03:54:00 +10:00
test Exoplayer exceptions (#76) 2020-04-20 14:19:43 +10:00
.gitignore Exoplayer exceptions (#76) 2020-04-20 14:19:43 +10:00
.metadata Project template 2019-11-26 01:50:21 +11:00
CHANGELOG.md Version 0.2.2 2020-06-24 23:19:43 +10:00
LICENSE Update Copyright dates 2020-01-02 13:37:22 +11:00
README.md Reformat documentation on streams. 2020-07-29 19:42:41 +10:00
pubspec.lock Android pubspec.lock 2020-07-28 04:29:47 +10:00
pubspec.yaml Playists, looping, shuffling for Android and web 2020-07-09 13:27:53 +10:00

README.md

just_audio

A Flutter plugin to play audio from URLs, files, assets, DASH/HLS streams and playlists. This plugin can be used with audio_service to play audio in the background and control playback from the lock screen, Android notifications, the iOS Control Center, and headset buttons.

Features

Feature Android iOS MacOS Web
read from URL
read from file
read from asset
request headers
DASH (untested) (untested) (untested)
HLS (untested) (untested)
play/pause/stop/seek
set volume (untested)
set speed
clip audio (untested)
playlists (untested)
looping (untested)
shuffle (untested)
compose audio (untested)
gapless playback (untested)
report player errors

This plugin has been tested on Android and Web, and is being made available for testing on iOS and MacOS. Please consider reporting any bugs you encounter here or submitting pull requests here.

Example

Initialisation:

final player = AudioPlayer();
var duration = await player.setUrl('https://foo.com/bar.mp3');

Standard controls:

player.play(); // Usually you don't want to wait for playback to finish.
await player.seek(Duration(seconds: 10));
await player.pause();
await player.stop();

Clipping audio:

await player.setClip(start: Duration(seconds: 10), end: Duration(seconds: 20));
await player.play(); // Waits for playback to finish

Gapless playlists:

await player.load(
  ConcatenatingAudioSource(
    children: [
      AudioSource.uri(Uri.parse("https://example.com/track1.mp3")),
      AudioSource.uri(Uri.parse("https://example.com/track2.mp3")),
      AudioSource.uri(Uri.parse("https://example.com/track3.mp3")),
    ],
  ),
);
// Jump to the beginning of track3.mp3.
player.seek(Duration(milliseconds: 0), index: 2);

Looping and shuffling:

player.setLoopMode(LoopMode.off); // no looping (default)
player.setLoopMode(LoopMode.all); // loop playlist
player.setLoopMode(LoopMode.one); // loop current item
player.setShuffleModeEnabled(true); // shuffle except for current item

Composing audio sources:

player.load(
  // Loop its child 4 times
  LoopingAudioSource(
    count: 4,
    // Play children one after the other
    child: ConcatenatingAudioSource(
      children: [
        // Play a regular media file
        ProgressiveAudioSource(Uri.parse("https://example.com/foo.mp3")),
        // Play a DASH stream
        DashAudioSource(Uri.parse("https://example.com/audio.mdp")),
        // Play an HLS stream
        HlsAudioSource(Uri.parse("https://example.com/audio.m3u8")),
        // Play a segment of the child
        ClippingAudioSource(
          child: ProgressiveAudioSource(Uri.parse("https://w.xyz/p.mp3")),
          start: Duration(seconds: 25),
          end: Duration(seconds: 30),
        ),
      ],
    ),
  ),
);

Releasing resources:

await player.dispose();

Catching player errors:

try {
  await player.setUrl("https://s3.amazonaws.com/404-file.mp3");
} catch (e) {
  print("Error: $e");
}

Listening to state changes:

player.playbackStateStream.listen((state) {
  switch (state) {
    case AudioPlaybackState.none: ...
    case AudioPlaybackState.stopped: ...
    case AudioPlaybackState.paused: ...
    case AudioPlaybackState.playing: ...
    case AudioPlaybackState.connecting: ...
    case AudioPlaybackState.completed: ...
  }
});

// See also:
// - durationStream
// - bufferingStream
// - icyMetadataStream
// - bufferedPositionStream
// - fullPlaybackStateStream
// - playbackEventStream
// - currentIndexStream
// - loopModeStream
// - shuffleModeEnabledStream
// - durationStream

Platform specific configuration

Android

If you wish to connect to non-HTTPS URLS, add the following attribute to the application element of your AndroidManifest.xml file:

    <application ... android:usesCleartextTraffic="true">

iOS

If you wish to connect to non-HTTPS URLS, add the following to your Info.plist file:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSAllowsArbitraryLoadsForMedia</key>
    <true/>
</dict>

By default, iOS will mute your app's audio when your phone is switched to silent mode. Depending on the requirements of your app, you can change the default audio session category using AudioPlayer.setIosCategory. For example, if you are writing a media app, Apple recommends that you set the category to AVAudioSessionCategoryPlayback, which you can achieve by adding the following code to your app's initialisation:

AudioPlayer.setIosCategory(IosCategory.playback);

Note: If your app uses a number of different audio plugins in combination, e.g. for audio recording, or text to speech, or background audio, it is possible that those plugins may internally override the setting you choose here. You may consider asking the developer of each other plugin you use to provide a similar method so that you can configure the same audio session category universally across all plugins you use.

MacOS

To allow your MacOS application to access audio files on the Internet, add the following to your DebugProfile.entitlements and Release.entitlements files:

    <key>com.apple.security.network.client</key>
    <true/>

If you wish to connect to non-HTTPS URLS, add the following to your Info.plist file:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSAllowsArbitraryLoadsForMedia</key>
    <true/>
</dict>