Cum să redați un sunet folosind Swift? (Programare, Ios, Swift, Avfoundation)

Michel Kansou a intrebat.

Aș dori să redau un sunet folosind Swift.

Codul meu a funcționat în Swift 1.0, dar acum nu mai funcționează în Swift 2 sau mai nou.

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

Comentarii

  • Aruncați o privire la SwiftySound. Mai multe detalii în acest răspuns. –  > Por Adam.
  • Dacă doriți doar un sunet de la sistem, atunci vedeți: Utilizarea sunetelor sistemului existent în aplicația iOS –  > Por Miere.
16 răspunsuri
Devapploper

Cel mai preferabil ar fi să utilizați AVFoundation. Acesta oferă toate elementele esențiale pentru a lucra cu medii audiovizuale.

Actualizare: Compatibil cu Swift 2, Swift 3 și Swift 4 așa cum au sugerat unii dintre dumneavoastră în comentarii.


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

Asigurați-vă că schimbați numele melodiei, precum și numele de extensia.Fișierul trebuie să fie importat în mod corespunzător (Project Build Phases > Copy Bundle Resources). Este posibil să doriți să îl plasați în assets.xcassets pentru o mai mare comoditate.

Pentru fișiere de sunet scurte, ați putea dori să alegeți formate audio necomprimate, cum ar fi .wav deoarece acestea au cea mai bună calitate și un impact redus asupra calculatorului. Consumul mai mare de spațiu pe disc nu ar trebui să fie o problemă pentru fișierele audio scurte. Cu cât fișierele sunt mai lungi, ar fi bine să alegeți un format comprimat, cum ar fi .mp3 etc. pp. Verificați formatele audio compatibile de pe CoreAudio.


Fun-fact: Există mici biblioteci care facilitează și mai mult redarea sunetelor. 🙂
De exemplu: SwiftySound

Comentarii

  • Îmi pare rău, dar acest cod nu mai funcționează în swift 2.0, ci afișează o eroare ” Call can throw, but it is not marked with ‘try’ and the error is not handled” – –  > Por Michel Kansou.
  • Înlocuiți bgMusic = AVAudioPlayer(contentsOfURL: bgMusicURL, fileTypeHint: nil) cu do { bgMusic = try AVAudioPlayer(contentsOfURL: bgMusicURL, fileTypeHint: nil) } catch _ { return \ if it doesn't exist, don't play it} –  > Por saagarjha.
  • A trebuit să fac din obiectul AVAudioPlayer o variabilă de instanță pentru ca acest lucru să funcționeze. Ca variabilă locală nu ar fi redat nimic, fără eroare. Nici delegații nu ar fi fost chemați. –  > Por Kaleb.
  • De ce folosești un guard aici? player = try AVAudioPlayer(contentsOf: url) guard let player = player else { return } mi se pare o muncă în plus, de ce nu o faci doar let player = try AVAudioPlayer(contentsOf: url)? –  > Por xandermonkey.
  • Utilizarea unei declarații de gardă vă protejează destul de bine de blocarea din cauza unei valori nule. –  > Por Aashish.
Adi Nugroho

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

Cea mai bună practică pentru activele locale este de a le pune în interiorul assets.xcassets și să încărcați fișierul astfel :

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

Comentarii

  • Acest cod a funcționat pentru mine pe iOS 10.2.1, xCode 8.2.1. Pentru mine, cele două linii „try AVAudioSession” au făcut diferența între sunetele care se auzeau efectiv pe un dispozitiv real sau nu. Fără ele, niciun sunet. –  > Por pvanallen.
  • Acest lucru m-a ajutat o tonă, am ceva probleme în a înțelege ce se întâmplă în do bloc, deși. evident. player!.play() este de la sine înțeles. Dar care este scopul setCategory și setActive metode? –  > Por Shan Robertson.
  • Dacă oferiți AVAudioSessionCategoryPlayback la setCategory, se va asigura că sunetul este întotdeauna redat, chiar dacă telefonul este în ecranul de blocare sau în modul silențios. setActive este ca și cum ai spune sistemului că aplicația ta este pregătită să redea audio –  > Por Adi Nugroho.
  • @AdiNugroho crezi că mă poți ajuta cu întrebarea mea: stackoverflow.com/questions/44201592/… ? –  > Por JamesG.
  • Am o mulțime de probleme cu acest lucru pe iOS 11. Obișnuia să funcționeze, dar acum brusc nu mai funcționează. Aveți vreo idee? –  > Por nickdnk.
