Giter VIP home page Giter VIP logo

swiftaudio's Introduction

logo

⚠️ This repo is not actively maintained ⚠️

Please do not use this in production applications. A fork of this package can be found here.

SwiftAudio

Build Status Version codecov License Platform

SwiftAudio is an audio player written in Swift, making it simpler to work with audio playback from streams and files.

Example

To see the audio player in action, run the example project! To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

iOS 10.0+

Installation

CocoaPods

SwiftAudio is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'SwiftAudio', '~> 0.11.2'

Carthage

SwiftAudio supports Carthage. Add this to your Cartfile:

github "jorgenhenrichsen/SwiftAudio" ~> 0.11.2

Then follow the rest of Carthage instructions on adding a framework.

Usage

AudioPlayer

To get started playing some audio:

let player = AudioPlayer()
let audioItem = DefaultAudioItem(audioUrl: "someUrl", sourceType: .stream)
player.load(item: audioItem, playWhenReady: true) // Load the item and start playing when the player is ready.

To listen for events in the AudioPlayer, subscribe to events found in the event property of the AudioPlayer. To subscribe to an event:

class MyCustomViewController: UIViewController {

    let audioPlayer = AudioPlayer()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        audioPlayer.event.stateChange.addListener(self, handleAudioPlayerStateChange)
    }
    
    func handleAudioPlayerStateChange(state: AudioPlayerState) {
        // Handle the event
    }
}

QueuedAudioPlayer

The QueuedAudioPlayer is a subclass of AudioPlayer that maintains a queue of audio tracks.

let player = QueuedAudioPlayer()
let audioItem = DefaultAudioItem(audioUrl: "someUrl", sourceType: .stream)
player.add(item: audioItem, playWhenReady: true) // Since this is the first item, we can supply playWhenReady: true to immedietaly start playing when the item is loaded.

When a track is done playing, the player will load the next track and update the queue, as long as automaticallyPlayNextSong is true (default).

Navigating the queue

All AudioItems are stored in either previousItems or nextItems, which refers to items that come prior to the currentItem and after, respectively. The queue is navigated with:

player.next() // Increments the queue, and loads the next item.
player.previous() // Decrements the queue, and loads the previous item.
player.jumpToItem(atIndex:) // Jumps to a certain item and loads that item.
Manipulating the queue
 player.removeItem(at:) // Remove a specific item from the queue.
 player.removeUpcomingItems() // Remove all items in nextItems.

Configuring the AudioPlayer

Current options for configuring the AudioPlayer:

  • bufferDuration: The amount of seconds to be buffered by the player.
  • timeEventFrequency: How often the player should call the delegate with time progress events.
  • automaticallyWaitsToMinimizeStalling: Indicates whether the player should automatically delay playback in order to minimize stalling.
  • volume
  • isMuted
  • rate
  • audioTimePitchAlgorithm: This value decides the AVAudioTimePitchAlgorithm used for each AudioItem. Implement TimePitching in your AudioItem-subclass to override individually for each AudioItem.

Audio Session

Remember to activate an audio session with an appropriate category for your app. This can be done with AudioSessionController:

try? AudioSessionController.shared.set(category: .playback)
//...
// You should wait with activating the session until you actually start playback of audio.
// This is to avoid interrupting other audio without the need to do it.
try? AudioSessionController.shared.activateSession()

Important: If you want audio to continue playing when the app is inactive, remember to activate background audio: App Settings -> Capabilities -> Background Modes -> Check 'Audio, AirPlay, and Picture in Picture'.

Interruptions

If you are using the AudioSessionController for setting up the audio session, you can use it to handle interruptions too. Implement AudioSessionControllerDelegate and you will be notified by handleInterruption(type: AVAudioSessionInterruptionType). If you are storing progress for playback time on items when the app quits, it can be a good idea to do it on interruptions as well. To disable interruption notifcations set isObservingForInterruptions to false.

Now Playing Info

The AudioPlayer can automatically update nowPlayingInfo for you. This requires automaticallyUpdateNowPlayingInfo to be true (default), and that the AudioItem that is passed in return values for the getters. The AudioPlayer will update: artist, title, album, artwork, elapsed time, duration and rate.

