【问题标题】:Playing a sound with AVAudioPlayer使用 AVAudioPlayer 播放声音
【发布时间】:2014-08-15 02:53:52
【问题描述】:

我正在尝试使用AVAudioPlayer 播放声音,但它不起作用。

编辑 1:还是不行。

编辑 2:此代码有效。我的设备处于静音模式。

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var audioPlayer = AVAudioPlayer()

    override func viewDidLoad() {
        super.viewDidLoad()

        var alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("button-09", ofType: "wav"))
        println(alertSound)

        var error:NSError?
        audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, error: &error)
        audioPlayer.prepareToPlay()
        audioPlayer.play()
    }
}

【问题讨论】:

  • 与其将“nil”传递给错误参数,不如传递一些东西并找出错误到底是什么?
  • 错误包含 nil
  • 我实际上在 osx 应用程序中使用与您完全相同的代码,除了错误代码本身似乎引发某种类型的错误之外,它一切正常:“致命错误:意外发现 nil同时展开一个可选值”,这让我相信错误声明有问题。我对 swift 中的错误了解不多,但这是你以前遇到过的吗?
  • @Uzebeckatrente - 检查你没有使用 NSURL(string:...)。在某些情况下,由于某种原因,这将返回 nil。您应该使用 NSURL(fileURLWithPath:...) 作为文件位置。
  • 哈哈哈...为静音模式点赞!

标签: ios swift audio avaudioplayer


【解决方案1】:

您的音频播放将在 viewDidLoad 完成后立即释放,因为您将其分配给了一个局部变量。您需要为其创建一个属性以保留它。

【讨论】:

【解决方案2】:

对您的代码进行了修改:

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var audioPlayer = AVAudioPlayer()

    override func viewDidLoad() {
        super.viewDidLoad()

        var alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("button-09", ofType: "wav"))
        println(alertSound)

        // Removed deprecated use of AVAudioSessionDelegate protocol
        AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
        AVAudioSession.sharedInstance().setActive(true, error: nil)

        var error:NSError?
        audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, error: &error)
        audioPlayer.prepareToPlay()
        audioPlayer.play()
    }

}

Swift 3 和 Swift 4.1:

import UIKit
import AVFoundation

class ViewController: UIViewController {
    private var audioPlayer: AVAudioPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()

        let alertSound = URL(fileURLWithPath: Bundle.main.path(forResource: "button-09", ofType: "wav")!)
        print(alertSound)

        try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try! AVAudioSession.sharedInstance().setActive(true)

        try! audioPlayer = AVAudioPlayer(contentsOf: alertSound)
        audioPlayer!.prepareToPlay()
        audioPlayer!.play()
    }
}

【讨论】:

  • 嗨,我正在尝试使用大致相同的代码向我的程序添加声音,但它正在崩溃。你到底把音频文件放在哪里?在资产文件夹或..?
  • @skyguy,您可以将声音文件拖到您的项目中并选择要添加的正确目标。
  • 关于如何将它用于 pls 或远程 mp3 文件的任何想法?
  • "AVplayer 不支持流媒体,你可以用 AVPlayer stackoverflow.com/questions/3635792/…
  • 我必须为每个要播放的声音文件创建一个AVAudioPlayer 的新实例吗?
【解决方案3】:

这会起作用.....

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var ding:AVAudioPlayer = AVAudioPlayer()

    override func viewDidLoad() {
        super.viewDidLoad()

        prepareAudios()
        ding.play()
    }

    func prepareAudios() {

        var path = NSBundle.mainBundle().pathForResource("ding", ofType: "mp3")
        ding = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: path!), error: nil)
        ding.prepareToPlay()
    }
}

【讨论】:

  • “这会起作用” 但是为什么它会起作用呢?请说明 OP 出了什么问题以及您是如何解决的,以便未来的用户能够理解其背后的概念。
【解决方案4】:

根据 Swift 2,代码应该是

var audioPlayer : AVAudioPlayer!

func playSound(soundName: String)
{
    let coinSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(soundName, ofType: "m4a")!)
    do{
        audioPlayer = try AVAudioPlayer(contentsOfURL:coinSound)
        audioPlayer.prepareToPlay()//there is also an async version
        audioPlayer.play()
    }catch {
        print("Error getting the audio file")
    }
}

【讨论】:

  • 您应该在某处使 audioPlayer 成为实例变量。此代码将在调用 .play() 后立即将其释放,您将听不到任何声音。
  • 该应用也会出现轻微的延迟,因为它需要一次加载文件并准备好播放器。
【解决方案5】:

解决方案适用于在导航栏中将播放/暂停/停止按钮作为栏按钮项的 AudioPlayer

