How to Play And Stop an AVAudioPlayer in swift3? - swift

I am developing an audio Player in swift and I need 2 buttons ( Play and Stop ) to control it. I have used the following code:
override func viewDidLoad() {
super.viewDidLoad()
let urlstring = "http://radio.spainmedia.es/wp-content/uploads/2015/12/tailtoddle_lo4.mp3"
let url = NSURL(string: urlstring)
print("the url = \(url!)")
downloadFileFromURL(url: url!)
}
func downloadFileFromURL(url:NSURL) {
var downloadTask:URLSessionDownloadTask
downloadTask = URLSession.shared.downloadTask(with: url as URL, completionHandler: { (URL, response, error) -> Void in
self.play(url: URL! as NSURL)
})
downloadTask.resume()
}
func play(url:NSURL) {
print("playing \(url)")
do {
self.SoundPlayer = try AVAudioPlayer(contentsOf: url as URL)
SoundPlayer.prepareToPlay()
SoundPlayer.volume = 1.0
SoundPlayer.play()
} catch let error as NSError {
//self.player = nil
print(error.localizedDescription)
} catch {
print("AVAudioPlayer init failed")
}
}
#IBAction func Play(_ sender: Any) {
SoundPlayer.play()
}
#IBAction func Stop(_ sender: Any) {
SoundPlayer.stop()
}
Basically, when the user opens the app, the mp3 audio file starts automatically. Therefore I have created 2 additional buttons, Start and Stop and I want to control this Audio Player with them. Would you please advice me how to do it, because now they are not connected with the Audio Player and no action is performed when I click on them.

If your objective is to just play the file while streaming it, get the Data from the URL from and then pass it to the AVAudioPlayer.
if let theURL = URL(string: "http://radio.spainmedia.es/wp-content/uploads/2015/12/tailtoddle_lo4.mp3") {
if let data = try? Data(contentsOf: theURL){
if let audioPlayer = try? AVAudioPlayer(data: data) {
print("Done")
audioPlayer.play()
} else {
print("Noo")
}
}
}
AVAudioPlayer(contentsOf: url as URL) often fails to fetch data from remote location.
You can also check other options such as AVPlayer to play your file
how can i play remote .mp3 file in my ios application?

Related

How to play sound after each network request is successful?

I want to play a sound after each network request is successful. I have some objects that I want to send to the server using a for loop. In each iteration I'm sending a request to the server and after each request is complete, I want to play a sound.
I've tried this:
for object in objects {
sendObjectToServer(object)
}
func playSound() {
let url = Bundle.main.url(forResource: "sound", withExtension: "mp3")!
let player = try! AVAudioPlayer(url)
player.play()
}
func sendObjectToServer(object: Object) {
URLSession.shared.dataTask(with url: object.url) {(data,response,error) in
DispatchQueue.main.async {
playSound() // doesn't play sound synchronously
}
}
}
Why are you using the main thread for background-related operations. Only update your UI in the Dispatch.main.async code:
Try this on a physical device (tested and worked)
import AVFoundation
for object in objects {
DispatchQueue.global(qos: .background).async {
sendObjectToServer(object)
}
}
var player: AVAudioPlayer?
func playSound() {
guard let url = Bundle.main.url(forResource: "sound", 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)
}
}
func sendObjectToServer(object: Object) {
URLSession.shared.dataTask(with url: object.url) {(data,response,error) in
// Custom Logic
playSound()
}
}

Can't play local audio mp3 file with AVAudioPlayer