Additional properties for items can be set by accessing the setter of the nowPlayingInforController:

    let player = AudioPlayer()
    player.load(item: someItem)
    player.nowPlayingInfoController.set(keyValue: NowPlayingInfoProperty.isLiveStream(true))

The set(keyValue:) and set(keyValues:) accept both MediaItemProperty and NowPlayingInfoProperty.

The info can be forced to reload/update from the AudioPlayer.

    audioPlayer.loadNowPlayingMetaValues()
    audioPlayer.updateNowPlayingPlaybackValues()

The current info can be cleared with:

    audioPlayer.nowPlayingInfoController.clear()

Remote Commands

To enable remote commands for the player you need to populate the RemoteCommands array for the player:

audioPlayer.remoteCommands = [
    .play,
    .pause,
    .skipForward(intervals: [30]),
    .skipBackward(intervals: [30]),
  ]

These commands will be activated for each AudioItem. If you need some audio items to have different commands, implement RemoteCommandable in a custom AudioItem-subclass. These commands will override the commands found in AudioPlayer.remoteCommands so make sure to supply all commands you need for that particular AudioItem.

Custom handlers for remote commands

To supply custom handlers for your remote commands, just override the handlers contained in the player's RemoteCommandController:

let player = QueuedAudioPlayer()
player.remoteCommandController.handlePlayCommand = { (event) in
    // Handle remote command here.
}

All available overrides can be found by looking at RemoteCommandController.

Start playback from a certain point in time

Make your AudioItem-subclass conform to InitialTiming to be able to start playback from a certain time.

Author

Jørgen Henrichsen

License

SwiftAudio is available under the MIT license. See the LICENSE file for more info.

swiftaudio's People

Contributors

alex601t avatar anharismail avatar cbess avatar dcvz avatar jorgenhenrichsen avatar minhtc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftaudio's Issues

Remove current item?

This is not an issue!

Question: How do i remove the current item (song) that is about to play?

I'm just curious.

Memory Leaks

Hi I've got 2 memory leaks,

Here is what I did:

  • declaring a DefaultAudioItem with .stream
  • passing it to player, player.load(item: audioItem, playWhenReady: true)

when player starts playing, first leaks happens, and a few second later, second one happens.

screen shot 2019-01-21 at 11 16 01 pm
screen shot 2019-01-21 at 11 16 36 pm

how to track milli-seconds elapsed time

currently the player track the state every second of playback, however, I couldn't find a way to track the change every milli-second, so that the playback UI component (slider or UIProgressView for ex.) will update the visual track smoother than a 1 second threshold.

progress bar on MPRemoteCommandCenter (sometime on AudioPlayer.currentTime) still update when player on .loading or .buffering state

Describe the bug
I set my network link conditioner on 3g, when I play a song at music player at the middle of song music player state change to .loading or .buffering and progress bar on music player interface didn't update/moving but progress bar on MPRemoteCommandCenter still updateing the value

update:

it's happend on AudioPlayer.currentTime too, sometime when player still buffer AudioPlayer.currentTime keep updating the value too. For this condition I reproduce it by turn on network link conditioner to very bad network at the first time song is loaded

To Reproduce
set network link conditioner to 3G
edit: try to play network link conditioner from turn off to very bad network when song is playing and buffer position still updating like the example of this video

http://www.mediafire.com/file/hsrcb07siyypbhp/VID20200310132441.mp4/file

IMG20200310135558

in this video I use streaming song from
https://www.eclassical.com/custom/eclassical/files/BIS1447-002-flac_24.flac because the duration of sample song that available on the SwiftAudio example is to short

make sure change network link conditioner to very bad network when song is playing but bufferedPosition still updating their value

Expected behavior
not updating progress bar until player state change to .playing like progress bar on music player

Smartphone (please complete the following information):

  • Device: iPhone 6s
  • OS: iOs 13.1.2
  • Version 0.11.2

Open filename that contains whitespaces