在 Swift 2.1 中,您可以使用以下代码

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var player:AVAudioPlayer = AVAudioPlayer()

    override func viewDidLoad() {
            super.viewDidLoad()

            let audioPath = NSBundle.mainBundle().pathForResource("ARRehman", ofType: "mp3")
            var error:NSError? = nil
            do {
                player = try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: audioPath!))
            }
            catch {
                print("Something bad happened. Try catching specific errors to narrow things down")
            }

        }

    @IBAction func play(sender: UIBarButtonItem) {
        player.play()

    }


    @IBAction func stop(sender: UIBarButtonItem) {
        player.stop()
        print(player.currentTime)
        player.currentTime = 0
    }


    @IBAction func pause(sender: UIBarButtonItem) {

        player.pause()
    }


    @IBOutlet weak var sliderval: UISlider!


    @IBAction func slidermov(sender: UISlider) {

        player.volume = sliderval.value
        print(player.volume)
    }

}

【讨论】:

    【解决方案6】:

    在 Swift 中使用这个函数发声(你可以在你想发声的地方使用这个函数。)

    首先添加 SpriteKit 和 AVFoundation 框架。

    import SpriteKit
    import AVFoundation
    func playEffectSound(filename: String){
         runAction(SKAction.playSoundFileNamed("\(filename)", waitForCompletion: false))
    }// use this function to play sound
    
    playEffectSound("Sound File Name With Extension")
    // Example :- playEffectSound("BS_SpiderWeb_CollectEgg_SFX.mp3")
    

    【讨论】:

    • 这可能“有效”,但它不会预加载音频,并且我在第一次执行时会导致性能下降
    【解决方案7】:

    这是一个相当古老的问题,但我没有看到适用于 Swift 3.0 的答案,因此我对代码进行了现代化改造并添加了一些安全检查以防止崩溃。

    我还采取了将游戏部分拉到自己的功能中的方法,以帮助遇到此答案的任何人重复使用。

    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController {
        var audioPlayer: AVAudioPlayer?
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            play(for: "button-09", type: "wav")
        }
    
        func play(for resource: String, type: String) {
            // Prevent a crash in the event that the resource or type is invalid
            guard let path = Bundle.main.path(forResource: resource, ofType: type) else { return }
            // Convert path to URL for audio player
            let sound = URL(fileURLWithPath: path)
            do {
                audioPlayer = try AVAudioPlayer(contentsOf: sound)
                audioPlayer?.prepareToPlay()
                audioPlayer?.play()
            } catch {
                // Create an assertion crash in the event that the app fails to play the sound
                assert(false, error.localizedDescription)
            }
        }
    }
    

    【讨论】:

    • 让audioPlayer成为一个实例变量
    【解决方案8】:

    从 Swift 4.2 开始,AudioSession 类别设置选项已更改。 (从 Swift 4.2 开始尝试以下代码)

    import UIKit
    import AVFoundation
    
    
    class ViewController: UIViewController {
    
    
        var audioPlayer: AVAudioPlayer?
    
        override func viewDidLoad() {
            super.viewDidLoad()
            prepareAudioSession()
        }
    
    
        func prepareAudioSession() -> Void {
            do {
                try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, mode: AVAudioSession.Mode.default, options: AVAudioSession.CategoryOptions.defaultToSpeaker)
                try AVAudioSession.sharedInstance().setActive(true)
    
                prepareAudioPlayer()
    
            } catch {
                print("Issue with Audio Session")
            }
        }
    
    
        func prepareAudioPlayer() -> Void {
    
            let audioFileName = "test"
            let audioFileExtension = "mp3"
    
            guard let filePath = Bundle.main.path(forResource: audioFileName, ofType: audioFileExtension) else {
                print("Audio file not found at specified path")
                return
            }
    
            let alertSound = URL(fileURLWithPath: filePath)
            try? audioPlayer = AVAudioPlayer(contentsOf: alertSound)
            audioPlayer?.prepareToPlay()
        }
    
    
        func playAudioPlayer() -> Void {
            audioPlayer?.play()
        }
    
    
        func pauseAudioPlayer() -> Void {
            if audioPlayer?.isPlaying ?? false {
                audioPlayer?.pause()
            }
        }
    
    
        func stopAudioPlayer() -> Void {
            if audioPlayer?.isPlaying ?? false {
                audioPlayer?.stop()
            }
        }
    
        func resetAudioPlayer() -> Void {
            stopAudioPlayer()
            audioPlayer?.currentTime = 0
            playAudioPlayer()
        }
    
    }
    

    【讨论】:

    • 我在 prepareAudioSession 函数中遇到错误...你在 iOS 12 中遇到过这个问题吗?
    猜你喜欢
    • 2015-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    相关资源
    最近更新 更多