Wie spiele ich einen Sound mit Swift?

148

Ich möchte einen Sound mit Swift spielen.

Mein Code funktionierte in Swift 1.0, aber jetzt funktioniert er in Swift 2 oder neuer nicht mehr.

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
quelle
1
Schauen Sie sich SwiftySound an . Weitere Details in dieser Antwort .
Adam
Wenn Sie nur einen Sound vom System wünschen, lesen Sie: Verwenden vorhandener System-Sounds in der iOS App
Honey

Antworten:

291

Am besten bevorzugen Sie die Verwendung von AVFoundation . Es bietet alle wichtigen Informationen für die Arbeit mit audiovisuellen Medien.

Update: Kompatibel mit Swift 2 , Swift 3 und Swift 4, wie von einigen von Ihnen in den Kommentaren vorgeschlagen.


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 (iOS 13 kompatibel)

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

Stellen Sie sicher, dass Sie den Namen Ihrer Melodie sowie die Erweiterung ändern . Die Datei muss ordnungsgemäß importiert werden ( Project Build Phases> Copy Bundle Resources). Möglicherweise möchten Sie es assets.xcassetsfür mehr Komfort platzieren.

Für kurze Audiodateien sollten Sie sich für nicht komprimierte Audioformate entscheiden, z. B. .wavweil sie die beste Qualität und eine geringe CPU-Auswirkung haben. Der höhere Speicherplatzverbrauch sollte für kurze Sounddateien keine große Rolle spielen. Je länger die Dateien sind, desto mehr möchten Sie möglicherweise ein komprimiertes Format wie z. B. .mp3S. wählen. Überprüfen Sie die kompatiblen Audioformate von CoreAudio.


Wissenswertes: Es gibt nette kleine Bibliotheken, die das Abspielen von Sounds noch einfacher machen. :)
Zum Beispiel: SwiftySound

Devapploper
quelle
Entschuldigung, aber dieser Code funktioniert in Swift 2.0 nicht mehr. Es wird ein Fehler angezeigt. "Anruf kann ausgelöst werden, aber er ist nicht mit 'try' markiert und der Fehler wird nicht behandelt."
Michel Kansou
2
Ersetzen Sie bgMusic = AVAudioPlayer(contentsOfURL: bgMusicURL, fileTypeHint: nil)durchdo { bgMusic = try AVAudioPlayer(contentsOfURL: bgMusicURL, fileTypeHint: nil) } catch _ { return \\ if it doesn't exist, don't play it}
saagarjha
11
Ich musste das AVAudioPlayer-Objekt zu einer Instanzvariablen machen, damit dies funktioniert. Als lokale Variable würde es nichts abspielen, kein Fehler. Auch die Delegierten würden nicht angerufen.
Kaleb
2
Warum benutzt du hier eine Wache? player = try AVAudioPlayer(contentsOf: url) guard let player = player else { return }scheint mir zusätzliche Arbeit zu sein, warum nicht einfach let player = try AVAudioPlayer(contentsOf: url)?
Xandermonkey
2
Die Verwendung einer Guard-Anweisung schützt Sie ziemlich vor Abstürzen aufgrund des Nullwerts.
Aashish
43

Für 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)")
    }
}

Die beste Vorgehensweise für lokale Assets besteht darin, sie einzulegen assets.xcassetsund die Datei wie folgt zu laden:

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
quelle
Dieser Code funktionierte für mich unter iOS 10.2.1, xCode 8.2.1. Für mich haben die beiden Zeilen "try AVAudioSession" den Unterschied zwischen den Geräuschen gemacht, die tatsächlich auf einem realen Gerät zu hören sind oder nicht. Ohne sie kein Ton.
Pvanallen
Das hat mir sehr geholfen, aber ich habe einige Probleme zu verstehen, was im doBlock passiert . ist offensichtlich player!.play()selbsterklärend. Aber was ist der Zweck der setCategoryund setActiveMethoden?
Shan Robertson
2
Wenn Sie zur Verfügung stellen AVAudioSessionCategoryPlaybackzu setCategory, wird dafür sorgen , es das Audio immer noch gespielt wird , obwohl Telefon im Sperrbildschirm oder im Silent - Modus ist. setActiveist wie dem System zu sagen, dass Ihre App bereit ist, Audio abzuspielen
Adi Nugroho
@AdiNugroho Glaubst du, du könntest bei meiner Frage helfen: stackoverflow.com/questions/44201592/… ?
JamesG
Ich habe große Probleme damit unter iOS 11. Früher hat es funktioniert, jetzt funktioniert es plötzlich nicht mehr. Irgendwelche Ideen?
Nickdnk
15