Hi, I'm using this library to open local url but I have a problem when I try to open an url that contains whitespaces in filename.
So, for example, if I try to open a file which name is "example_file.mp3" this audio is successfully opened.
But, if I try to open a file which name is "example file.mp3" an error occurs "The requested URL was not found on this server". I've also tried to replace the name with "example%20file.mp3" but I have the same error.

[Question] Is Remote Notifications actually needed?

I am using SwiftAudio as part of react-native-track-player. I am trying to track down some issues related to the lock screen controls and background loading. doublesymmetry/react-native-track-player#709

So far, I don't think the issue is with SwiftAudio. However, I was looking at differences between SwiftAudio example and react-native-track-player example, and noticed that SwiftAudio has the Remote Notifications background mode enabled.

Is this really necessary?

The SwiftAudio docs say to enable it as part of supporting remote commands.
App Settings -> Capabilites -> Background Modes -> Check 'Remote notifications'

However, all the Apple docs I can find on this setting are referring to a completely different type of notification, related to alerting the app of new content to download.

https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW10

Can you explain, if you have some time? Thanks!

Previous Items appends the last played Item

Hello @jorgenhenrichsen ,
I have a table view with a list of categories. When I'm open any category, I have a list of songs.
I'm adding the list of songs to QueuedAudioPlayer like in 1 number. First time the previous and next are working correctly, but if I'm leaving the current category, going back and trying to open another one, the last played song is added to Previous Items from 0 and one of the current previous items is removed.

  1. try player.add(items: sources, playWhenReady: playWhenReady)
    try player.jumpToItem(atIndex: index)

  2. When I call 1 again, the previous items are appended from 0 the last played items and one of previous are removed

Can you help to fix, please?

Best Regards,
Mike

EXC_BAD_ACCESS

I'm using react-native-track-player, which uses this library for iOS audio playback. I've run into an issue that I can't seem to find the root cause of - my app is crashing when trying to add tracks to it suddenly. When it crashes, I get this error:

Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

The code it's telling me that caused the crash is in NowPlayingInfoCenter.swift:

    public func set(keyValue: NowPlayingInfoKeyValue) {
        _info[keyValue.getKey()] = keyValue.getValue()
        self._infoCenter.nowPlayingInfo = _info
    }

Looking through the trace on the right of Xcode, it looks like the call to update the now playing duration is what's causing this? Would it be possible to guard these functions from setting invalid values?

    public func set(keyValue: NowPlayingInfoKeyValue) {
        let key = try? keyValue.getKey()
        let value = try? keyValue.getValue()
        
        if (key != nil && value != nil) {
            _info[keyValue.getKey()] = keyValue.getValue()
            self._infoCenter.nowPlayingInfo = _info
        }
    }

playing current time and duration get wrong

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
If needed, include code examples for the problem or steps to reproduce.

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Version [e.g. 0.7.0]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6, Simulator iPhone6 ...]
  • OS: [e.g. iOS8.1]
  • Version [e.g. 0.7.0]

Additional context
Add any other context about the problem here.

Is it possible to load song image from a given url?

I want to load the song image from my database.
instead of
DefaultAudioItem(audioUrl: <String>, artist: <String?>, title: <String?>, albumTitle: <String?>, sourceType: <SourceType>, artwork: <UIImage?>)
can I use

`DefaultAudioItem(audioUrl: , artist: <String?>, title: <String?>, albumTitle: <String?>, sourceType: , artwork: <ImageLink?>)

`

The operation couldn’t be completed.

Describe the bug
Cannot play an audio from a url that has a space.

To Reproduce
Add an item.
With no space:
http://website.com/songs/Hanasakam.mp3
IT WORKS
but with spaces:
http://website.com/songs/Adil Hawrami - Krmshan.mp3
As you see, Adil Hawrami - Krmshan.mp3

You get:

The operation couldn’t be completed. (SwiftAudio.APError.LoadError error 0.)

Show audio item image,name and more.

Hi,
I want to show song details when I'm connecting to some Bluetooth device like tv.
How can I do it?
For now, ic can see when I connect to tv just the progress bar and time.

