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
Swift 4 - Hmcharacteristictypeserialnumber Deprecated
How to Present a UIcollectionview in Swiftui with UIviewcontrollerrepresentable
Enum of String Type Vs Struct with Static Constant
iOS Swift, Aws Cognito User Pool, Unable to Refresh Access Token
Produce Sounds of Different Frequencies in Swift
Swift 2.0 Replicate Objc_Association_Retain
Swift System Version Checking on Ubuntu
Where Do I Register a Valuetransformer in Swift
Uidatepicker Show Only Sunday's Date Only
How to Get Reliable Timing for My Audio App
How to Create a Pulse Effect on an Skspritenode
Pause Spritekit Scene When Iad Is Clicked in Swift
Ibdesignable View Not Rendering
How to Convert Custom Object to Data Swift