Bagaimana cara memutar suara menggunakan Swift?

162

Saya ingin memutar suara menggunakan Swift.

Kode saya berfungsi di Swift 1.0 tetapi sekarang tidak berfungsi lagi di Swift 2 atau yang lebih baru.

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
  }
}
Michel Kansou
sumber
1
Lihat SwiftySound . Lebih detail dalam jawaban ini .
Adam
Jika Anda hanya ingin suara dari sistem, lihat: Menggunakan suara sistem yang ada di Aplikasi iOS
Madu

Jawaban:

320

Lebih disukai Anda mungkin ingin menggunakan AVFoundation . Ini menyediakan semua hal penting untuk bekerja dengan media audiovisual.

Pembaruan: Kompatibel dengan Swift 2 , Swift 3 dan Swift 4 seperti yang disarankan oleh beberapa dari Anda di komentar.


Swift 2.3.0

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

Cepat 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 (kompatibel dengan 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)
    }
}

Pastikan untuk mengubah nama lagu Anda serta ekstensinya . File harus diimpor dengan benar ( Project Build Phases> Copy Bundle Resources). Anda mungkin ingin menempatkannya assets.xcassetsuntuk kenyamanan yang lebih baik.

Untuk file suara pendek Anda mungkin ingin menggunakan format audio non-terkompresi seperti .wavkarena mereka memiliki kualitas terbaik dan dampak cpu rendah. Konsumsi ruang disk yang lebih tinggi seharusnya tidak menjadi masalah besar untuk file suara pendek. Semakin panjang file, Anda mungkin ingin menggunakan format terkompresi seperti .mp3dll. Pp. Periksa format audio yang kompatibel dari CoreAudio.


Fakta menyenangkan: Ada perpustakaan kecil yang rapi yang membuat pemutaran suara menjadi lebih mudah. :)
Misalnya: SwiftySound

Devapploper
sumber
Maaf, tetapi kode ini tidak berfungsi lagi di swift 2.0 itu meminta kesalahan "Panggilan bisa melempar, tetapi tidak ditandai dengan 'coba' dan kesalahan tidak ditangani"
Michel Kansou
2
Gantikan bgMusic = AVAudioPlayer(contentsOfURL: bgMusicURL, fileTypeHint: nil)dengando { bgMusic = try AVAudioPlayer(contentsOfURL: bgMusicURL, fileTypeHint: nil) } catch _ { return \\ if it doesn't exist, don't play it}
saagarjha
12
Saya harus menjadikan objek AVAudioPlayer sebagai variabel instan agar ini berfungsi. Sebagai variabel lokal, itu tidak akan memainkan apa pun, tidak ada kesalahan. Delegasi juga tidak akan dipanggil.
Kaleb
2
Mengapa Anda menggunakan penjaga di sini? player = try AVAudioPlayer(contentsOf: url) guard let player = player else { return }Sepertinya pekerjaan tambahan bagi saya, mengapa tidak let player = try AVAudioPlayer(contentsOf: url)?
xandermonkey
2
Menggunakan pernyataan penjaga membuat Anda cukup aman dari crash karena nilai nihil.
Aashish
44

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

Praktik terbaik untuk aset lokal adalah memasukkannya ke dalam assets.xcassetsdan Anda memuat file seperti ini:

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)")
    }
}
Adi Nugroho
sumber
Kode ini berfungsi untuk saya di iOS 10.2.1, xCode 8.2.1. Bagi saya, dua baris "coba AVAudioSession" membuat perbedaan antara suara yang benar-benar didengar di perangkat nyata atau tidak. Tanpa mereka, tidak ada suara.
pvanallen
Ini sangat membantu saya, saya kesulitan memahami apa yang terjadi di doblok tersebut. jelas player!.play()sudah cukup jelas. Tapi apa tujuan dari metode setCategorydan setActive?
Shan Robertson
2
Jika Anda memberikan AVAudioSessionCategoryPlaybackuntuk setCategory, itu akan memastikan audio selalu dimainkan meski ponsel dalam layar kunci atau dalam mode silent. setActiveseperti memberi tahu sistem bahwa aplikasi Anda siap memutar audio
Adi Nugroho
@AdiNugroho menurut Anda apakah Anda dapat membantu dengan pertanyaan saya: stackoverflow.com/questions/44201592/… ?
JamesG
Saya mengalami banyak masalah dengan ini di iOS 11. Dulu berfungsi tetapi sekarang tiba-tiba tidak. Ada ide?
nickdnk
16

