Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/florent37/Flutter-AssetsAudioPlayer

Play simultaneously music/audio from assets/network/file directly from Flutter, compatible with android / ios / web / macos, displays notifications
https://github.com/florent37/Flutter-AssetsAudioPlayer

android audio audios dart flutter ios java kotlin listen mac macos media mp3 player playlist song songs swift web

Last synced: 3 months ago
JSON representation

Play simultaneously music/audio from assets/network/file directly from Flutter, compatible with android / ios / web / macos, displays notifications

Awesome Lists containing this project

README

        

# ๐ŸŽง assets_audio_player ๐Ÿ”Š

[![pub package](https://img.shields.io/pub/v/assets_audio_player.svg)](https://pub.dartlang.org/packages/assets_audio_player)

Awesome Flutter

[![Codemagic build status](https://api.codemagic.io/apps/5ed8002fe1907b001c67db52/5ed8002fe1907b001c67db51/status_badge.svg)](https://codemagic.io/apps/5ed8002fe1907b001c67db52/5ed8002fe1907b001c67db51/latest_build)
[![CodeFactor](https://www.codefactor.io/repository/github/florent37/flutter-assetsaudioplayer/badge)](https://www.codefactor.io/repository/github/florent37/flutter-assetsaudioplayer)

Play music/audio stored in assets files (simultaneously) directly from Flutter (android / ios / web / macos).

You can also use play audio files from **network** using their url, **radios/livestream** and **local files**

**Notification can be displayed on Android & iOS, and bluetooth actions are handled**

```yaml
flutter:
assets:
- assets/audios/
```

```Dart
AssetsAudioPlayer.newPlayer().open(
Audio("assets/audios/song1.mp3"),
autoStart: true,
showNotification: true,
);
```

[![sample1](./medias/sample1.png)](https://github.com/florent37/Flutter-AssetsAudioPlayer)
[![sample1](./medias/sample2.png)](https://github.com/florent37/Flutter-AssetsAudioPlayer)

# ๐Ÿ“ฅ Import

```yaml
dependencies:
assets_audio_player: ^3.0.8
```

**Works with `flutter: ">=3.3.0"`, be sure to upgrade your sdk**

You like the package ? buy me a kofi :)

Buy Me a Coffee at ko-fi.com



Audio Source
Android
iOS
Web
MacOS




๐Ÿ—„๏ธ Asset file (asset path)
โœ…
โœ…
โœ…
โœ…


๐ŸŒ Network file (url)
โœ…
โœ…
โœ…
โœ…


๐Ÿ“ Local file (path)
โœ…
โœ…
โœ…
โœ…


๐Ÿ“ป Network LiveStream / radio (url)
(Default, HLS, Dash, SmoothStream)
โœ…
โœ…
โœ…
โœ…



Feature
Android
iOS
Web
MacOS




๐ŸŽถ Multiple players
โœ…
โœ…
โœ…
โœ…


๐Ÿ’ฝ Open Playlist
โœ…
โœ…
โœ…
โœ…


๐Ÿ’ฌSystem notification
โœ…
โœ…
๐Ÿšซ
๐Ÿšซ


๐ŸŽง Bluetooth actions
โœ…
โœ…
๐Ÿšซ
๐Ÿšซ


๐Ÿ”• Respect System silent mode
โœ…
โœ…
๐Ÿšซ
๐Ÿšซ


๐Ÿ“ž Pause on phone call
โœ…
โœ…
๐Ÿšซ
๐Ÿšซ



Commands
Android
iOS
Web
MacOS




โ–ถ Play
โœ…
โœ…
โœ…
โœ…


โธ Pause
โœ…
โœ…
โœ…
โœ…


โน Stop
โœ…
โœ…
โœ…
โœ…


โฉ Seek(position)
โœ…
โœ…
โœ…
โœ…


โชโฉ SeekBy(position)
โœ…
โœ…
โœ…
โœ…


โฉ Forward(speed)
โœ…
โœ…
โœ…
โœ…


โช Rewind(speed)
โœ…
โœ…
โœ…
โœ…


โญ Next
โœ…
โœ…
โœ…
โœ…


โฎ Prev
โœ…
โœ…
โœ…
โœ…



Widgets
Android
iOS
Web
MacOS




๐Ÿฆ Audio Widget
โœ…
โœ…
โœ…
โœ…


๐Ÿฆ Widget Builders
โœ…
โœ…
โœ…
โœ…


๐Ÿฆ AudioPlayer Builders Extension
โœ…
โœ…
โœ…
โœ…



Properties
Android
iOS
Web
MacOS




๐Ÿ” Loop
โœ…
โœ…
โœ…
โœ…


๐Ÿ”€ Shuffle
โœ…
โœ…
โœ…
โœ…


๐Ÿ”Š get/set Volume
โœ…
โœ…
โœ…
โœ…


โฉ get/set Play Speed
โœ…
โœ…
โœ…
โœ…


โฉ get/set Pitch
โœ…
๐Ÿšซ
๐Ÿšซ
๐Ÿšซ



Listeners
Android
iOS
Web
MacOS




๐Ÿฆป Listener onReady(completeDuration)
โœ…
โœ…
โœ…
โœ…


๐Ÿฆป Listener currentPosition
โœ…
โœ…
โœ…
โœ…


๐Ÿฆป Listener finished
โœ…
โœ…
โœ…
โœ…


๐Ÿฆป Listener buffering
โœ…
โœ…
โœ…
โœ…


๐Ÿฆป Listener volume
โœ…
โœ…
โœ…
โœ…


๐ŸฆปListener Play Speed
โœ…
โœ…
โœ…
โœ…


๐ŸฆปListener Pitch
โœ…
๐Ÿšซ
๐Ÿšซ
๐Ÿšซ

# ๐Ÿ“ Import assets files

No needed to copy songs to a media cache, with assets_audio_player you can open them directly from the assets.

1. Create an audio directory in your assets (not necessary named "audios")
2. Declare it inside your pubspec.yaml

```yaml
flutter:
assets:
- assets/audios/
```

## ๐Ÿ› ๏ธ Getting Started

```Dart
final assetsAudioPlayer = AssetsAudioPlayer();

assetsAudioPlayer.open(
Audio("assets/audios/song1.mp3"),
);
```

You can also play _network songs_ from _url_

```Dart
final assetsAudioPlayer = AssetsAudioPlayer();

try {
await assetsAudioPlayer.open(
Audio.network("http://www.mysite.com/myMp3file.mp3"),
);
} catch (t) {
//mp3 unreachable
}
```

_LiveStream / Radio_ from _url_

**The main difference with network, if you pause/play, on livestream it will resume to present duration**

```Dart
final assetsAudioPlayer = AssetsAudioPlayer();

try {
await assetsAudioPlayer.open(
Audio.liveStream(MY_LIVESTREAM_URL),
);
} catch (t) {
//stream unreachable
}
```

And play _songs from file_

```Dart
//create a new player
final assetsAudioPlayer = AssetsAudioPlayer();

assetsAudioPlayer.open(
Audio.file(FILE_URI),
);
```

for file uri, please look at https://pub.dev/packages/path_provider

```Dart
assetsAudioPlayer.playOrPause();
assetsAudioPlayer.play();
assetsAudioPlayer.pause();
```

```Dart
assetsAudioPlayer.seek(Duration to);
assetsAudioPlayer.seekBy(Duration by);
```

```Dart
assetsAudioPlayer.forwardRewind(double speed);
//if positive, forward, if negative, rewind
```

```Dart
assetsAudioPlayer.stop();
```

# Notifications

[![notification](./medias/notification_android.png)](https://github.com/florent37/Flutter-AssetsAudioPlayer)

[![notification](./medias/notification_iOS.png)](https://github.com/florent37/Flutter-AssetsAudioPlayer)

on iOS, it will use `MPNowPlayingInfoCenter`

1. Add metas inside your audio

```dart
final audio = Audio.network("/assets/audio/country.mp3",
metas: Metas(
title: "Country",
artist: "Florent Champigny",
album: "CountryAlbum",
image: MetasImage.asset("assets/images/country.jpg"), //can be MetasImage.network
),
);
```

2. open with `showNotification: true`

```dart
_player.open(audio, showNotification: true)
```

## Custom notification

Custom icon (android only)

### By ResourceName

Make sure you added those icons inside your `android/res/drawable` **!!! not on flutter assets !!!!**

```dart
await _assetsAudioPlayer.open(
myAudio,
showNotification: true,
notificationSettings: NotificationSettings(
customStopIcon: AndroidResDrawable(name: "ic_stop_custom"),
customPauseIcon: AndroidResDrawable(name:"ic_pause_custom"),
customPlayIcon: AndroidResDrawable(name:"ic_play_custom"),
customPrevIcon: AndroidResDrawable(name:"ic_prev_custom"),
customNextIcon: AndroidResDrawable(name:"ic_next_custom"),
)

```

And don't forget tell proguard to keep those resources for release mode

(part Keeping Resources)

https://sites.google.com/a/android.com/tools/tech-docs/new-build-system/resource-shrinking

```xml

```

### By Manifest

1. Add your icon into your android's `res` folder (android/app/src/main/res)

2. Reference this icon into your AndroidManifest (android/app/src/main/AndroidManifest.xml)

```xml

```

You can also change actions icons

```

```

## Handle notification click (android)

Add in main

```dart
AssetsAudioPlayer.setupNotificationsOpenAction((notification) {
//custom action
return true; //true : handled, does not notify others listeners
//false : enable others listeners to handle it
});
```

Then if you want a custom action on widget

```dart
AssetsAudioPlayer.addNotificationOpenAction((notification) {
//custom action
return false; //true : handled, does not notify others listeners
//false : enable others listeners to handle it
});
```

## Custom actions

You can enable/disable a notification action

```dart
open(AUDIO,
showNotification: true,
notificationSettings: NotificationSettings(
prevEnabled: false, //disable the previous button

//and have a custom next action (will disable the default action)
customNextAction: (player) {
print("next");
}
)

)
```

## Update audio's metas / notification content

After your audio creation, just call

```dart
audio.updateMetas(
player: _assetsAudioPlayer, //add the player if the audio is actually played
title: "My new title",
artist: "My new artist",
//if I not provide a new album, it keep the old one
image: MetasImage.network(
//my new image url
),
);
```

## Bluetooth Actions

You have to enable notification to make them work

Available remote commands :

- Play / Pause
- Next
- Prev
- Stop

## HeadPhone Strategy

(Only for Android for now)

while opening a song/playlist, add a strategy

```dart
assetsAudioPlayer.open(
...
headPhoneStrategy: HeadPhoneStrategy.pauseOnUnplug,
//headPhoneStrategy: HeadPhoneStrategy.none, //default
//headPhoneStrategy: HeadPhoneStrategy.pauseOnUnplugPlayOnPlug,
)
```

If you want to make it work on bluetooth too, you'll have to add the BLUETOOTH permission inside your AndroidManifest.xml

```xml

```

# โ›“ Play in parallel / simultaneously

You can create new AssetsAudioPlayer using AssetsAudioPlayer.newPlayer(),
which will play songs in a different native Media Player

This will enable to play two songs simultaneously

You can have as many player as you want !

```dart
///play 3 songs in parallel
AssetsAudioPlayer.newPlayer().open(
Audio("assets/audios/song1.mp3")
);
AssetsAudioPlayer.newPlayer().open(
Audio("assets/audios/song2.mp3")
);

//another way, with create, open, play & dispose the player on finish
AssetsAudioPlayer.playAndForget(
Audio("assets/audios/song3.mp3")
);
```

Each player has an unique generated `id`, you can retrieve or create them manually using

```dart
final player = AssetsAudioPlayer.withId(id: "MY_UNIQUE_ID");
```

# ๐Ÿ—„๏ธ Playlist

```Dart
assetsAudioPlayer.open(
Playlist(
audios: [
Audio("assets/audios/song1.mp3"),
Audio("assets/audios/song2.mp3")
]
),
loopMode: LoopMode.playlist //loop the full playlist
);

assetsAudioPlayer.next();
assetsAudioPlayer.prev();
assetsAudioPlayer.playlistPlayAtIndex(1);
```

## Audio Widget

If you want a more flutter way to play audio, try the `AudioWidget` !

[![sample](./medias/audio_widget.gif)](https://github.com/florent37/Flutter-AssetsAudioPlayer)

```dart
//inside a stateful widget

bool _play = false;

@override
Widget build(BuildContext context) {
return AudioWidget.assets(
path: "assets/audios/country.mp3",
play: _play,
child: RaisedButton(
child: Text(
_play ? "pause" : "play",
),
onPressed: () {
setState(() {
_play = !_play;
});
}
),
onReadyToPlay: (duration) {
//onReadyToPlay
},
onPositionChanged: (current, duration) {
//onPositionChanged
},
);
}
```

How to ๐Ÿ›‘ stop ๐Ÿ›‘ the AudioWidget ?

Just remove the Audio from the tree !
Or simply keep `play: false`

## ๐ŸŽง Listeners

All listeners exposes Streams
Using RxDart, AssetsAudioPlayer exposes some listeners as ValueObservable (Observable that provides synchronous access to the last emitted item);

### ๐ŸŽต Current song

```Dart
//The current playing audio, filled with the total song duration
assetsAudioPlayer.current //ValueObservable

//Retrieve directly the current played asset
final PlayingAudio playing = assetsAudioPlayer.current.value;

//Listen to the current playing song
assetsAudioPlayer.current.listen((playingAudio){
final asset = playingAudio.assetAudio;
final songDuration = playingAudio.duration;
})
```

### โŒ› Current song duration

```Dart
//Listen to the current playing song
final duration = assetsAudioPlayer.current.value.duration;
```

### โณ Current position (in seconds)

```Dart
assetsAudioPlayer.currentPosition //ValueObservable

//retrieve directly the current song position
final Duration position = assetsAudioPlayer.currentPosition.value;

return StreamBuilder(
stream: assetsAudioPlayer.currentPosition,
builder: (context, asyncSnapshot) {
final Duration duration = asyncSnapshot.data;
return Text(duration.toString());
}),
```

or use a PlayerBuilder !

```dart
PlayerBuilder.currentPosition(
player: _assetsAudioPlayer,
builder: (context, duration) {
return Text(duration.toString());
}
)
```

or Player Builder Extension

```dart
_assetsAudioPlayer.builderCurrentPosition(
builder: (context, duration) {
return Text(duration.toString());
}
)
```

### โ–ถ IsPlaying

boolean observable representing the current mediaplayer playing state

```Dart
assetsAudioPlayer.isPlaying // ValueObservable

//retrieve directly the current player state
final bool playing = assetsAudioPlayer.isPlaying.value;

//will follow the AssetsAudioPlayer playing state
return StreamBuilder(
stream: assetsAudioPlayer.isPlaying,
builder: (context, asyncSnapshot) {
final bool isPlaying = asyncSnapshot.data;
return Text(isPlaying ? "Pause" : "Play");
}),
```

or use a PlayerBuilder !

```dart
PlayerBuilder.isPlaying(
player: _assetsAudioPlayer,
builder: (context, isPlaying) {
return Text(isPlaying ? "Pause" : "Play");
}
)
```

or Player Builder Extension

```dart
_assetsAudioPlayer.builderIsPlaying(
builder: (context, isPlaying) {
return Text(isPlaying ? "Pause" : "Play");
}
)
```

### ๐Ÿ”Š Volume

Change the volume (between 0.0 & 1.0)

```Dart
assetsAudioPlayer.setVolume(0.5);
```

The media player can follow the system "volume mode" (vibrate, muted, normal)
Simply set the `respectSilentMode` optional parameter as `true`

```dart
_player.open(PLAYABLE, respectSilentMode: true);
```

https://developer.android.com/reference/android/media/AudioManager.html?hl=fr#getRingerMode()

https://developer.apple.com/documentation/avfoundation/avaudiosessioncategorysoloambient

Listen the volume

```dart
return StreamBuilder(
stream: assetsAudioPlayer.volume,
builder: (context, asyncSnapshot) {
final double volume = asyncSnapshot.data;
return Text("volume : $volume");
}),
```

or use a PlayerBuilder !

```dart
PlayerBuilder.volume(
player: _assetsAudioPlayer,
builder: (context, volume) {
return Text("volume : $volume");
}
)
```

### โœ‹ Finished

Called when the current song has finished to play,

it gives the Playing audio that just finished

```Dart
assetsAudioPlayer.playlistAudioFinished //ValueObservable

assetsAudioPlayer.playlistAudioFinished.listen((Playing playing){

})
```

Called when the complete playlist has finished to play

```Dart
assetsAudioPlayer.playlistFinished //ValueObservable

assetsAudioPlayer.playlistFinished.listen((finished){

})
```

### ๐Ÿ” Looping

```Dart
final LoopMode loopMode = assetsAudioPlayer.loop;
// possible values
// LoopMode.none : not looping
// LoopMode.single : looping a single audio
// LoopMode.playlist : looping the fyll playlist

assetsAudioPlayer.setLoopMode(LoopMode.single);

assetsAudioPlayer.loopMode.listen((loopMode){
//listen to loop
})

assetsAudioPlayer.toggleLoop(); //toggle the value of looping
```

### ๐Ÿƒ Play Speed

```Dart
assetsAudioPlayer.setPlaySpeed(1.5);

assetsAudioPlayer.playSpeed.listen((playSpeed){
//listen to playSpeed
})

//change play speed for a particular Audio

Audio audio = Audio.network(
url,
playSpeed: 1.5
);
assetsAudioPlayer.open(audio);
```

### ๐ŸŽ™๏ธ Pitch

```Dart
assetsAudioPlayer.setPitch(1.2);

assetsAudioPlayer.pitch.listen((pitch){
//listen to pitch
})

//change pitch for a particular Audio

Audio audio = Audio.network(
url,
pitch: 1.2
);
assetsAudioPlayer.open(audio);
```

# Error Handling

By default, on playing error, it stop the audio

BUT you can add a custom behavior

```dart
_player.onErrorDo = (handler){
handler.player.stop();
};
```

Open another audio

```dart
_player.onErrorDo = (handler){
handler.player.open(ANOTHER_AUDIO);
};
```

Try to open again on same position

```dart
_player.onErrorDo = (handler){
handler.player.open(
handler.playlist.copyWith(
startIndex: handler.playlistIndex
),
seek: handler.currentPosition
);
};
```

# Network Policies (android/iOS/macOS)

Android only allow HTTPS calls, you will have an error if you're using HTTP,
don't forget to add INTERNET permission and seet `usesCleartextTraffic="true"` in your **AndroidManifest.xml**

```



...

```

iOS only allow HTTPS calls, you will have an error if you're using HTTP,
don't forget to edit your **info.plist** and set `NSAppTransportSecurity` to `NSAllowsArbitraryLoads`

```
NSAppTransportSecurity

NSAllowsArbitraryLoads

```

To enable http calls on macOs, you have to add input/output calls capabilities into `info.plist`

```
NSAppTransportSecurity

NSAllowsArbitraryLoads

UIBackgroundModes

audio
fetch

com.apple.security.network.client

```

and in your

`Runner/DebugProfile.entitlements`

add

```
com.apple.security.network.client

```

Complete `Runner/DebugProfile.entitlements`

```

com.apple.security.app-sandbox

com.apple.security.cs.allow-jit

com.apple.security.network.server

com.apple.security.network.client

```

# ๐ŸŽถ Musics

All musics used in the samples came from https://www.freemusicarchive.org/