I want to download and play the sound from Google Translate (Text to Speech).
The mp3 file's downloaded successfull. I tried to play it with AVAudioPlayer, but there's no sound on both simulator and my real iPhone
I use XCode 10.2.1, Swift 5. Test on simulator (XSMax) and iPhone XSMax
import UIKit
import AVFoundation
class TextToSpeechGoogleTranslate: AVAudioPlayer, AVAudioPlayerDelegate {
var player: AVAudioPlayer?
func speak() {
let fileURL = URL(string: "https://translate.google.com/translate_tts?ie=UTF-8&total=1&idx=0&client=tw-ob&tl=vi&q=Hello" )!
let documentsUrl:URL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL?)!
let destinationFileUrl = documentsUrl.appendingPathComponent("voice.mp3")
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = URLRequest(url:fileURL)
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
}
do {
try? FileManager.default.removeItem(at: destinationFileUrl)
try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
print(destinationFileUrl)
do {
self.player = try AVAudioPlayer(contentsOf: destinationFileUrl)
self.player!.delegate = self
self.player!.prepareToPlay()
self.player!.volume = 1.0
self.player!.play()
}
catch let error as NSError {
print("Error: \(error.localizedDescription)")
}
catch {
print("AVAudioPlayer init failed")
}
} catch (let writeError) {
print("Error creating a file \(destinationFileUrl) : \(writeError)")
}
} else {
print("Error took place while downloading a file. Error description: %#", error?.localizedDescription as Any);
}
}
task.resume()
}
}
Output:
Successfully downloaded. Status code: 200
file:///Users/macbook/Library/Developer/CoreSimulator/Devices/F43F9B03-674C-4EE1-8CAD-01B5145868DE/data/Containers/Data/Application/6D1A3310-386D-4706-9F1E-DFF536B2A43F/Documents/voice.mp3
I played that file in Finder. It's OK.
I just tried your code and it seems to work fine. Maybe the problem is in how you create the TextToSpeechGoogleTranslate object and call speak() on it. For example, here is what I tried:
class ViewController: UIViewController {
var test: TextToSpeechGoogleTranslate?
override func viewDidLoad() {
super.viewDidLoad()
test = TextToSpeechGoogleTranslate()
test!.speak()
}
}
If that doesn't help, can you post some code showing how you call this method?
import UIKit
import AVFoundation
class ViewController: UIViewController, AVAudioPlayerDelegate {
var audioPlayer = TextToSpeechGoogleTranslate()
override func viewDidLoad() {
super.viewDidLoad()
audioPlayer.delegate = self
audioPlayer!.speak()
}
}
1) create instance of your class
2) Confirm it's delegate
3) call your function after you received your data
4) while testing from device, don't forget to turn off silence mode (volume up)

AVPlayer with downloaded content doesn't work but streaming content does

I am trying to (1) download a piece of audio from a link, (2) add that newly-downloaded audio to an AVPlayer and (3) play it. Something is going wrong at step (3) and I'm looking for any guidance. Here's the code, including my alamofire and download functions, as I fear something may be going wrong at that stage.
import AVFoundation
class SettingAlarmViewController: UIViewController {
var player:AVPlayer!
override func viewDidLoad() {
super.viewDidLoad()
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
}
catch {
// report for an error
}
}
func getLatestPodcastURL(completion: #escaping (URL) -> ()) {
let RSSUrl: String = "https://www.npr.org/rss/podcast.php?id=510318"
Alamofire.request(RSSUrl).responseRSS() {response in
if let podcastURL: String = response.result.value?.items[0].enclosure!
{
let audioURL = URL(string: podcastURL)
completion(audioURL!)
}
else {
//error handling
}
}
}
func downloadSongAsynch(audioUrl: URL, completion: #escaping (URL) -> ()) {
let fileManager = FileManager.default
let documentsDirectoryURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("podcasts/")
do {
try fileManager.createDirectory(atPath: documentsDirectoryURL.path,
withIntermediateDirectories: true, attributes: nil)
} catch {
//error handling
}
let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
URLSession.shared.downloadTask(with: audioUrl, completionHandler: { (location, response, error) -> Void in
guard let location = location, error == nil else { return }
do {
try FileManager.default.moveItem(at: location, to: destinationUrl)
} catch {
//error handling
}
}).resume()
completion(destinationUrl)
}
#IBAction func SetUpBotton(_ sender: Any) {
getLatestPodcastURL() {response in
//Uses an asynchronous call to Alamofire to get the podcast URL
self.downloadPodcastAsynch(audioUrl: response){response2 in
self.player = AVPlayer(url: response2)
print(self.player.currentItem)
}
#IBAction func PlayButton(_ sender: Any) {
player.play()
print(player.currentItem)
}
The log consistently shows my current item: >
But nothing plays. I have checked that the audio is working by trying to use the URL to stream this content. That works fine. I am getting the following:
BoringSSL errors "[BoringSSL] Function boringssl_session_errorlog: line 2871 [boringssl_session_read] SSL_ERROR_ZERO_RETURN(6): operation failed because the connection was cleanly shut down with a close_notify alert
but from what I've read, this is just a bug in the latest update and shouldn't be impacting the download. Any thoughts on this?

Swift Sound Effects // Why Won't My Code Work?

