Swift AVAudioPlayer (Xcode) - 在应用程序包外播放音频文件

Posted

技术标签:

【中文标题】Swift AVAudioPlayer (Xcode) - 在应用程序包外播放音频文件【英文标题】:Swift AVAudioPlayer (Xcode) - Play Audio File Outside Application Bundle 【发布时间】:2019-06-11 09:28:21 【问题描述】:

在我的 Xcode 项目中,我设置了以下代码(简化代码):

import Cocoa
import AVKit

class ViewController: NSViewController 

    var audioPlayer = AVAudioPlayer()

    override func viewDidLoad() 
        super.viewDidLoad()

        do 
            guard let filePath = Bundle.main.path(forResource: "sample", ofType: "mp3") else 
                print("ERROR: Failed to retrieve music file Path")
                return
            
            let fileURL = URL.init(fileURLWithPath: filePath)
            print(" PATH: \(filePath)")
            print("  URL: \(fileURL)")
            try audioPlayer = AVAudioPlayer.init(contentsOf: fileURL)
         catch 
            print("ERROR: Failed to retrieve music file URL")
        

        audioPlayer.play() 
    


//CONSOLE PRINTS ----------:
// PATH: /Users/vakho/Library/Developer/Xcode/DerivedData/MusicPlayer-foqzsckozmcjnofvlvhuwabfssqi/Build/Products/Debug/MusicPlayer.app/Contents/Resources/sample.mp3
//  URL: file:///Users/vakho/Library/Developer/Xcode/DerivedData/MusicPlayer-foqzsckozmcjnofvlvhuwabfssqi/Build/Products/Debug/MusicPlayer.app/Contents/Resources/sample.mp3

通过首先转换为 URL,我成功地将 sample.mp3 的文件路径(包含在应用程序包中)传递给 audioPlayer。调用 play() 函数播放音频文件。

但是,由于我正在创建一个音乐播放器应用程序,我希望能够播放位于目录文件夹中的音频文件,例如桌面、下载文件夹等....但是当我尝试通过应用包外音频文件的filePath,代码中断:

import Cocoa
import AVKit

class ViewController: NSViewController 

    var audioPlayer = AVAudioPlayer()

    override func viewDidLoad() 
        super.viewDidLoad()

        do 
            let filePathOptional: String? = "/Users/vakho/Downloads/sample.mp3"
            guard let filePath = filePathOptional else 
                print("ERROR: Failed to retrieve music file Path")
                return
            
            let fileURL = URL.init(fileURLWithPath: filePath)
            print(" PATH: \(filePath)")
            print("  URL: \(fileURL)")
            try audioPlayer = AVAudioPlayer.init(contentsOf: fileURL)
         catch 
            print("ERROR: Failed to retrieve music file URL")
        

        audioPlayer.play()
    


//CONSOLE PRINTS ----------:
// PATH: /Users/vakho/Downloads/sample.mp3
//  URL: file:///Users/vakho/Downloads/sample.mp3
//ERROR: Failed to retrieve music file URL

//ERRORS ----------:
//  (lldb)
//  Thread 1: EXC_BAD_ACCESS (code=1, address=0x38)

据我所知,AVAudioPlayer 和 AVKit 库设计用于访问应用程序资产和捆绑媒体文件,以及来自互联网的流媒体。但它无法播放目录中的媒体。

我找到了几个关于这个问题的帖子,都是不完整或没有答案的,例如:https://forums.developer.apple.com/thread/18272

如果 AVKit 不能做我认为它应该做的事情,我可以使用什么库或方法来访问目录文件? OSX 的音乐播放器应用程序当然能够提示用户扫描目录和访问音乐文件。他们是怎么做到的?

【问题讨论】:

【参考方案1】:

看来问题出在这里:

guard let filePath = filePathOptional else 
    print("ERROR: Failed to retrieve music file Path")
    return

请将打印改为:

print("ERROR: Failed to retrieve music file Path \(error.localizedDescription)")

我想您会发现问题在于您无权访问此文件。 默认情况下,您只能访问应用程序和桌面文件夹的沙盒。

同时尝试将您的文件放到桌面并播放。

【讨论】:

我尝试将文件放在桌面上,但同样的事情发生了。然后我尝试根据在应用程序包中的格式化方式自行将 filePath 格式化为 fileURL,并将其传递给初始化程序。正如我推测的那样,似乎无法使用捆绑包之外的 URL 初始化 audioPlayer。如果确实是访问权限问题,我会尝试要求访问权限。 我们更正了,我已经捕获了错误消息并将其打印到控制台。它说“permErr:权限错误(打开文件时)”。然后我进一步阅读了 Apple 文档,结果发现出于隐私原因启用了 Sanboxing。禁用 Sanboxing 是一个选项,但这意味着您不能再将应用程序提交到应用程序商店。正确的解决方案是导入文件/目录 uisng NSOpenPanel。谢谢!

以上是关于Swift AVAudioPlayer (Xcode) - 在应用程序包外播放音频文件的主要内容,如果未能解决你的问题,请参考以下文章

Swift - AVAudioPlayer 无法正常工作

AVAudioPlayer 不播放音频文件 - swift

Swift - AVAudioPlayer,声音播放不正确

将 AirPlay 添加到 AVAudioPlayer (Swift)

AVAudioPlayer 使用数组对音频文件进行排队 - Swift

macOS 上的 swift: AVAudioPlayer 立即停止