I've created a button to play audio (streaming from a link) with AVPlayer in Swift. How to stop the audio automatically when the audio time is finished?
Here is some of my code :
var player : AVPlayer?
url = URL(string: "https://cdn.islamic.network/quran/audio/128/ar.alafasy/162.mp3")
let playerItem:AVPlayerItem = AVPlayerItem(url: url!)
player = AVPlayer(playerItem: playerItem)
player?.play()
For example, in this URL (https://cdn.islamic.network/quran/audio/128/ar.alafasy/162.mp3), the audio length is 19 seconds. So after 19 seconds I play the audio, the audio must stop.
Thank you :)
You can use the NSNotificationCenter Observer
NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerDidFinishPlaying:", name: AVPlayerItemDidPlayToEndTimeNotification, object: item)
player?.play()
and stop player in this function
func playerDidFinishPlaying(note: NSNotification) {
// Your code here
player?.pause()
player?.replaceCurrentItem(with: nil)
}
Related
I am using AVQueuePlayer to playback a batch of audio files. I'd like to insert a pause in between items. Any idea how to do that?
Here the method that adds items into the queue:
func addItemToAudioQueue (file:String, last:Bool) {
let urlPath = Bundle.main.path(forResource: file, ofType: "mp3")
let fileURL = NSURL(fileURLWithPath:urlPath!)
let playerItem = AVPlayerItem(url:fileURL as URL)
if last {
NotificationCenter.default.addObserver(self, selector: #selector(self.playerDidFinishPlaying(sender:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playerItem)
}
queuePlayer.insert(playerItem, after: nil)
}
Add an observer for the notification named AVPlayerItemDidPlayToEndTimeNotification that will be fired every time an AVPlayerItem is finished playing, i.e.
NotificationCenter.default.addObserver(self, selector: #selector(playerEndedPlaying), name: Notification.Name("AVPlayerItemDidPlayToEndTimeNotification"), object: nil)
AVPlayerItemDidPlayToEndTimeNotification
A notification that's posted
when the item has played to its end time.
Next, when the playerEndedPlaying method is called after the notification is fired, pause() the AVQueuePlayer initially and then play() it again after 5 seconds like so,
#objc func playerEndedPlaying(_ notification: Notification) {
self.player?.pause()
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {[weak self] in
self?.player?.play()
}
}
I have created a sample function, which will play a short-duration tone instantly, with the infinite loop. Here is the code:
let audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayer.numberOfLoops = -1
audioPlayer.play()
How to create a 5 second delay before the player will play the tone again? Is there a way to do this?
Unfortunately there is no simple way of doing this. You should use AVAudioPlayerDelegate. Please find some example below:
class ViewController: UIViewController, AVAudioPlayerDelegate
{
private var player: AVAudioPlayer!
#objc private func startPlaying()
{
self.player = try? AVAudioPlayer(contentsOf: url)
self.player.delegate = self
self.player.play()
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool)
{
self.perform(#selector(startPlaying), with: nil, afterDelay: 5)
}
}
Don't forget to stop selector whenever you want stop the continuation of the audio:
NSObject.cancelPreviousPerformRequests(withTarget: self)
I am trying to loop a video with playerViewController on Swift for TVOS. I have the video playing fine, but I want to loop the video. Here is my code so far:
override func viewDidAppear(_ animated: Bool) {
let videoURL = URL(string: "https://url-to-video.com/video.mp4")
let player = AVPlayer(url: videoURL!)
let playerViewController = AVPlayerViewController()
playerViewController.player = player self.present(playerViewController, animated: true) {
playerViewController.player!.play()
}
}
Any help is appreciated. Thanks
The quickest way to do this is to use an AVQueuePlayer with an AVPlayerLooper. You can set the player on your player view controller the same as you would with an ordinary AVPlayer, but you need to keep a persistent reference around to the looper so it’ll keep working. In other words, add this to your view controller’s interface:
var looper: AVPlayerLooper?
…and in your viewDidAppear, replace this:
let player = AVPlayer(url: videoURL!)
with this:
let player = AVQueuePlayer()
looper = AVPlayerLooper(player: player, templateItem: AVPlayerItem(asset: AVAsset(url: videoURL!)))
Then, once you start the player playing, its video will loop indefinitely.
So I can video to play when you click on the thumbnail but if I attach the ad to it, the ad will play over the video. how do I wait to play the ad after?
func playVideo(){
player = AVPlayer(URL: NSURL(string: String(vid))!)
player?.play()
if(ALInterstitialAd.isReadyForDisplay()){
ALInterstitialAd.show()
}
}
Did you try to register for AVPlayerItemDidPlayToEndTimeNotification?
Just add
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourViewController.itemDidFinishPlaying(_:)), name: AVPlayerItemDidPlayToEndTimeNotification, object: nil)
when you play your video and implement the itemDidFinishPlaying: method when you need to present your advertising. Something like this:
func playVideo(){
player = AVPlayer(URL: NSURL(string: String(vid))!)
player?.play()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourViewController.itemDidFinishPlaying(_:)), name: AVPlayerItemDidPlayToEndTimeNotification, object: nil)
}
func itemDidFinishPlaying(notification : NSNotification){
if(ALInterstitialAd.isReadyForDisplay()){
ALInterstitialAd.show()
}
NSNotificationCenter.defaultCenter().removeObserver(self, name: AVPlayerItemDidPlayToEndTimeNotification, object: nil)
}
I'm attempting to play a simple local clip in Xcode7 using Swift for tvOS. All I want is for the video to load fullscreen in the view and loop. Every tutorial I see has the old MPMoviePlayerController or loads from a URL. What is the best way to do this on tvOS?
Update2: This got the video to loop but there is a pause in between. looking into it now to see how to do it seamlessly.
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController {
var videoPlayer: AVPlayer!
var playerLayer: AVPlayerLayer?
override func viewDidLoad() {
super.viewDidLoad()
let path = NSBundle.mainBundle().pathForResource("video", ofType:"mp4")
let url = NSURL(fileURLWithPath: path!)
let playerItem = AVPlayerItem(URL: url)
self.videoPlayer = AVPlayer(playerItem: playerItem)
self.playerLayer = AVPlayerLayer(player: self.videoPlayer)
self.playerLayer!.frame = self.view.frame
self.videoPlayer!.play()
self.view.layer.addSublayer(self.playerLayer!)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("playerDidReachEnd:"), name: AVPlayerItemDidPlayToEndTimeNotification, object:nil)
}
func playerDidReachEnd(notification: NSNotification) {
self.videoPlayer.seekToTime(kCMTimeZero)
self.videoPlayer.play()
}
}
Let's say your file is named video.m4v and is stored locally on the device (don't forget to add it to Copy Bundle Resources in Build Phases). Create a stored property so you can access the AVPlayer-instance:
var videoPlayer: AVPlayer?
Setup the video player and add the AVPlayerLayer to your view hierarchy.
if let path = NSBundle.mainBundle().pathForResource("video", ofType:"m4v") {
let url = NSURL(fileURLWithPath: path)
let playerItem = AVPlayerItem(URL: url)
self.videoPlayer = AVPlayer(playerItem: playerItem)
self.playerLayer = AVPlayerLayer(player: self.videoPlayer)
self.playerLayer!.frame = self.view.frame
self.view.layer.addSublayer(self.playerLayer!)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("playerDidReachEnd:"), name: AVPlayerItemDidPlayToEndTimeNotification, object:nil)
}
You have now subscribed a notification that i sent when this video ends. Implement handler and tell the player to replay video.
func playerDidReachEnd(notification: NSNotification) {
self.videoPlayer.seekToTime(kCMTimeZero)
self.videoPlayer.play()
}