如何使用Swift播放声音?


148

我想用Swift播放声音。

我的代码在Swift 1.0中有效,但现在在Swift 2或更高版本中不再有效。

override func viewDidLoad() {
  super.viewDidLoad()

  let url:NSURL = NSBundle.mainBundle().URLForResource("soundName", withExtension: "mp3")!

  do { 
    player = try AVAudioPlayer(contentsOfURL: url, fileTypeHint: nil) 
  } catch _{
    return
  }

  bgMusic.numberOfLoops = 1
  bgMusic.prepareToPlay()

  if (Data.backgroundMenuPlayed == 0){
    player.play()
    Data.backgroundMenuPlayed = 1
  }
}

1
看看SwiftySound此答案中有更多详细信息。
亚当

如果您只想从系统中获取声音,
Honey

Answers:


291

最可取的是,您可能想使用AVFoundation。它提供了使用视听媒体的所有必要条件。

更新:某些评论中建议与Swift 2Swift 3Swift 4兼容。


斯威夫特2.3

import AVFoundation

var player: AVAudioPlayer?

func playSound() {
    let url = NSBundle.mainBundle().URLForResource("soundName", withExtension: "mp3")!

    do {
        player = try AVAudioPlayer(contentsOfURL: url)
        guard let player = player else { return }

        player.prepareToPlay()
        player.play()

    } catch let error as NSError {
        print(error.description)
    }
}

迅捷3

import AVFoundation

var player: AVAudioPlayer?

func playSound() {
    guard let url = Bundle.main.url(forResource: "soundName", withExtension: "mp3") else { return }

    do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try AVAudioSession.sharedInstance().setActive(true)

        let player = try AVAudioPlayer(contentsOf: url)

        player.play()

    } catch let error {
        print(error.localizedDescription)
    }
}

Swift 4(与iOS 13兼容)

import AVFoundation

var player: AVAudioPlayer?

func playSound() {
    guard let url = Bundle.main.url(forResource: "soundName", withExtension: "mp3") else { return }

    do {
        try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)            
        try AVAudioSession.sharedInstance().setActive(true)

        /* The following line is required for the player to work on iOS 11. Change the file type accordingly*/
        player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue)

        /* iOS 10 and earlier require the following line:
        player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3) */

        guard let player = player else { return }

        player.play()

    } catch let error {
        print(error.localizedDescription)
    }
}

确保更改乐曲的名称以及扩展名 该文件需要正确导入(Project Build Phases> Copy Bundle Resources)。您可能希望将其放置在assets.xcassets更大的便利中。

对于短声音文件,您可能需要使用非压缩音频格式,例如,.wav因为它们具有最佳的质量和较低的cpu影响。对于短声音文件而言,较高的磁盘空间消耗不应该是大问题。较长的文件,你可能会想要去的压缩格式,如.mp3等页。检查兼容的音频格式CoreAudio


趣味:整洁的小资料库使播放声音更加轻松。:)
例如:SwiftySound


抱歉,此代码在swift 2.0中不再起作用,它提示错误“呼叫可以抛出,但未标记为'try'并且未处理该错误”
Michel Kansou 2015年

2
替换bgMusic = AVAudioPlayer(contentsOfURL: bgMusicURL, fileTypeHint: nil)do { bgMusic = try AVAudioPlayer(contentsOfURL: bgMusicURL, fileTypeHint: nil) } catch _ { return \\ if it doesn't exist, don't play it}
saagarjha 2015年

11
我必须使AVAudioPlayer对象成为实例变量,才能使其正常工作。作为局部变量,它不会播放任何内容,没有错误。代表也不会被召集。
卡列布

2
为什么在这里使用警卫?player = try AVAudioPlayer(contentsOf: url) guard let player = player else { return }对我来说似乎是额外的工作,为什么不let player = try AVAudioPlayer(contentsOf: url)呢?
xandermonkey '16

2
使用保护语句使您非常安全,不会因为nil值而崩溃。
阿什什

43

对于Swift 3

import AVFoundation

/// **must** define instance variable outside, because .play() will deallocate AVAudioPlayer 
/// immediately and you won't hear a thing
var player: AVAudioPlayer?

func playSound() {
    guard let url = Bundle.main.url(forResource: "soundName", withExtension: "mp3") else {
        print("url not found")
        return
    }

    do {
        /// this codes for making this app ready to takeover the device audio
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try AVAudioSession.sharedInstance().setActive(true)

        /// change fileTypeHint according to the type of your audio file (you can omit this)

        player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3)

        // no need for prepareToPlay because prepareToPlay is happen automatically when calling play()
        player!.play()
    } catch let error as NSError {
        print("error: \(error.localizedDescription)")
    }
}

本地资产的最佳做法是将其放入其中,assets.xcassets然后按以下方式加载文件:

func playSound() {
    guard let url = Bundle.main.url(forResource: "soundName", withExtension: "mp3") else {
        print("url not found")
        return
    }

    do {
        /// this codes for making this app ready to takeover the device audio
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try AVAudioSession.sharedInstance().setActive(true)

        /// change fileTypeHint according to the type of your audio file (you can omit this)

        /// for iOS 11 onward, use :
        player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue)

        /// else :
        /// player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3)

        // no need for prepareToPlay because prepareToPlay is happen automatically when calling play()
        player!.play()
    } catch let error as NSError {
        print("error: \(error.localizedDescription)")
    }
}

此代码在iOS 10.2.1 xCode 8.2.1上对我有用。对我而言,两条“尝试AVAudioSession”行使在真实设备上实际听到或未听到的声音之间产生了区别。没有他们,就没有声音。
pvanallen

这帮助了我很多,但是我在理解do区块中发生的事情时遇到了一些麻烦。显然player!.play()是自我解释。但是setCategorysetActive方法的目的是什么?
山罗伯逊

2
如果提供AVAudioSessionCategoryPlaybacksetCategory,这样既保证了音频始终扮演即使手机在锁屏或者静音模式。setActive就像告诉系统您的应用已准备好播放音频
Adi Nugroho

@AdiNugroho您认为您可以帮助解决我的问题:stackoverflow.com/questions/44201592/…吗?
JamesG '17

我在iOS 11上遇到了很多麻烦。它曾经可以工作,但现在突然不起作用了。有任何想法吗?
nickdnk

15

iOS 12-Xcode 10 Beta 6-Swift 4.2

仅使用1个IBAction并将所有按钮指向该1个动作。

import AVFoundation

var player = AVAudioPlayer()

@IBAction func notePressed(_ sender: UIButton) {
    print(sender.tag) // testing button pressed tag
    let path = Bundle.main.path(forResource: "note\(sender.tag)", ofType : "wav")!
    let url = URL(fileURLWithPath : path)
    do {
        player = try AVAudioPlayer(contentsOf: url)
        player.play()
    } catch {
        print ("There is an issue with this code!")
    }
}

5
有趣的是,您假设每个人都在观看“ iOS 11和Swift 4-完整的iOS应用程序开发训练

12

如果代码没有产生任何错误,但是您听不到声音,请创建播放器作为实例:

   static var player: AVAudioPlayer!

对我来说,当我进行此更改时,第一个解决方案有效:)


为我工作。有人知道您为什么必须将此设置为静态吗?
kuzdu

3
我不认为它必须是静态的(不再吗?),但似乎您在创建后就让它超出了范围,即使您已经调用play(),它也不会播放?我只是将其作为类的实例变量,并且可以正常工作。
biomiker

3
@kuzdu这是由于您未将放置player在外部范围内。否则,player将被本地化,因此无法播放任何不再存在的声音。
George_E

工作对我来说-无static
托德

5

斯威夫特4、4.2和5

从URL和项目(本地文件)播放音频

import UIKit
import AVFoundation

class ViewController: UIViewController{

var audioPlayer : AVPlayer!

override func viewDidLoad() {
        super.viewDidLoad()
// call what ever function you want.
    }

    private func playAudioFromURL() {
        guard let url = URL(string: "https://geekanddummy.com/wp-content/uploads/2014/01/coin-spin-light.mp3") else {
            print("error to get the mp3 file")
            return
        }
        do {
            audioPlayer = try AVPlayer(url: url as URL)
        } catch {
            print("audio file error")
        }
        audioPlayer?.play()
    }

    private func playAudioFromProject() {
        guard let url = Bundle.main.url(forResource: "azanMakkah2016", withExtension: "mp3") else {
            print("error to get the mp3 file")
            return
        }

        do {
            audioPlayer = try AVPlayer(url: url)
        } catch {
            print("audio file error")
        }
        audioPlayer?.play()
    }

}

3

迅捷3

import AVFoundation


var myAudio: AVAudioPlayer!

    let path = Bundle.main.path(forResource: "example", ofType: "mp3")!
    let url = URL(fileURLWithPath: path)
do {
    let sound = try AVAudioPlayer(contentsOf: url)
    myAudio = sound
    sound.play()
} catch {
    // 
}

//If you want to stop the sound, you should use its stop()method.if you try to stop a sound that doesn't exist your app will crash, so it's best to check that it exists.

if myAudio != nil {
    myAudio.stop()
    myAudio = nil
}

1

首先导入这些库

import AVFoundation

import AudioToolbox    

像这样设置代表

   AVAudioPlayerDelegate

将这些漂亮的代码写在按钮动作或其他动作上:

guard let url = Bundle.main.url(forResource: "ring", withExtension: "mp3") else { return }
    do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try AVAudioSession.sharedInstance().setActive(true)
        player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue)
        guard let player = player else { return }

        player.play()
    }catch let error{
        print(error.localizedDescription)
    }

100%在我的项目中工作并经过测试


2
无需AudioToolbox在此导入。
ixany18年

1

经过Swift 4和iOS 12测试:

import UIKit
import AVFoundation
class ViewController: UIViewController{
    var player: AVAudioPlayer!
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func playTone(number: Int) {
        let path = Bundle.main.path(forResource: "note\(number)", ofType : "wav")!
        let url = URL(fileURLWithPath : path)
        do {
            player = try AVAudioPlayer(contentsOf: url)
            print ("note\(number)")
            player.play()
        }
        catch {
            print (error)
        }
    }

    @IBAction func notePressed(_ sender: UIButton) {
        playTone(number: sender.tag)
    }
}

1

Swift 4(与iOS 12兼容)

var player: AVAudioPlayer?

let path = Bundle.main.path(forResource: "note\(sender.tag)", ofType: "wav")
let url = URL(fileURLWithPath: path ?? "")
    
do {
   player = try AVAudioPlayer(contentsOf: url)
   player?.play()
} catch let error {
   print(error.localizedDescription)
}

我收到以下错误:The operation couldn’t be completed. (OSStatus error 1954115647.)。我到处都看过,找不到解决方法。可能会发布有关它的问题。
George_E

1

游戏风格:

文件Sfx.swift

import AVFoundation

public let sfx = Sfx.shared
public final class Sfx: NSObject {
    
    static let shared = Sfx()
    
    var apCheer: AVAudioPlayer? = nil
    
    private override init() {
        guard let s = Bundle.main.path(forResource: "cheer", ofType: "mp3") else {
            return  print("Sfx woe")
        }
        do {
            apComment = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: s))
        } catch {
            return  print("Sfx woe")
        }
    }
    
    func cheer() { apCheer?.play() }
    func plonk() { apPlonk?.play() }
    func crack() { apCrack?.play() } .. etc
}

代码中的任何地方

sfx.explosion()
sfx.cheer()

1

这是在Swift中查找和播放音频文件的基本代码。

将音频文件添加到Xcode,然后添加以下代码。

import AVFoundation

class ViewController: UIViewController {

   var audioPlayer = AVAudioPlayer() // declare globally

   override func viewDidLoad() {
        super.viewDidLoad()

        guard let sound = Bundle.main.path(forResource: "audiofilename", ofType: "mp3") else {
            print("Error getting the mp3 file from the main bundle.")
            return
        }
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: sound))
        } catch {
            print("Audio file error.")
        }
        audioPlayer.play()
    }

    @IBAction func notePressed(_ sender: UIButton) { // Button action
        audioPlayer.stop()
    }
}

0
import UIKit
import AVFoundation

class ViewController: UIViewController{

    var player: AVAudioPlayer?

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

    @IBAction func notePressed(_ sender: UIButton) {

        guard let url = Bundle.main.url(forResource: "note1", withExtension: "wav") else { return }

        do {
            try AVAudioSession.sharedInstance().setCategory((AVAudioSession.Category.playback), mode: .default, options: [])
            try AVAudioSession.sharedInstance().setActive(true)


            /* The following line is required for the player to work on iOS 11. Change the file type accordingly*/
            player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.wav.rawValue)

            /* iOS 10 and earlier require the following line:
             player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3) *//

            guard let player = player else { return }

            player.play()

        } catch let error {
            print(error.localizedDescription)
        }

    }

}

0
var soundEffect = AVAudioPlayer()

func playSound(_ buttonTag : Int){

    let path = Bundle.main.path(forResource: "note\(buttonTag)", ofType : "wav")!
    let url = URL(fileURLWithPath : path)

    do{
        soundEffect = try AVAudioPlayer(contentsOf: url)
        soundEffect?.play()
        // to stop the spound .stop()
    }catch{
        print ("file could not be loaded or other error!")
    }
}

在Swift 4最新版本中工作。ButtonTag将是界面上按钮的标签。注释位于与Main.storyboard平行的文件夹中的一个文件夹中。每个音符都被命名为note1,note2等。ButtonTag从被单击的按钮中给出数字1、2等,作为参数传递


0

导入AVFoundation

导入AudioToolbox

公共最终课程MP3Player:NSObject {

// Singleton class
static let shared:MP3Player = MP3Player()

private var player: AVAudioPlayer? = nil

// Play only mp3 which are stored in the local
public func playLocalFile(name:String) {
    guard let url = Bundle.main.url(forResource: name, withExtension: "mp3") else { return }

    do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
        try AVAudioSession.sharedInstance().setActive(true)
        player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue)
        guard let player = player else { return }

        player.play()
    }catch let error{
        print(error.localizedDescription)
    }
}

}

//调用此函数

MP3Player.shared.playLocalFile(名称:“ JungleBook”)


-1
import AVFoundation
var player:AVAudioPlayer!

func Play(){
    guard let path = Bundle.main.path(forResource: "KurdishSong", ofType: "mp3")else{return}
    let soundURl = URL(fileURLWithPath: path)
    player = try? AVAudioPlayer(contentsOf: soundURl)
    player.prepareToPlay()
    player.play()
    //player.pause()
    //player.stop()
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.