วิธีเล่นเสียงโดยใช้ Swift


162

ฉันต้องการเล่นเสียงโดยใช้ 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 รายละเอียดเพิ่มเติมในคำตอบนี้
Adam

ถ้าคุณเพียงต้องการเสียงจากระบบแล้วดู: การใช้เสียงระบบที่มีอยู่ใน iOS App
น้ำผึ้ง

คำตอบ:


320

ส่วนใหญ่โดยเฉพาะอย่างยิ่งที่คุณอาจต้องการที่จะใช้AVFoundation มีสิ่งจำเป็นทั้งหมดสำหรับการทำงานกับสื่อโสตทัศน์

อัปเดต:เข้ากันได้กับSwift 2 , Swift 3และSwift 4ตามที่คุณบางคนแนะนำในความคิดเห็น


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

สวิฟต์ 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เนื่องจากมีคุณภาพดีที่สุดและมีผลกระทบต่อซีพียูต่ำ การใช้พื้นที่ดิสก์ที่สูงขึ้นไม่ควรเป็นเรื่องใหญ่สำหรับไฟล์เสียงสั้น ๆ ไฟล์มีความยาวมากขึ้นคุณอาจต้องการใช้รูปแบบการบีบอัดเช่น.mp3เป็นต้นหน้าตรวจสอบรูปแบบเสียงที่เข้ากันได้ของCoreAudio.


เรื่องสนุก:มีห้องสมุดเล็ก ๆ ที่เป็นระเบียบซึ่งทำให้การเล่นเสียงง่ายยิ่งขึ้น :)
ตัวอย่างเช่นSwiftySound


ขออภัยรหัสนี้ใช้งานไม่ได้อีกต่อไปใน swift 2.0 ซึ่งแจ้งข้อผิดพลาด "Call can throw แต่ไม่มีเครื่องหมาย" ลอง "และไม่มีการจัดการข้อผิดพลาด"
Michel Kansou

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

12
ฉันต้องทำให้ออบเจ็กต์ AVAudioPlayer เป็นตัวแปรอินสแตนซ์เพื่อให้มันใช้งานได้ ในฐานะที่เป็นตัวแปรท้องถิ่นจะไม่เล่นอะไรเลยไม่มีข้อผิดพลาด ผู้รับมอบสิทธิ์จะไม่ถูกเรียกด้วยเช่นกัน
Kaleb

2
ทำไมคุณถึงใช้ยามที่นี่? player = try AVAudioPlayer(contentsOf: url) guard let player = player else { return }ดูเหมือนจะทำงานพิเศษให้ฉันทำไมไม่ทำlet player = try AVAudioPlayer(contentsOf: url)ล่ะ?
xandermonkey

2
การใช้คำสั่งป้องกันทำให้คุณค่อนข้างปลอดภัยจากการหยุดทำงานเนื่องจากค่าศูนย์
Aashish

44

สำหรับ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()เป็นการอธิบายตนเอง แต่จุดประสงค์setCategoryและsetActiveวิธีการคืออะไร?
Shan Robertson

2
ถ้าคุณให้AVAudioSessionCategoryPlaybackไปsetCategoryก็จะให้แน่ใจว่าเสียงจะเล่นเสมอแม้ว่าโทรศัพท์อยู่ในการล็อคหน้าจอหรือในโหมดเงียบ setActiveก็เหมือนกับการบอกระบบว่าแอปของคุณพร้อมที่จะเล่นเสียง
Adi Nugroho

@AdiNugroho คุณคิดว่าจะช่วยตอบคำถามของฉันได้ไหม: stackoverflow.com/questions/44201592/… ?
JamesG

ฉันมีปัญหากับสิ่งนี้บน iOS 11 มันเคยใช้งานได้ แต่ตอนนี้กลับไม่ทำงาน ความคิดใด ๆ ?
nickdnk

16

iOS 12 - Xcode 10 เบต้า 6 - Swift 4.2

ใช้ IBAction เพียง 1 ครั้งแล้วชี้ปุ่มทั้งหมดไปที่ 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!")
    }
}

6
เป็นเรื่องตลกที่คุณสมมติว่าทุกคนกำลังดู "iOS 11 & Swift 4 - The Complete iOS App Development Bootcamp" 😂😂
karlingen

13

หากรหัสไม่สร้างข้อผิดพลาดใด ๆ แต่คุณไม่ได้ยินเสียง - สร้างโปรแกรมเล่นเป็นอินสแตนซ์:

   static var player: AVAudioPlayer!

สำหรับฉันวิธีแก้ปัญหาแรกใช้ได้ผลเมื่อฉันทำการเปลี่ยนแปลงนี้ :)


ใช้ได้ผลสำหรับฉัน มีใครรู้บ้างว่าทำไมคุณต้องตั้งค่านี้เป็นแบบคงที่?
kuzdu

3
ฉันไม่คิดว่ามันจะต้องคงที่ (อีกต่อไป?) แต่ดูเหมือนว่าบางทีถ้าคุณปล่อยให้มันออกไปนอกขอบเขตหลังจากสร้างขึ้นแม้ว่าคุณจะเรียกว่า play () มันจะไม่เล่น? ฉันเพิ่งทำให้มันเป็นตัวแปรอินสแตนซ์ของคลาสของฉันและมันใช้งานได้
biomiker

3
@kuzdu นี่เป็นเพราะคุณไม่ได้วางไว้playerในขอบเขตภายนอก มิฉะนั้นplayerจะถูกเบี่ยงเบนความสนใจดังนั้นจึงไม่สามารถเล่นเสียงใด ๆ ได้เนื่องจากไม่มีอยู่แล้ว
George_E

ทำงานให้ฉัน - ไม่มีstatic
ทอดด์

8

Swift 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ในสถานที่นี้
ixany

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 จะเป็นแท็กบนปุ่มบนอินเทอร์เฟซของคุณ Notes อยู่ในโฟลเดอร์ในโฟลเดอร์ขนานกับ Main.storyboard โน้ตทุกตัวมีชื่อว่า note1, note2 และอื่น ๆ ButtonTag ให้หมายเลข 1, 2 ฯลฯ จากปุ่มที่คลิกซึ่งจะส่งผ่านเป็นพารามิเตอร์


0
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()
}

0
import AVFoundation

import AudioToolbox

public final class 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(name: "JungleBook")
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.