iOS 12 - Xcode 10 Beta 6 - Swift 4.2

Verwenden Sie nur 1 IBAction und zeigen Sie mit allen Schaltflächen auf diese 1 Aktion.

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
quelle
5
Es ist lustig, dass Sie davon ausgehen, dass alle "iOS 11 & Swift 4 - Das komplette Bootcamp zur Entwicklung von iOS-Apps" sehen
Karlingen
12

Wenn der Code keinen Fehler generiert, Sie jedoch keinen Ton hören, erstellen Sie den Player als Instanz:

   static var player: AVAudioPlayer!

Für mich hat die erste Lösung funktioniert, als ich diese Änderung vorgenommen habe :)

EranKT
quelle
Funktioniert bei mir. Weiß jemand, warum Sie dies auf statisch setzen müssen?
Kuzdu
3
Ich denke nicht, dass es statisch sein muss (mehr?), Aber es scheint vielleicht, dass es nicht abgespielt wird, wenn Sie es nach seiner Erstellung aus dem Gültigkeitsbereich entfernen, selbst wenn Sie play () aufgerufen haben? Ich habe es gerade zu einer Instanzvariablen meiner Klasse gemacht und es funktioniert.
Biomiker
3
@kuzdu Dies liegt daran, dass Sie das nicht playerin den Außenbereich stellen. Andernfalls playerwird delokalisiert und kann daher keinen Ton wiedergeben, da dieser nicht mehr vorhanden ist.
George_E
Arbeitete für mich - ohnestatic
Todd
5

Swift 4, 4.2 und 5

Spielen Sie Audio von der URL und von Ihrem Projekt ab (lokale Datei)

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
quelle
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
}
Mr.Shin
quelle
1

Importieren Sie zuerst diese Bibliotheken

import AVFoundation

import AudioToolbox    

Setze den Delegaten so

   AVAudioPlayerDelegate

Schreiben Sie diesen hübschen Code für eine Tastenaktion oder eine Aktion:

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% arbeiten in meinem Projekt und getestet

Mr.Javed Multani
quelle
2
An AudioToolboxdieser Stelle muss nicht importiert werden .
Ixany
1

Getestet mit Swift 4 und 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
quelle
1

Swift 4 (iOS 12 kompatibel)

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
quelle
Ich erhalte folgende Fehlermeldung : The operation couldn’t be completed. (OSStatus error 1954115647.). Ich habe überall gesucht und kann keine Lösung finden. Könnte eine Frage dazu posten.
George_E
1

Spielstil:

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

Überall im Code

sfx.explosion()
sfx.cheer()
Fattie
quelle
1

Dies ist der grundlegende Code zum Suchen und Abspielen einer Audiodatei in Swift.

Fügen Sie Ihre Audiodatei zu Ihrem Xcode hinzu und fügen Sie den folgenden Code hinzu.

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

funktioniert in Swift 4 neueste Version. ButtonTag wäre ein Tag auf einer Schaltfläche auf Ihrer Benutzeroberfläche. Notizen befinden sich in einem Ordner in einem Ordner parallel zu Main.storyboard. Jede Note wird als Note1, Note2 usw. bezeichnet. ButtonTag gibt die Nummer 1, 2 usw. über die angeklickte Schaltfläche an, die als Parameter übergeben wird

Egi Messito
quelle
0

AVFoundation importieren

AudioToolbox importieren

öffentliche letzte Klasse 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)
    }
}

}}

// Um ​​diese Funktion aufzurufen

MP3Player.shared.playLocalFile (Name: "JungleBook")

Nirbhay Singh
quelle
-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()
}
Mobin Valadi
quelle