Как воспроизвести звук с помощью Swift?

149

Я хотел бы воспроизвести звук с помощью 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
Honey

Ответы:

293

Наиболее предпочтительно вы можете использовать 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

Devapploper
источник
Извините, но этот код больше не работает в swift 2.0, он выдает ошибку «Вызов может сгенерировать, но он не помечен как« попытка », и ошибка не обрабатывается»
Мишель Кансу
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
Использование защитного оператора делает вас довольно безопасным от сбоя из-за нулевого значения.
Aashish
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 - полный Bootcamp для разработки приложений для iOS» k
karlingen
12

Если код не генерирует никаких ошибок, но вы не слышите звук - создайте проигрыватель в качестве примера:

   static var player: AVAudioPlayer!

Для меня первое решение сработало, когда я сделал это изменение :)

EranKT
источник
Работает для меня. Кто-нибудь знает, почему вы должны установить это на статический?
Кузду
3
Я не думаю, что он должен быть статичным (больше?), Но, возможно, если вы позволите ему выйти из области видимости после его создания, даже если вы вызвали play (), он не будет воспроизводиться? Я просто сделал это переменной экземпляра моего класса, и она работает.
biomiker
3
@kuzdu Это из-за того, что вы не размещаете playerвнешнюю область. В противном случае, он playerстановится делокализованным и, следовательно, не может воспроизводить звук, поскольку его больше не существует.
George_E
Работал для меня - безstatic
Тодд
5

Свифт 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
}
Mr.Shin
источник
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в этом месте.
Иксани
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)
}
imdpk
источник
Я получаю следующее сообщение об ошибке: 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()
Fattie
источник
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 будет тегом кнопки на вашем интерфейсе. Заметки находятся в папке, расположенной параллельно папке 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()
}
Мобин Валади
источник