Play local audio file with AVAudioPlayer - swift

I'm testing my app in simulator.
I'm downloading file and getting it's local way like this one:
file:///Users/administrator/Library/Developer/CoreSimulator/Devices/4CDF286B-543F-4137-B5E2-C312E19B992F/data/Containers/Data/Application/E5F13797-A6A8-48A1-B3C3-FBC3D7A03151/Documents/4d13e04980d3.mp3
Now I want to play this file with AVAudioPlayer but I'm always getting this error:
file:///
Error Domain=NSOSStatusErrorDomain Code=2003334207 "(null)"
Code for playing:
var alertSound = NSURL(fileURLWithPath: "file:///Users/administrator/Library/Developer/CoreSimulator/Devices/4CDF286B-543F-4137-B5E2-C312E19B992F/data/Containers/Data/Application/E5F13797-A6A8-48A1-B3C3-FBC3D7A03151/Documents/4d13e04980d3.mp3")
print(alertSound)
var error:NSError?
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: alertSound)
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch {
print(error)
}
How should I make it playing?

Under iOS8, the path that you have saved won't be valid across launches. The id you see "E5F13797-A6A8-48A1-B3C3-FBC3D7A03151" will change with each launch.
The solution is to save the filename and not the complete path, and to recreate the URL or complete path, by getting the path to the Documents (or tmp) folder and appending the filename to it.

Look at NSFileManager. The method URLForDirectory:inDomain:appropriateForURL:create:error: is what you should use.

let fileName = ("FILE_NAME.mp3")
let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let soundFileURL = documentsDirectory.URLByAppendingPathComponent(fileName)
AudioCenter.player.playURL(soundFileURL)

// create the soundFileURL for the word
let toAppendString = "\(String)" //
let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
soundFileURL = documentsDirectory.URLByAppendingPathComponent(toAppendString)
do {
self.player = try AVAudioPlayer(contentsOfURL: soundFileURL)
player.prepareToPlay()
player.volume = 1.0
player.play()
} catch let error as NSError {
print(error)
}

Related

How do I save AudioRecording to app folder?

I am working on a app with recording function and followed a tutorial on this. I would like to edit the function where the AudioRecorder saves the file so that the file goes in the same folder it would if I dragged an audiofile directly in to xcode.
I am having trouble fetching a singe recording from the directory the Audiorecorder is saving to atm and found another tutorial that shows how to find recordings based on name from the app folder.
This is the recordings func today:
func startRecording() {
let recordingSession = AVAudioSession.sharedInstance()
do {
try recordingSession.setCategory(.playAndRecord, mode: .default)
try recordingSession.setActive(true)
} catch {
print("Failed to set up recording session")
}
let documentPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
print("AUDIORECORDER document path: \(documentPath)")
let audioFilename = documentPath.appendingPathComponent("\(Date().toString(dateFormat: "dd-MM-YY_'at'_HH:mm:ss")).m4a")
print("AUDIORECORDER audioFilename: \(audioFilename)")
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 12000,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
do {
audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
audioRecorder.record()
recording = true
} catch {
print("Could not start recording")
}
}
Any idea on how to do this? The tutorial only shows how to fetch all recordings to a list and I am trying to fetch a single recording. This is the fetch function if this helpes:
func fetchRecordings() {
recordings.removeAll()
let fileManager = FileManager.default
let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let directoryContents = try! fileManager.contentsOfDirectory(at: documentDirectory, includingPropertiesForKeys: nil)
for audio in directoryContents {
let recording = Recording(fileURL: audio, createdAt: getCreationDate(for: audio))
recordings.append(recording)
}
objectWillChange.send(self)
}
It does not really matter where it saves but I need to be able to save the name to a string (So that I can fetch the right audio to the right object) and then find the audio based on that string.
Thank you.

Error in playing some type of audio file in swift

I would like to play audio Files from the directory in swift and I use following code for initializing:
func setAVAudioPlayer(){
let fileName = URL(string: audioFilename)?.lastPathComponent
let fileURL = NSURL(fileURLWithPath: myPath)
let destinationPath = fileURL.appendingPathComponent(fileName!)
let filePath = destinationPath?.path
let fileManager : FileManager = FileManager.default
if fileManager.fileExists(atPath: filePath!){
ChannelViewController.audioPlayerArrayList[indexPathRow] = AVAudioPlayer()
let path: String! = myPath + "/" + fileName!
let mp3URL = NSURL(fileURLWithPath: path)
do
{
ChannelViewController.audioPlayerArrayList[indexPathRow] = try AVAudioPlayer(contentsOf: mp3URL as URL)
}
catch
{
print("An error occurred while trying to extract audio file")
print(error)
}
}
}
It works for some audio type like m4a, mp3, etc. but I get error for some type like 3gp files.
How can I fix this issue and this function works for all audio type.
Error:
2020-11-29 10:16:57.828589+0330 School_iApp[4038:63911] 3531: MP4Parser_PacketProvider->GetASBD() failed
2020-11-29 10:16:57.829053+0330 School_iApp[4038:63911] 101: OpenFromDataSource failed
2020-11-29 10:16:57.829252+0330 School_iApp[4038:63911] 76: Open failed
An error occurred while trying to extract audio file
Error Domain=NSOSStatusErrorDomain Code=2003334207 "(null)"
Thanks in advance.
AVAudioPlayer is a Audio player your tried to play a mp4 data that’s a video. That will not work. But there is a way in AvFoundation to take the audio from a Video.
Here is something to read for you: https://developer.apple.com/documentation/avfoundation/media_playback_and_selection/creating_a_basic_video_player_ios_and_tvos

