Detecting End of The Playback in Avaudioplayer

How to monitor for AVAudioPlayerNode finished playing

Instead of using avPlayer.scheduleFile(file, at: nil), use the form of the method with a completion handler:

avPlayer.scheduleFile(file, at: nil) {
//call your completion function here
print("Done playing")
}

How can I detect that AVQueuePlayer finished playing?

Figured it out. Need to add before inserting an item:

NotificationCenter.default.addObserver(self, selector: #selector(self.playerDidFinishPlaying(sender:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playerItem

which then calls

@objc func playerDidFinishPlaying(sender: Notification) {
print("Finished playing")
}

How do I continuously check if AVAudioplayer is done playing in Swift?

You don't have to continually check - you should instead implement the AVAudioPlayerDelegate protocol in your View Controller: https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioPlayerDelegateProtocolReference/index.html#//apple_ref/occ/intfm/AVAudioPlayerDelegate/audioPlayerDidFinishPlaying:successfully:

See: audioPlayerDidFinishPlaying:successfully:. I think you'll find it does exactly the opposite of what you want to do, which is actually the correct way. This way, your player will simply call the "end" function that you define.

Do an action when a sound has finished playing in AVAudioPlayer?

When a sound is finished playing, I want the application to do something.

Then set yourself as the delegate and respond to audioPlayerDidFinishPlaying:successfully:.

In the code snippet you showed, you've done step 2 but not step 1: You're not setting yourself as the delegate.

I tried to use applicationDidFinishLaunching to do the action at the end of the first sound …

Brain fart? That method has nothing that I can see to do with playing sounds.

…, but I couldn't use that for the second sound because I got a redefinition error.

Huh? Did you implement the method twice or something instead of just comparing the player object in the method body?

It would help if you showed the exact error message you got.

Check play state of AVPlayer

To get notification for reaching the end of an item (via Apple):

[[NSNotificationCenter defaultCenter] 
addObserver:<self>
selector:@selector(<#The selector name#>)
name:AVPlayerItemDidPlayToEndTimeNotification
object:<#A player item#>];

And to track playing you can:

"track changes in the position of the playhead in an AVPlayer object" by using addPeriodicTimeObserverForInterval:queue:usingBlock: or addBoundaryTimeObserverForTimes:queue:usingBlock:.

Example is from Apple:

// Assume a property: @property (retain) id playerObserver;

Float64 durationSeconds = CMTimeGetSeconds([<#An asset#> duration]);
CMTime firstThird = CMTimeMakeWithSeconds(durationSeconds/3.0, 1);
CMTime secondThird = CMTimeMakeWithSeconds(durationSeconds*2.0/3.0, 1);
NSArray *times = [NSArray arrayWithObjects:[NSValue valueWithCMTime:firstThird], [NSValue valueWithCMTime:secondThird], nil];

self.playerObserver = [<#A player#> addBoundaryTimeObserverForTimes:times queue:NULL usingBlock:^{
// Passing NULL for the queue specifies the main queue.

NSString *timeDescription = (NSString *)CMTimeCopyDescription(NULL, [self.player currentTime]);
NSLog(@"Passed a boundary at %@", timeDescription);
[timeDescription release];
}];

How to track when song is finished AVAudioPlayer

I solved my problem with help of Leo Dabus.
I changed my edited code. I moved player?.delegate = self
to playSound func. Finally, it is working.

playSound & audioPlayerDidFinishPlaying function:

  func playSound(name: String ) {
guard let url = Bundle.main.url(forResource: name, withExtension: "mp3") else {
print("url not found")
return
}

do {
/// this codes for making this app ready to takeover the device audio
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)

/// change fileTypeHint according to the type of your audio file (you can omit this)
player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3)

player?.delegate = self

// no need for prepareToPlay because prepareToPlay is happen automatically when calling play()
player!.play()
} catch let error as NSError {
print("error: \(error.localizedDescription)")
}
}

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
print("finished")//It is working now! printed "finished"!
}

Do not forget to add AVAudioPlayerDelegate to ViewController!

class ViewController: UIViewController,AVAudioPlayerDelegate {


Related Topics



Leave a reply



Submit