Less constrained RemoteCommandController

Hey!
Right now AudioPlayer asks items for related remote commands or uses those provided when track changes.
I find very useful to have the ability to refresh them later (because of the how backend's API is designed) – unfortunately current API doesn't allow to do that.
Maybe a new function or remoteCommands didSet block?

public var remoteCommands: [RemoteCommand] = [] {
    didSet {
        if let currentItem = currentItem {
            enableRemoteCommands(forItem: currentItem)
        }
    }
}

Player state does not always change to playing

Player state sometimes does not change to playing, even though audio starts and elapsedSecond event emits. It happens randomly, but more often if your network connection is slow. I'm testing on a device using Network Link Conditioner in Settings -> Developer Options to simulate a slow connection.

image

If you look at this log, it shouldn't be possible for player.playerState to be paused while emitting secondElapse (and actually playing):

⌛ stateChange - state: paused
⌛ stateChange - state: loading
⌛ stateChange - state: paused
⌛ secondElapse - currentTime: 0.0 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ secondElapse - currentTime: 0.0 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ secondElapse - currentTime: 0.0 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ updateDuration: 0.3657142857142857
⌛ secondElapse - currentTime: 0.02672804 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ secondElapse - currentTime: 0.026939374 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ updateDuration: 2.36472281
⌛ updateDuration: 7.380233014
⌛ secondElapse - currentTime: 1.000674124 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ updateDuration: 11.403090157
⌛ updateDuration: 16.941049341
⌛ secondElapse - currentTime: 2.000570967 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ updateDuration: 20.467579953
⌛ secondElapse - currentTime: 3.001347996 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ updateDuration: 23.994110565
⌛ updateDuration: 27.520641177
⌛ secondElapse - currentTime: 4.001117254 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ updateDuration: 33.032477912
⌛ updateDuration: 36.559008524
⌛ secondElapse - currentTime: 5.001199992 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ updateDuration: 42.096967708
⌛ secondElapse - currentTime: 6.000966879 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ updateDuration: 46.616151381
⌛ updateDuration: 52.154110565
⌛ secondElapse - currentTime: 7.000541125 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ updateDuration: 55.680641177
⌛ secondElapse - currentTime: 7.856695665 / state: Optional(SwiftAudio.AVPlayerWrapperState.paused)
⌛ updateDuration: 59.20717179

Tested on a device with iOS 13.

Remote commands not enabling as expected

Describe the bug
Let met start by saying I don't do much with Swift; I'm using this library as a part of react-native-track-player.

Our app implements skipBackward and skipForward. Randomly, the iOS lock screen will display the standard rewind button instead of the skip backward button.

I'm led to believe this is some kind of race condition but am not comfortable enough with Swift to confirm.

To Reproduce
This must be tested on a device as iOS simulator does not show media controls.

These steps won't cause the exact scenario I mentioned above, but I believe it's the same bug.

  1. In Example/SwiftAudio/AudioController.swift, add skipBackward and skipForward as remote commands. Use an interval other than 60 seconds, like:
.skipForward(preferredIntervals: [30]),
.skipBackward(preferredIntervals: [30]),
  1. Open RemoteCommandController.swift and make the following change:
     internal func enable(commands: [RemoteCommand]) {
         commands.forEach { (command) in
             self.enable(command: command)
         }
+
+        self.enable(command: RemoteCommand.skipBackward(preferredIntervals: [60]))
+        // usleep(10000)
+        self.enable(command: RemoteCommand.skipForward(preferredIntervals: [60]))
     }

The skipBackward icon should say 60 and the skipForward icon should say 30, even though it should say 60.

  1. Uncomment the added usleep and test again. Both buttons should now say 60. (Obviously usleep is not a solution, it's just the only way I've been able to guarantee the expected behavior in my test.)

Expected behavior
Media controls should display the skipBackward and skipForward icons.

Screenshots
Incorrect behavior:
IMG_2166

Expected behavior:
IMG_2167

Device 1:

  • Device: iPhone 7
  • OS: iOS 13.2 and iOS 13.3

Device 2:

  • Device: iPhone 11 Pro
  • OS: iOS 13.3.1

Jump to Item is not working

I am using this code:

`for i in 0 ..< songInfoArray.count {

let item = songInfoArray[i]

let audio = DefaultAudioItem(audioUrl: item.url artist: item.singerName, title: item.title, albumTitle: item.thumbnail, sourceType: .stream)

 sources.append(audio)

        }`

try? player.add(items: sources, playWhenReady: false)

`if songInfoArray.count > 1 {

 try? player.jumpToItem(atIndex: songInfoArray.count - 1)

}`

**try? player.jumpToItem(atIndex: songInfoArray.count - 1)** is not working

the player always play the songs from the start

Playing local audio file

Hey there.

I'm trying to work with SwiftAudio. I have downloaded a 3MB music using URLSession and i can see it in the simulator folders,

My URL looks something like this:

file:///Users/Adam/Library/Developer/CoreSimulator/Devices/D38BAB08-846E-4172-9DB1-8D3567F6E10E/data/Containers/Data/Application/DE2FF955-B927-4542-A290-4DE550B6C53D/Library/Caches/Digger/mySongByAdam.mp3

Now, using loadItem won't work for me.

Also as mentioned in issue #43 that i SHOULDN'T include my scheme URL, But i do not know how to remove the file:/// or get an appropriate index of the file.

Edit:
Testing it on iPhone X iOS(12.0)
With this file var/mobile/Containers/Data/Application/2BC8BB07-D24C-4625-B2F8-C444F687994D/Library/Caches/Digger/flowerAdam.mp3
Still doesn't work

Logo Design Offering as Open Source Contribution

Hello Sir. I'm a Graphics Designer. I'm happy to see an open source project, So, I want provide a logo for you. Would you mind if I propose a new logo design for your project as my Open Source Contribution?

Thanks for the attention.

The "player.currentTime" value returned is incorrect - more so after a seek.

Describe the bug
When you try and fetch the current time using player.currentTime AFTER having seeked a track; it returns a value that is off by < 1%.

By way of example, I played a track with duration 1700.78, seeked to close to the end of the track right away, and once the track ended it reported a progress time of 1682.39 (so off by around 1.1%)?

I've tested both having done a seek and having not done a seek; and the the currentTime appears to be off by a much greater margin when the user has seeked thru the track previously. The attached screenshots show an example of the reported current time and duration when the same track ends both with and without a seek having occurred.

Without A Seek (Off by < 0.03 of a second)
Screenshot 2019-11-07 at 12 47 02

With A Seek (Off by around 12 seconds / around 1% of the total track time).
Screenshot 2019-11-07 at 12 50 41

The behaviour seems to occur consistently across all the tracks I'm trying to play - which are just regular MP3 files.

To Reproduce
See above.

Expected behavior
The current time to always be reported correctly.

Screenshots
See above.

Desktop (please complete the following information):
Catalina

Smartphone (please complete the following information):

  • Device: iPhone X
  • OS: iOS 13

Using the latest Swift Audio (0.11.1)

Additional context
I think it might have to do with CMTimeMakeWithSeconds in the seek function and/or could be a rounding issue somewhere? Just guesses...

A quick google also brought up this: https://stackoverflow.com/questions/47158688/ios-11-avplayer-mp3-currenttime-not-accurate so might be worth adding [AVURLAssetPreferPreciseDurationAndTimingKey: true] to the AVURLAsset options just in the hope it sorts it out.

Crash in Release mode only

Describe the bug
In debug mode all works like charm, in release the app crashes trying to play audio.

To Reproduce
Install pod, add tracks and run in release mode.

Expected behavior
Always works like in debug.

Desktop (please complete the following information):

  • OS: 10.14.6
  • Version: 0.10.0

Smartphone (please complete the following information):

  • Device: Simulator iPhone11
  • OS: 13.2.1
  • Version 0.10.0

Additional context
I'm developing a react-native app with the react native track player library.
This is the link at the issue.

How to implement Custom DefaultAudioItem with my custom Items?

How to implement Custom DefaultAudioItem with my custom Items.

I want to use more than title and album title I want to implement more than the current implementation

DefaultAudioItem(audioUrl: item.mp3Path.replaceTom3u8(), artist: item.singerName, title: item.title, albumTitle: item.singerName, sourceType: .stream, artwork: image)

How to achieve that?

Move to next song dynamically

How to move to the next song when I add a new song to the array while music is playing behavior like any music player :
Explanation:
The array has 1 item and I am playing that item then I click on another item and I added to the array so the array now has 2 items and I want so the second item starts playing.

iOS 13 won't play next track in Queue Automatic!

Describe the bug
iOS 13 won't play next track in Queue Automatic!

To Reproduce
just create an array with DefaultAudioItem and then playsong.

Expected behavior
after a track ends automatic play next track in queue

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):
iOS
xCode 11-beta7

