Làm cách nào để phát âm thanh bằng Swift?


148

Tôi muốn phát âm thanh bằng Swift.

Mã của tôi đã hoạt động trong Swift 1.0 nhưng bây giờ nó không hoạt động nữa trong Swift 2 hoặc mới hơn.

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
Hãy xem SwiftySound . Thêm chi tiết trong câu trả lời này .
Adam

Nếu bạn chỉ muốn một âm thanh từ hệ thống thì hãy xem: Sử dụng âm thanh hệ thống hiện có trong Ứng dụng iOS
Honey

Câu trả lời:


291

Tốt nhất là bạn có thể muốn sử dụng AVFoundation . Nó cung cấp tất cả các yếu tố cần thiết để làm việc với phương tiện nghe nhìn.

Cập nhật: Tương thích với Swift 2 , Swift 3Swift 4 theo đề xuất của một số bạn trong các nhận xét.


Swift 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)
    }
}

Swift 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 (tương thích 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)
    }
}

Đảm bảo thay đổi tên của giai điệu cũng như phần mở rộng . Các tập tin cần phải được nhập đúng ( Project Build Phases> Copy Bundle Resources). Bạn có thể muốn đặt nó vào assets.xcassetsđể thuận tiện hơn.

Đối với các tệp âm thanh ngắn, bạn có thể muốn sử dụng các định dạng âm thanh không nén như .wavvì chúng có chất lượng tốt nhất và tác động cpu thấp. Tiêu thụ không gian đĩa cao hơn không phải là một vấn đề lớn đối với các tệp âm thanh ngắn. Các tệp càng dài, bạn có thể muốn sử dụng định dạng nén, .mp3v.v. Trang. Kiểm tra các định dạng âm thanh tương thích của CoreAudio.


Sự thật thú vị: Có những thư viện nhỏ gọn giúp cho việc phát âm thanh trở nên dễ dàng hơn. :)
Ví dụ: SwiftySound


Xin lỗi nhưng mã này không hoạt động nữa trong swift 2.0, nó nhắc lỗi "Cuộc gọi có thể ném, nhưng nó không được đánh dấu là 'thử' và lỗi không được xử lý"
Michel Kansou

2
Thay thế bgMusic = AVAudioPlayer(contentsOfURL: bgMusicURL, fileTypeHint: nil)bằngdo { bgMusic = try AVAudioPlayer(contentsOfURL: bgMusicURL, fileTypeHint: nil) } catch _ { return \\ if it doesn't exist, don't play it}
saagarjha

11
Tôi đã phải làm cho đối tượng AVAudioPlayer trở thành một biến thể hiện để làm việc này. Là một biến cục bộ, nó sẽ không chơi bất cứ thứ gì, không có lỗi. Các đại biểu cũng sẽ không được gọi.
Kaleb

2
Tại sao bạn sử dụng một người bảo vệ ở đây? player = try AVAudioPlayer(contentsOf: url) guard let player = player else { return }Có vẻ như làm thêm cho tôi, tại sao không chỉ let player = try AVAudioPlayer(contentsOf: url)?
xandermonkey

2
Sử dụng một tuyên bố bảo vệ làm cho bạn khá an toàn khỏi bị rơi do giá trị không.
Aashish

43

Dành cho 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)")
    }
}

Cách thực hành tốt nhất cho các tài sản cục bộ là đặt nó vào bên trong assets.xcassetsvà bạn tải tệp như thế này:

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)")
    }
}

Mã này hoạt động với tôi trên iOS 10.2.1, xCode 8.2.1. Đối với tôi, hai dòng "thử AVAudioSession" đã tạo ra sự khác biệt giữa âm thanh thực sự được nghe trên một thiết bị thực hay không. Không có chúng, không có âm thanh.
pvanallen

Điều này giúp tôi rất nhiều, tôi đang gặp một số khó khăn để hiểu những gì xảy ra trong dokhối. rõ ràng player!.play()là tự giải thích. Nhưng mục đích của setCategorysetActivephương pháp là gì?
Shan Robertson