I have been trying to make a game to teach myself swift, and cant seem to get this code to work. I am extremely new to this, and can't seem to find out why it won't work... XCode doesn't flag any problems, build sucseed, and debugger even prints "Got to Stage 1 & Got to Stage 2... anything help?
I Imported AVFoundation..
class GAME {
class func SuperStartGame(playerwhowon1: SKSpriteNode) {
var player = AVAudioPlayer()
func PlaySound() {
guard let URL = Bundle.main.url(forResource: "PowerUp", withExtension: "mp3")
else {
print("Didn't Find URL")
return
}
do {
print("Got to Stage 1")
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
player = try AVAudioPlayer(contentsOf: URL, fileTypeHint: "mp3")
player.prepareToPlay()
player.play()
print("Got to Stage 2")
} catch let error as NSError {
print("error: \(error.localizedDescription)")
}
RoundNumber += 1
Round.text = "Round \(RoundNumber)"
if playerwhowon1 == Mine {
MyScore.run(addscoreM) {
PlaySound()
Round.run(NewRoundForRound) {
...
Code keeps going.. thats the only part that is relevant to the sound. I added the sound file to Xcode, and made sure it was added tot he project target... it is in my main bundle.
Make sure that your device isn't muted
mp3 file is copied to bundle
Example VC playing sound:
class ViewController: UIViewController {
var game = Game()
#IBAction func playAction(_ sender: UIButton) {
game.playSound()
}
}
class Game {
var player: AVAudioPlayer?
func playSound() {
guard let URL = Bundle.main.url(forResource: "SampleAudio", withExtension: "mp3") else {
print("Didn't Find URL")
return
}
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
player = try AVAudioPlayer(contentsOf: URL, fileTypeHint: "mp3")
player?.prepareToPlay()
player?.play()
} catch let error as NSError {
print("\(error.localizedDescription)")
}
}
}

Swift 3: stream MP3 file from server

I am trying to stream a sample mp3 from a url. It is a very small sample file. However, when I press the play button nothing happens. Well, no sound plays.
I am rather new to Swift and very much a noob so here is the full View Controller as I am unsure what you might need.
import UIKit
import AVKit
import AVFoundation
import Foundation
class ViewController: UIViewController {
#IBAction func playButton(_ sender: Any) {
print("pressed")
let urlstring = "http://cdn.mos.musicradar.com/audio/samples/80s-heat-demos/AM_Eighties08_85-01.mp3"
let url = NSURL(string: urlstring)
print("the url = \(url!)")
downloadFileFromURL(url: url!)
}
override func viewDidLoad() {
// Do any additional setup after loading the view
}
func downloadFileFromURL(url:NSURL){
weak var weakSelf = self
var downloadTask:URLSessionDownloadTask
downloadTask = URLSession.shared.downloadTask(with: url as URL, completionHandler: { (URL, response, error) -> Void in
print("URL = \(URL)")
weakSelf!.plays(url: URL! as URL)
})
downloadTask.resume()
}
func plays(url:URL) {
print("playing \(url)")
do {
var playerItem = AVPlayerItem(url: url as URL)
player = AVPlayer(url : url)
player.volume = 1.0
player.play()
} catch let error as NSError {
print(error.localizedDescription)
} catch {
print("AVAudioPlayer init failed")
}
}
}
in my console I am getting this:
pressed
the url = http://cdn.mos.musicradar.com/audio/samples/80s-heat-demos/AM_Eighties08_85-01.mp3
URL = Optional(file:///private/var/mobile/Containers/Data/Application/C255E8F4-DDBA-43BB-BC33-AF71C08BBDFD/tmp/CFNetworkDownload_tm0O8v.tmp)
playing file:///private/var/mobile/Containers/Data/Application/C255E8F4-DDBA-43BB-BC33-AF71C08BBDFD/tmp/CFNetworkDownload_tm0O8v.tmp
URL = Optional(file:///private/var/mobile/Containers/Data/Application/C255E8F4-DDBA-43BB-BC33-AF71C08BBDFD/tmp/CFNetworkDownload_J1f2LF.tmp)
playing file:///private/var/mobile/Containers/Data/Application/C255E8F4-DDBA-43BB-BC33-AF71C08BBDFD/tmp/CFNetworkDownload_J1f2LF.tmp
Can anyone help me solve this? I just want to be able to play this sound on click of the button from the server not locally.
Please try to use this code for you player function.
func plays(url:URL) {
print("playing \(url)")
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
player = try AVAudioPlayer(contentsOf: url)
guard let player = player else { return }
player.play()
} catch let error as NSError {
print(error.localizedDescription)
} catch {
print("AVAudioPlayer init failed")
}
}