如何将音频文件保存在Firebase中,并使音频文件自动显示在下一个View Controller中?

时间:2019-04-03 15:48:18

标签: swift firebase audio avfoundation firebase-storage

我正在创建一个应用程序,可以在其中记录音频,它将自动将音频文件保存在Firebase(已连接到我的项目)中,并显示在下一个视图控制器中。他们将能够播放在视图控制器中播放的文件所保存的内容,以备将来参考。

我的问题是

  1. 能够保存音频并将其自动保存在其帐户下的Firebase中,并能够显示在视图控制器中。
  2. 我的应用程序尝试创建新帐户时崩溃。

这是我登录/创建帐户首页的代码:

import UIKit
import SVProgressHUD
import Firebase
import AVFoundation

class ViewController: UIViewController {

@IBOutlet weak var email: UITextField!
@IBOutlet weak var password: UITextField!
@IBAction func logIn(_ sender: Any) {
    SVProgressHUD.show()

    Auth.auth().signIn(withEmail: email.text!, password: password.text!) { (user, error) in

        if error != nil {
            print(error!)
        } else {
            print("Log in Succesful")

            SVProgressHUD.dismiss()

            self.performSegue(withIdentifier: "logIn", sender: self)
        }

    }
}
@IBAction func createAccount(_ sender: Any) {
    self.performSegue(withIdentifier: "createAccount", sender: self)
}
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.


}

}
public protocol MicrophonePermissions {

typealias PermissionsState = AVAudioSession.RecordPermission

func requestPermissions(handler: @escaping (PermissionsState) -> Void)
func permissionsState() -> PermissionsState
}

open class DefaultMicrophonePermissions: MicrophonePermissions {

public init() {}

public func requestPermissions(handler: @escaping (PermissionsState) -> Void) {
    AVAudioSession.sharedInstance().requestRecordPermission { _ in
        DispatchQueue.main.async { [weak self] in
            guard let `self` = self else { return }
            handler(self.permissionsState())
        }
    }
}

public func permissionsState() -> PermissionsState {
    return AVAudioSession.sharedInstance().recordPermission
}

}

这是我创建帐户的代码:

import UIKit
import Firebase
import SVProgressHUD

class CreateAccountViewController: UIViewController, UIApplicationDelegate {

@IBOutlet weak var emailAddress: UITextField!
@IBOutlet weak var password: UITextField!
@IBAction func createAccount(_ sender: Any) {

    Auth.auth().createUser(withEmail: emailAddress.text!, password: password.text!) { (user, error) in
        if error != nil {
            print(error!)
        } else {
            print("Account Created!")
            SVProgressHUD.dismiss()
            self.performSegue(withIdentifier: "mainPage", sender: self)
        }
    }

    func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
}

这是我的代码,它们开始和结束录制的时间以及能够将音频文件保存在下一个视图控制器中的

 import UIKit
 import AVFoundation
 import Firebase

 var recordButton: UIButton!
 var audioRecorder: AVAudioRecorder!
 var recordingSession: AVAudioSession!

 class PracticePageViewController: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate {

@IBOutlet weak var beginRecording: UIButton!

@IBAction func endRecording(_ sender: Any) {
    finishRecording(success: true)

    func saveTrack(asset: AVURLAsset) {
        let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A)
        let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("YourApp/documents/Track01.m4a")
        exporter?.outputURL = fileURL
        exporter?.outputFileType = AVFileType.m4a

        exporter?.exportAsynchronously(completionHandler: {
            print(exporter?.status)
            print(exporter?.estimatedOutputFileLength)
            print(exporter?.maxDuration)
            print("Finished Saving File")
        })
    }
}

@IBAction func beginRecording(_ sender: Any) {
    startRecording()
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    recordingSession = AVAudioSession.sharedInstance()

    do {
        try recordingSession.setCategory(.playAndRecord, mode: .default)
        try recordingSession.setActive(true)
        recordingSession.requestRecordPermission() { [unowned self] allowed in
            DispatchQueue.main.async {
                if allowed {
                    loadRecordingUI()
                } else {
                    print("Failed to Record")
                }
        }

    }

    } catch {
        print("Failed to Record")
    }

    func loadRecordingUI() {
        recordButton = UIButton(frame: CGRect(x: 64, y: 64, width: 128, height: 64))
        recordButton.setTitle("Tap to Record", for: .normal)
        recordButton.titleLabel?.font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle(rawValue: title!))
        recordButton.addTarget(self, action: #selector(recordTapped), for: .touchUpInside)
        view.addSubview(recordButton)
    }

}


func startRecording() {
    let audioFilename = getDocumentsDirectory().appendingPathComponent("recording.m4a")
    let settings = [
        AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
        AVSampleRateKey: 12000,
        AVNumberOfChannelsKey: 1,
        AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
    ]

    do {
        audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
        audioRecorder.delegate = self
        audioRecorder.record()
        recordButton.setTitle("Tap to Stop", for: .normal)
    } catch {
        finishRecording(success: false)
    }
}

func getDocumentsDirectory() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    return paths[0]
}

func finishRecording(success: Bool) {
    audioRecorder.stop()
    audioRecorder = nil

    if success {
        recordButton.setTitle("Tap to Re-record", for: .normal)
    } else {
        recordButton.setTitle("Tap to Record", for: .normal)
    }
}

@objc func recordTapped() {
    if audioRecorder == nil {
        startRecording()
    } else {
        finishRecording(success: true)
    }
}

func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
        if !flag {
            finishRecording(success: false)
    }
    }
}

最后,这是我为View Controller提供的代码,其中显示了所有音频文件,并为他们提供了选择发送文件作为附件的选项

import UIKit
import MessageUI
import Firebase
import AVFoundation
import FirebaseStorage

class PracticeSessionsViewController: UIViewController, MFMailComposeViewControllerDelegate {

@IBAction func emailTeacher(_ sender: Any) {
    let mailComposeViewController = configureMailController()
    if MFMailComposeViewController.canSendMail() {
        self.present(mailComposeViewController, animated: true, completion: nil)
    } else {
        showMailError()
    }
}
override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.

    func renameAudio(newTitle: String) {
        do {
            let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) [0]
            let documentDirectory = URL(fileURLWithPath: path)
            let originPath = documentDirectory.appendingPathComponent("audio.m4a")
            let destinationPath = documentDirectory.appendingPathComponent("\(newTitle).m4a")
            try FileManager.default.moveItem(at: originPath, to: destinationPath)
        } catch {
            print(error)
        }
    }
}

func configureMailController() -> MFMailComposeViewController {
    let mailComposeVC = MFMailComposeViewController()
    mailComposeVC.mailComposeDelegate = self
    mailComposeVC.setToRecipients([""])
    mailComposeVC.setSubject("Hello")

    return mailComposeVC
}

func showMailError() {
    let sendMailErrorAlert = UIAlertController(title: "Could not send mail", message: "Your device could not send message", preferredStyle: .alert)
    let dismiss = UIAlertAction(title: "Ok", style: .default, handler: nil)
    sendMailErrorAlert.addAction(dismiss)
    self.present(sendMailErrorAlert, animated: true, completion: nil)
}

func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    controller.dismiss(animated: true, completion: nil)
}

我一直在尝试寻求最佳方法,但无济于事。我的代码在下面。请记住,我是Swift的新手,所以我只想确保自己正在学习正确的方法。谢谢!

0 个答案:

没有答案