Як відтворювати звук за допомогою Swift?


148

Я хотів би відтворити звук за допомогою 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 . Більш детально у цій відповіді .
Адам

Якщо ви просто хочете отримати звук із системи, то дивіться: Використання існуючих системних звуків у додатку iOS
мед

Відповіді:


291

Найбільш переважно ви можете використовувати AVFoundation . Він пропонує всі необхідні для роботи з аудіовізуальними носіями інформації.

Оновлення: сумісний із Swift 2 , Swift 3 та Swift 4, як пропонують деякі з вас у коментарях.


Швидкий 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


Вибачте, але цей код більше не працює у швидкому 2.0, він підказує помилку "Виклик може кинути, але він не позначений" спробувати "і помилка не обробляється"
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

11
Мені довелося зробити об’єкт AVAudioPlayer примірною змінною для того, щоб це працювало. Як локальна змінна, вона не відтворюватиме нічого, без помилок. Делегатів також не дзвонили.
Калеб

2
Чому ви тут використовуєте охорону? player = try AVAudioPlayer(contentsOf: url) guard let player = player else { return }мені здається додатковою роботою, чому б не просто let player = try AVAudioPlayer(contentsOf: url)?
xandermonkey

2
Використання твердження про захист робить вас досить безпечним від збоїв через нульове значення.
Аашиш

43

Для 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методи?
Шен Робертсон

2
Якщо ви надаєте AVAudioSessionCategoryPlaybackце setCategory, воно гарантуватиме, що аудіо завжди відтворюється, навіть якщо телефон знаходиться в заблокованому екрані або в беззвучному режимі. setActiveце як сказати системі, що ваш додаток готовий відтворювати аудіо
Аді Нугрохо

@AdiNugroho, ти думаєш, ти можеш допомогти з моїм питанням: stackoverflow.com/questions/44201592/… ?
JamesG

У мене багато проблем з цим на iOS 11. Раніше вона працювала, але зараз вона раптом не працює. Будь-які ідеї?
nickdnk

15

iOS 12 - Xcode 10 beta 6 - Swift 4.2

Використовуйте лише 1 IBAction і вкажіть усі кнопки на цю 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!")
    }
}

5
Смішно, що ви припускаєте, що всі дивляться "iOS 11 & Swift 4 - The Complete iOS App Bootcamp" 😂😂
karlingen

12

Якщо код не створює помилок, але ви не чуєте звуку - створіть плеєр як екземпляр:

   static var player: AVAudioPlayer!

Для мене перше рішення спрацювало, коли я зробив цю зміну :)


Працює для мене. Хтось знає, чому ви повинні встановити це на статичне?
кузду

3
Я не думаю, що це має бути статичним (вже?), Але, здається, можливо, якщо ви відпустите його поза рамки після його створення, навіть якщо ви покликали play (), він не буде грати? Я щойно зробив це змінною екземпляром свого класу, і він працює.
біомікер

3
@kuzdu Це пов’язано з тим, що ви не розміщуєте playerзовнішнє поле. В іншому випадку playerстає delocalised і тому не може відтворювати жоден звук, оскільки його більше немає.
George_E

Працював для мене - безstatic
Тодд

5

Швидкі 4, 4.2 та 5

Відтворюйте аудіо з URL-адреси та з вашого проекту (Local File)

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

працює в останній версії 4. ButtonTag буде тегом на кнопці вашого інтерфейсу. Примітки знаходяться в папці в папці, паралельній Main.storyboard. Кожна примітка називається note1, note2 і т. Д. ButtonTag дає номер 1, 2 і т. Д. Від натиснутої кнопки, яка передається як парам


0

імпорт AVFoundation

імпортувати AudioToolbox

публічний фінальний клас 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 (назва: "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()
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.