2
Nếu bạn cung cấp AVAudioSessionCategoryPlaybackcho setCategory, nó sẽ đảm bảo âm thanh luôn được phát ngay cả khi điện thoại ở màn hình khóa hoặc ở chế độ im lặng. setActivegiống như nói với hệ thống rằng ứng dụng của bạn đã sẵn sàng phát âm thanh
Adi Nugroho

@AdiNugroho bạn có nghĩ rằng bạn có thể giúp với câu hỏi của tôi không: stackoverflow.com/questions/44201592/ .
JamesG

Tôi gặp nhiều rắc rối với điều này trên iOS 11. Nó đã từng hoạt động nhưng bây giờ nó đột nhiên không hoạt động. Có ý kiến ​​gì không?
nickdnk

15

iOS 12 - Xcode 10 beta 6 - Swift 4.2

Chỉ sử dụng 1 IBAction và trỏ tất cả các nút vào 1 hành động đó.

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
Thật buồn cười khi bạn cho rằng mọi người đang xem "iOS 11 & Swift 4 - Bootcamp phát triển ứng dụng iOS hoàn chỉnh"
karlingen

12

Nếu mã không tạo ra bất kỳ lỗi nào, nhưng bạn không nghe thấy âm thanh - hãy tạo trình phát làm ví dụ:

   static var player: AVAudioPlayer!

Đối với tôi giải pháp đầu tiên có hiệu quả khi tôi thực hiện thay đổi này :)


Làm việc cho tôi. Có ai biết tại sao bạn phải đặt cái này thành tĩnh không?
kuzdu

3
Tôi không nghĩ nó phải tĩnh (nữa?), Nhưng có vẻ như nếu bạn để nó vượt ra khỏi phạm vi sau khi nó được tạo, ngay cả khi bạn đã gọi play (), nó sẽ không chơi? Tôi chỉ biến nó thành một biến thể hiện của lớp và nó hoạt động.
khối

3
@kuzdu Điều này là do bạn không đặt playertrong phạm vi bên ngoài. Mặt khác, playerđược định vị và do đó không thể phát bất kỳ âm thanh nào vì nó không còn tồn tại.
George_E

Làm việc cho tôi - không cóstatic
Todd

5

Swift 4, 4.2 và 5

Phát âm thanh từ URL và từ dự án của bạn (Tệp cục bộ)

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

Swift 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

Đầu tiên nhập các thư viện này

import AVFoundation

import AudioToolbox    

đặt đại biểu như thế này

   AVAudioPlayerDelegate

viết mã đẹp này vào hành động nút hoặc hành động gì đó:

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% làm việc trong dự án của tôi và đã thử nghiệm


2
Không cần phải nhập AudioToolboxở nơi này.
ixany

1

Đã thử nghiệm với Swift 4 và 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 (tương thích 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)
}

Tôi nhận được lỗi sau : The operation couldn’t be completed. (OSStatus error 1954115647.). Tôi đã tìm kiếm khắp nơi, và không thể tìm ra giải pháp. Có thể gửi một câu hỏi về nó.
George_E

1

Phong cách chơi:

tập tin 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
}

Bất cứ nơi nào trong mã

sfx.explosion()
sfx.cheer()

1

Đây là mã cơ bản để tìm và phát tệp âm thanh trong Swift.

Thêm tệp âm thanh của bạn vào Xcode của bạn và thêm mã bên dưới.

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!")
    }
}

hoạt động trong swift 4 phiên bản mới nhất. ButtonTag sẽ là một thẻ trên một nút trên giao diện của bạn. Ghi chú nằm trong một thư mục trong thư mục song song với Main.storyboard. Mỗi ghi chú được đặt tên là note1, note2, v.v. NútTag đang đưa ra số 1, 2, v.v.


0

nhập AVFoundation

nhập AudioToolbox

lớp cuối cùng công khai 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)
    }
}

}

// Để gọi hàm này

MP3Player. Shared.playLocalFile (tên: "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()
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.