Smartphone (please complete the following information):
iOS13 beta 8 [Simulator and iPhone 6s real device]

Remote Control: NextTrack and PreviousTrack

How to add NextTrack and PreviousTrack in remote control as if I remove SeekForward and SeekPrevious , it displays the Next and Back Button but are disabled.

Enum has no case for these, So how I can implement it keeping pod attached.

Loading (buffering) state over 3G connection is not triggered when the mp3 file is being loaded

Describe the bug
Loading (buffering) state over 3G connection is not fired when the mp3 file is being loaded. Over Wifi it works OK, I guess because it loads the mp3 file faster.

To Reproduce
Just play an MP3 file over a 3G connection and you will see that the loading state is not triggered until the very end.
Edit:
This only happens the first time you load/play an MP3 file, after stopping the playback and playing it again it triggers the loading state immediately as it should.

Expected behavior
The loading state should be triggered as soon as the MP3 file starts to being loaded. This is useful for people over 3G connections to know that the MP3 is being loaded.

Desktop (please complete the following information):

  • OS: iOS 12.2
  • Version: Latest

Smartphone (please complete the following information):

  • Device: iPhone SE
  • OS: 12.3.1
  • Version: Latest

`player.audioTimePitchAlgorithm = .varispeed` doesn't work

Describe the bug
After I initialize my player, I set player.audioTimePitchAlgorithm = .varispeed, but it doesn't work. (Really, I want Spectral, but varispeed should be really obvious and produce a chipmunk-like sound at 2x, so I'm just using that to try to reproduce the bug. It sounds like it's actually using lowQualityZeroLatency.)