iOS 12 - Xcode 10 beta 6 - Swift 4.2

Gunakan hanya 1 IBAction dan arahkan semua tombol ke 1 tindakan tersebut.

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!")
    }
}
Tony Ward
sumber
6
Lucu sekali Anda berasumsi bahwa semua orang menonton "iOS 11 & Swift 4 - Kamp Pelatihan Pengembangan Aplikasi iOS Lengkap" 😂😂
karlingen
13

Jika kode tidak menghasilkan kesalahan apa pun, tetapi Anda tidak mendengar suara - buat pemutar sebagai contoh:

   static var player: AVAudioPlayer!

Bagi saya, solusi pertama berhasil ketika saya melakukan perubahan ini :)

EranKT
sumber
Bekerja untuk saya. Adakah yang tahu mengapa Anda harus menyetel ini ke statis?
kuzdu
3
Saya tidak berpikir itu harus statis (lagi?), Tetapi tampaknya mungkin jika Anda membiarkannya keluar dari ruang lingkup setelah dibuat, bahkan jika Anda memanggil play (), itu tidak akan diputar? Saya baru saja menjadikannya sebagai variabel instan kelas saya dan berhasil.
biomiker
3
@kuzdu Ini karena Anda tidak menempatkan playerdi luar ruang lingkup. Jika tidak, playerakan terdelokalisasi dan karenanya tidak dapat memutar suara apa pun karena sudah tidak ada lagi.
George_E
Bekerja untuk saya - tanpastatic
Todd
8

Swift 4, 4.2 dan 5

Putar audio dari URL dan dari proyek Anda (File Lokal)

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

}
Akbar Khan
sumber
3

Cepat 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
}
Tuan Shin
sumber
1

Impor pertama perpustakaan ini

import AVFoundation

import AudioToolbox    

atur delegasi seperti ini

   AVAudioPlayerDelegate

tulis kode cantik ini pada aksi tombol atau aksi sesuatu:

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% bekerja dalam proyek saya dan diuji

Tuan Javed Multani
sumber
2
Tidak perlu mengimpor AudioToolboxdi tempat ini.
ixany
1

Diuji dengan Swift 4 dan 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)
    }
}
Ershin Bot
sumber
1

Swift 4 (kompatibel dengan 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)
}
imdpk
sumber
Saya mendapatkan error berikut: The operation couldn’t be completed. (OSStatus error 1954115647.). Saya telah mencari ke mana-mana, dan tidak dapat menemukan solusi. Mungkin memposting pertanyaan tentang itu.
George_E
1

Gaya permainan:

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

Di mana saja dalam kode

sfx.explosion()
sfx.cheer()
Gendut
sumber
1

Ini adalah kode dasar untuk mencari dan memutar file audio di Swift.

Tambahkan file audio Anda ke Xcode Anda dan tambahkan kode di bawah ini.

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()
    }
}
M VIJAY
sumber
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)
        }

    }

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

bekerja di swift 4 versi terbaru. ButtonTag akan menjadi tag pada tombol di antarmuka Anda. Catatan berada dalam folder di folder yang sejajar dengan Main.storyboard. Setiap nada dinamai sebagai note1, note2, dll. ButtonTag memberikan nomor 1, 2, dll dari tombol yang diklik yang dilewatkan sebagai parameter

Egi Messito
sumber
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()
}
Mobin Valadi
sumber
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)
        }
    }
}

Untuk memanggil fungsi ini

MP3Player.shared.playLocalFile(name: "JungleBook")
Nirbhay Singh
sumber