How to fix 'appendingPathComponent' is unavailable: Use appendingPathComponent on URL error

I'm working on a old Swift tutorial (Swift 2.0) that's posted on Ray Wenderlich's web site (https://www.raywenderlich.com/2185-how-to-make-a-letter-word-game-with-uikit-and-swift-part-3-3) and I'm running into an error when I tried to re-setup a function called "preloadAudioEffects" in Swift 4.2 . The error? appendingPathComponent' is unavailable: Use appendingPathComponent on URL instead.
I've tried to rename the old Swift code [Ex: NSBundle to Bundle , stringByAppendingPathComponent to appendingPathComponent()], but I'm still running into some syntax issues due to my inexperience with Swift.
This is the original code:
func preloadAudioEffects(effectFileNames:[String]) {
for effect in AudioEffectFiles {
//1 get the file path URL
let soundPath = NSBundle.mainBundle().resourcePath!.stringByAppendingPathComponent(effect)
let soundURL = NSURL.fileURLWithPath(soundPath)
//2 load the file contents
var loadError:NSError?
let player = AVAudioPlayer(contentsOfURL: soundURL, error: &loadError)
assert(loadError == nil, "Load sound failed")
//3 prepare the play
player.numberOfLoops = 0
player.prepareToPlay()
//4 add to the audio dictionary
audio[effect] = player
}
}
And this is what I've tried to do via following the suggestions in Xcode:
func preloadAudioEffects(effectFileNames:[String]) {
for effect in AudioEffectFiles {
//1 get the file path URL
let soundPath = Bundle.main.resourcePath!.appendingPathComponent(effect)
let soundURL = NSURL.fileURL(withPath: soundPath)
//2 load the file contents
var loadError:NSError?
let player = AVAudioPlayer(contentsOfURL: soundURL, error: &loadError)
assert(loadError == nil, "Load sound failed")
//3 prepare the play
player.numberOfLoops = 0
player.prepareToPlay()
//4 add to the audio dictionary
audio[effect] = player
}
}
Get the full path to the sound file and convert it to a URL by using NSURL.fileURLWithPath().
Call AVAudioPlayer(contentsOfURL:error:) to load a sound file in an audio player.
Set the numberOfLoops to zero so that the sound won’t loop at all. Call prepareToPlay() to preload the audio buffer for that sound.
Finally, save the player object in the audio dictionary, using the name of the file as the dictionary key.
Just replace resourcePath with resourceURL
let soundURL = Bundle.main.resourceURL!.appendingPathComponent(effect)
and you have to wrap the AVAudioPlayer initializer in a try block
func preloadAudioEffects(effectFileNames:[String]) {
for effect in AudioEffectFiles {
let soundURL = Bundle.main.resourceURL!.appendingPathComponent(effect)
//2 load the file contents
do {
let player = try AVAudioPlayer(contentsOf: soundURL)
//3 prepare the play
player.numberOfLoops = 0
player.prepareToPlay()
//4 add to the audio dictionary
audio[effect] = player
} catch { print(error) }
}
}

File cannot be opened - however it does exist - swift 3

I am recording video to a file with this code:
print(documentsPath)
//var/mobile/Containers/Data/Application/FFB207E7-36CC-4C53-A2E2-5FADC7C23A18/Documents/gymnastVideos/test.mp4
let filePath = NSURL(fileURLWithPath: documentsPath)
videoFileOutput.startRecording(toOutputFileURL: filePath as URL!, recordingDelegate: recordingDelegate)
and have verified that the file exists, however, when I try to open the file to check if anything is being saved there, I return an error. The code:
var documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
documentsPath.append("/gymnastVideos")
let filePath = URL(fileURLWithPath: documentsPath)
do {
let directoryContents = try FileManager.default.contentsOfDirectory(at: filePath, includingPropertiesForKeys: nil, options: [])
print(directoryContents)
print("!")
} catch let error as NSError {
print(error.localizedDescription)
//The file “gymnastVideos” couldn’t be opened.
print("!!")
}
Why can't I open the file, and what do I need to change in my code to be able to open the file?

Play m4a file from document Directory

I would to play an m4a file but I'm getting an error in the console and the file won't play.
Console prints:
The operation couldn’t be completed. (OSStatus error 2003334207.)
let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
print("File Location: ",url.path)
if(FileManager.default.fileExists(atPath: url.path)) {
do {
audioPlayer = try AVAudioPlayer(contentsOf: url)
guard let player = audioPlayer else { return }
player.prepareToPlay()
} catch let error {
print(error.localizedDescription)
}
} else {
print("file not found")
}
I tried URL like this:
let NoteUrl = Bundle.main.url(forResource: "Voice Note", withExtension: "m4a")
But I couldn't get it to play. Can someone help me to play m4a file by file's name? Any help will be appreciated.
You are passing the Documents folder to the audio player. Your code needs to append the specific filename to the Documents folder.
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let url = documentsURL.appendingPathComponent("Voice Note.m4a")