Tony Ward

iOS 12 – Xcode 10 beta 6 – Swift 4.2

Folosiți doar 1 IBAction și îndreptați toate butoanele către acea 1 acțiune.

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

Comentarii

  • Este amuzant că presupui că toată lumea se uită la „iOS 11 & Swift 4 – The Complete iOS App Development Bootcamp” – -.  > Por karlingen.
EranKT

Dacă codul nu generează nicio eroare, dar nu auziți sunetul – creați playerul ca instanță:

   static var player: AVAudioPlayer!

Pentru mine, prima soluție a funcționat când am făcut această modificare 🙂

Comentarii

  • Pentru mine funcționează. Știe cineva de ce trebuie să setați acest lucru la static? –  > Por kuzdu.
  • Nu cred că trebuie să fie static (mai este?), dar se pare că poate dacă îl lași să iasă din scope după ce a fost creat, chiar dacă ai apelat play(), nu se va reda? Eu doar am făcut-o o variabilă de instanță a clasei mele și funcționează. –  > Por biomiker.
  • @kuzdu Acest lucru se datorează faptului că nu ai plasat player în afara domeniului de aplicare. În caz contrar, player este delocalizat și, prin urmare, nu poate reda niciun sunet, deoarece nu mai există. –  > Por George_E.
  • A funcționat pentru mine – fără static –  > Por Todd.
  • A funcționat și pentru mine! Mulțumesc! –  > Por Maverick447.
Akbar Khan

Swift 4, 4.2 și 5

Redă audio de la URL și din proiectul dvs. (Fișier local)

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

}

Mr.Shin

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
}

Dl Javed Multani

Importați mai întâi aceste biblioteci

import AVFoundation

import AudioToolbox    

setați delegatul astfel

   AVAudioPlayerDelegate

scrieți acest cod drăguț pe acțiunea butonului sau ceva acțiune:

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% de lucru în proiectul meu și testat

Comentarii

  • Nu este nevoie să importați AudioToolbox în acest loc. –  > Por ixany.
Hunter Akers
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)
        }

    }

}

Ershin Bot

Testat cu Swift 4 și 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)
    }
}

imdpk

Swift 4 (compatibil cu 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)
}

Comentarii

  • Primesc următoarea eroare: The operation couldn’t be completed. (OSStatus error 1954115647.). Am căutat peste tot și nu găsesc o soluție. S-ar putea să postez o întrebare despre asta. –  > Por George_E.
Fattie

Stil de joc:

fișier 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
}

Oriunde în cod

sfx.explosion()
sfx.cheer()

M VIJAY

Acesta este codul de bază pentru a găsi și reda un fișier audio în Swift.

Adăugați fișierul audio în Xcode și adăugați codul de mai jos.

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

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

funcționează în swift 4 ultima versiune. ButtonTag ar fi o etichetă pe un buton de pe interfața dvs. Notele se află într-un dosar într-un dosar paralel cu Main.storyboard. Fiecare notă se numește ca note1, note2, etc. ButtonTag dă numărul 1, 2, etc. de la butonul pe care s-a făcut clic, care este trecut ca parametru.

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

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

Pentru a apela această funcție

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

Sadiq Qasmi

Pentru Swift 5AVFoundation

Cod simplu fără gestionarea erorilor pentru a reda audio din calea locală

import AVFoundation
var audio:AVPlayer!

func stopAlarm() {
    // To pause or stop audio in swift 5 audio.stop() isn't working
    audio.pause()
}

func playAlarm() {
    // need to declare local path as url
    let url = Bundle.main.url(forResource: "Alarm", withExtension: "mp3")
    // now use declared path 'url' to initialize the player
    audio = AVPlayer.init(url: url!)
    // after initialization play audio its just like click on play button
    audio.play()
}