AVAudioEngine Cannot Create AVAudioFile from URL

I cannot seem to create an AVAudioFile from a URL to be played in an AVAudioEngine. Here is my complete code, following the documentation.

import UIKit
import AVKit
import AVFoundation

class ViewController: UIViewController {
    let audioEngine = AVAudioEngine()
    let audioPlayerNode = AVAudioPlayerNode()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        streamAudioFromURL(urlString: "https://samplelib.com/lib/preview/mp3/sample-9s.mp3")
        
    }
    
  
    func streamAudioFromURL(urlString: String) {
        guard let url = URL(string: urlString) else {
            print("Invalid URL")
            return
        }
        
        let audioFile = try! AVAudioFile(forReading: url)
        let audioEngine = AVAudioEngine()
        let playerNode = AVAudioPlayerNode()

        audioEngine.attach(playerNode)

        audioEngine.connect(playerNode,
                            to: audioEngine.outputNode,
                            format: audioFile.processingFormat)
        playerNode.scheduleFile(audioFile,
                                at: nil,
                                completionCallbackType: .dataPlayedBack) { _ in
            /* Handle any work that's necessary after playback. */
        }
        do {
            try audioEngine.start()
            playerNode.play()
        } catch {
            /* Handle the error. */
        }
        
    }
    
}

I am getting the following error on let audioFile = try! AVAudioFile(forReading: url)

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=com.apple.coreaudio.avfaudio Code=2003334207 "(null)" UserInfo={failed call=ExtAudioFileOpenURL((CFURLRef)fileURL, &_extAudioFile)}

I have tried many other .mp3 file URLs as well as .wav and .m4a and none seem to work. The documentation makes this look so easy but I have been trying for hours to no avail. If you have any suggestions, they would be greatly appreciated!

Replies

The "file" part of AVAudioFile is literal — the URL has to point to a file in a local file system. The URL in your example refers to a resource on a server, which isn't supported by AVAudioFile. Instead, you should download the resource to a temporary or cached file, and play it from there.

Note also that if your code is in a sandboxed app, you can't read an arbitrary local file either. You can only read files that are (1) inside your app's container, or (2) in a predefined location outside your container that apps are generally allowed to reference, or (3) designated by the user in a way that grants access to an otherwise-inaccessible local file. (The details vary from platform to platform.)

Hi!

For the second part on arbitrary local file, does it include assetURL obtained from MPMediaItem?

I've been facing a similar issue but with error code -54 when I do "file = try AVAudioFile(forReading: url!)".

Thank you.

Kind regards, 8K