I also tried subclassing AudioItem but that doesn't work either.

To Reproduce
Clone and run this repo. (The main file to look at is here.)

Expected behavior
When you tap "play" and increase the speed to 2x, it should sound like a chipmunk.

Desktop (please complete the following information):

  • OS: macOS
  • Version: 10.15 (Catalina)

Smartphone (please complete the following information):

  • Device: iPhone 8, all iPhones in simulator
  • OS: iOS
  • Version 13.1.3

Player becomes unresponsive after failure to play track.

Describe the bug
After there is a problem playing a track, and the AVPlayer status changes to failed, the player becomes unresponsive and will not play any other track. Every command after reaching this state results in an error.

To Reproduce
I found this error when I was attempting to play a track. I later discovered that there was image metadata in the track. After removing the image metadata, the track does not result in an error.

I cannot post the test file publicly, but I can provide it privately if it helps to debug.

While modifying this audio file fixes the immediate issue, there is still the underlying issue of the player becoming unresponsive after a failure.

Expected behavior
The player should be able to recover after failing to play a track and resume normal operation when attempting to play a different track.

Info:

  • iPhoneX iOS 12.1
  • SwiftAudio Version 0.7.2

Additional context
I am using SwiftAudio as part of react-native-track-player, which is maintained by @dcvz.

However, I have recreated this issue within the SwiftAudio example by replacing one of the example tracks with the track I have been having issues with. The default example track play fine until I try to play the problem track. After that, the example tracks will no longer play.

