0

I know this is a duplicate question but I did not find any solution that works for me.

I am using AVAudioPlayer to play an audio with the url which I am getting from Firebase. The url I get from Firebase is:

https://firebasestorage.googleapis.com:443/v0/b/unified-45b5c.appspot.com/o/AudioMessage%2F5%2B8_5_Audio_07-09-20224:07:30.m4a?alt=media&token=af3aabce-46bd-4d55-a7ca-30623eaf1817

if I open this url on google chrome it gives me my audio. But when I try it using AVAudioPlayer it gives me the following error:

The operation couldn’t be completed. (OSStatus error 2003334207.)

This is what I am doing:

Button {  
 
         vm.startPlaying(url: audioURL ?? URL(fileURLWithPath: "")) 
        } label: {

            Image(systemName: startAudio ? "pause.fill" : "play.fill")
                .foregroundColor(.black)
                .padding()
                .background(
                    RoundedRectangle(cornerRadius: 10)
                        .foregroundColor(.gray)
                        .frame(width: 100)
                )
        }

And the function startPlaying():

    func startPlaying(url : URL) {
                    
           do {
               audioPlayer = try AVAudioPlayer(contentsOf : url)
               audioPlayer.prepareToPlay()
               audioPlayer.play()
                   
           } catch {
               Helper.shared.printDebug("Playing Failed")
               Helper.shared.printDebug(error.localizedDescription)  // error: The operation couldn’t be completed. (OSStatus error 2003334207.)
           }
                   
       }
Taimoor Arif
  • 750
  • 3
  • 19
  • 1
    Often pure `error`s reveal more than their `localizedDescription`. – vadian Sep 07 '22 at 11:20
  • @vadian I am printing the error and it gives me this: "Error Domain=NSOSStatusErrorDomain Code=2003334207 "(null)" – Taimoor Arif Sep 07 '22 at 11:22
  • 1
    That's an *unspecified error* https://www.osstatus.com/search/results?platform=all&framework=all&search=2003334207. Is the `URL` valid? The browser is more tolerant than the `Foundation` framework. Better handle **that** error rather than passing completely pointless `URL(fileURLWithPath: "")` – vadian Sep 07 '22 at 11:26

2 Answers2

2

The initializer you are using for AVAudioPlayer expect an URL to a local file. You can’t pass it a URL to a file on a remote server. To quote the docs:

Declaration
init(contentsOf url: URL) throws
Parameters
url
A URL that identifies the local audio file to play

You’ll need to download the data to a local file before playing it, or use a method that supports streaming audio playback.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
1

Duncan's solution works if you want to download the item first, and then play it. If you want more like a streaming experience, you can use AVPlayer, which is built to allow playing remote files, and helps with streaming:

Use an instance of AVPlayer to play local and remote file-based media, such as QuickTime movies and MP3 audio files, as well as audiovisual media served using HTTP Live Streaming.

let player = AVPlayer(playerItem: item) 
let audio = AVPlayerItem(url: url)
player.play()

Note that you can keep an instance of the player to play multiple items

See this answer for detailed comparison between the two

timbre timbre
  • 12,648
  • 10
  • 46
  • 77
  • 1
    Thanks for adding an answer describing AVPlayer. (Voted.) I didn’t remember the class that handled streaming audio, and didn’t have time this morning to hunt for it. – Duncan C Sep 07 '22 at 16:00