Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting URL to AVAsset - Swift

I am attempting to convert the url that is in my audio player to an AVAsset so that I am able to manipulate the audio track to my liking. ( I just want to be able to trim the file). Unfortunately I am running into an issue where the asset is not correctly converting. When I print the duration of the audio url before I convert it, it will correctly print out the duration. Unfortunately when I convert it to the AVAsset, it says the duration is 0. What is going on? Any guidance would be much appreciated!

func trimmingFunc() {

        try? audioPlayer = AVAudioPlayer(contentsOf: audioURL!)
        passingTime = audioPlayer.duration
        audioPlayer.delegate = self


        let currentDuration = audioPlayer.duration
        print(currentDuration) //correctly prints duration
        let filePath = URL(fileURLWithPath: (("\(String(describing: audioPlayer.url!))")))
        print(filePath) //correctly prints filePath


        let currentAsset = AVAsset(url: filePath)
        print(CMTimeGetSeconds(currentAsset.duration) //This is printing 0

}
like image 380
AndrewS Avatar asked Jun 06 '17 12:06

AndrewS


1 Answers

Loading an AVAsset is asynchronous operation. You should wait until it will be prepared. The most efficient way to "wait" is using KVO.

In your class, let it be ViewController, make AVAsset the member and call your trimmingFunc somewhere:

class ViewController: UIViewController {

    var currentAsset: AVAsset?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.trimmingFunc()
    }
....

In your trimmingFunc, subscribe for notifications of currentAsset:

func trimmingFunc() {

    let audioURL = URL.init(fileURLWithPath: Bundle.main.path(forResource: "Be That Man", ofType: "mp3")!)

    print("audioURL=\(audioURL)")
    currentAsset = AVAsset(url: audioURL)
    let options = NSKeyValueObservingOptions([.new, .old, .initial, .prior])
    currentAsset!.addObserver(self, forKeyPath: "duration", options: options, context: nil)
}

To receive that notifications, override function observeValue of NSObject:

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

    print("\(keyPath): \(change?[.newKey])")

    print(CMTimeGetSeconds(currentAsset!.duration)) //This is printing 0
}

So, if you had file "Be That Man.mp3" in resources, after few milliseconds you would see duration = 202.945306122449

Full code of ViewController is here.

like image 113
olha Avatar answered Sep 22 '22 05:09

olha