Suggested Solution
Apple docs say that when AVPlayer status changes to 'failed', the AVPlayer instance can no longer be used and must be replaced with a new instance.
https://developer.apple.com/documentation/avfoundation/avplayer/1388096-status

I tried this, and it seems to resolve the issue. Check out this commit on my fork.

However, I did not create a PR because I am not proficient in swift, and I don't feel I have a good enough grasp on the overall structure of this library in order to implement this fix in the best way possible.

For instance, I don't know if it would be better to do this in response to the failure, or to check before the next action and recreate the instance on demand. Also, I'm not sure if the wrapper should be re-created or just the AVPlayer.

Repeat Audio

Hello thanks for this wonderful library, do you planned to add any repeating features? either repeat one or all audios? If not I would appreciate if you could point me to the right logic to figure it out. Thank you!

Crash on loading items immediately

I've got weird crashes when trying to loading items one after one in .stream sourceType.
I'm using AudioPlayer and not QueuedAudioPlayer

I've checked a few things and it seems the problem is with removing observer and sometimes the AVPlayerItem gets deallocated but the observers for .duration and ```.loadedTimeRanges```` still registered.

Image 1:

Screen Shot 2019-03-16 at 12 27 12 PM

Image 2:

Screen Shot 2019-03-16 at 12 57 18 PM

NOTE

the problem occurred when I've tried to load items immediately one after one.
its ok when I let them to get .ready state before loading another-one.

Caching & More Robust Loading

Wanted to bring this to your attention: https://github.com/neekeetab/CachingPlayerItem

I've done some basic test integrating into the library and it's interesting.

In a library I would expect a track should play ASAP - and caching in queued mode to automatically download the next track when the current one is fully loaded.

This doesn't provide all of that but it has some nice ideas.

[Question] Get total duration

Is it possible to get total duration of a remote audio file?

By using the event updateDuration event the duration is continually updated (I think until everything has been downloaded/buffered?). This makes the knob on a seek bar/scrubber jump around until duration has been determined and are perceived quite buggy and hard to use by our users.

PS. Thanks for an awesome lib! :)

Get Audio Buffering Status

I am looking for a way to get the audio buffering status and/or event. My audio is an URL being pulled. I have set try? controller.player.load(item: item, playWhenReady: false). I want to receive notice that the audio is ready to play. Do you know how I can achieve this?

calling load(item:PlayWhenReady) doesn't trigger play the second time

Calling load(item:playWhenReady:) method will not trigger play method of the wrapper after adding item(s) to the QueuedPlayer, that means when I add items first then play any of them, if we decide to add more items or just load a new item later, the view sometimes freezes and the item is not played.
After some investigation, it turned out to be load(from:, playWhenReady:) method, it must not call avPlayer.replaceCurrentItem(with:) on the main thread, rather, it must be called using asset.loadValuesAsynchronously(forKeys:) method (as detailed in the second answer here).

Add option dictionary to the AVURLAsset.

Is your feature request related to a problem? Please describe.
Add a way to supply option key-values to the AVURLAsset by using init(url:options:).

Describe the solution or feature you would like
Should be able to supply these values to the AudioPlayer, which will pass it down to the AVPlayerWrapper that initializes the AVURLAsset.

Describe alternatives you've considered
A protocol that AudioItems can conform to in order to supply relevant options.

Additional context
A result of PR #64, that was adding auth headers to the asset by supplying headers in the option dictionary with the AVURLAssetHTTPHeaderFieldsKey key, but this is a private API. The feature described here offers a way for developers to use this at their own risk.

Play last song on previous when I am on the first one

Is your feature request related to a problem? Please describe.
go to the last song when I am on the first one and I click on previous

Describe the solution or feature you would like
I want to add the behavior when user click on previous and he is on the first to play the last song and so on

making AVPlayerWrapper class open

It's important to set the wrapper class and all of its methods & properties access level to be 'open', so I can implement my custom wrapper on top of this wrapper, for example, I want to use a custom AVPlayerItem inside the wrapper to manage caching, there is no way to do so without subclassing AVPlayerWrapper class.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.