【问题标题】:How to download and save an audio file and then play it in swift?如何下载并保存音频文件然后快速播放?
【发布时间】:2019-05-17 22:04:20
【问题描述】:

我正在尝试从 Internet 下载音频文件并将其保存到手机上。这是下载功能:

func download() {
    if let audioUrl = downloadUrl {

        // then lets create your document folder url
        let documentsDirectoryURL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

        // lets create your destination file url
        let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
        print(destinationUrl)

        // to check if it exists before downloading it
        if FileManager.default.fileExists(atPath: destinationUrl.path) {
            print("The file already exists at path")

            // if the file doesn't exist
        } else {

            // you can use NSURLSession.sharedSession to download the data asynchronously
            URLSession.shared.downloadTask(with: audioUrl, completionHandler: { (location, response, error) -> Void in
                guard let location = location, error == nil else { return }
                do {
                    // after downloading your file you need to move it to your destination url
                    try FileManager.default.moveItem(at: location, to: destinationUrl)
                    print("File moved to documents folder")
                } catch let error as NSError {
                    print(error.localizedDescription)
                }
            }).resume()
        }
    }
}

然后,在我关闭并打开应用程序后,我使用以下函数检索 url 并使用 AVPlayer 播放它:

func getUrl2() {
    if let audioUrl = downloadUrl {

        // then lets create your document folder url
        let documentsDirectoryURL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

        destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)

        if let u = self.destinationUrl {
            let player = AVPlayer(url: u)
            print(u)
            print("Bouta play")
            print(CMTimeGetSeconds(player.currentItem!.duration))
            player.play()
        }
    }
}

不断打印出来的持续时间是“nan”。有没有办法检查音频文件是否真的在下载?或者下载后检索文件是否有问题?提前致谢。

【问题讨论】:

    标签: ios swift xcode avplayer


    【解决方案1】:

    首先,您必须使用以下逻辑检查 URL 是否为空:

    if !link.isEmpty{
            checkBookFileExists(withLink: link){ [weak self] downloadedURL in
                guard let self = self else{
                    return
                }
                play(url: downloadedURL)
            }
        }
    

    然后 checkBookFileExists 函数会在再次下载之前检查文件是否已经保存:

        func checkBookFileExists(withLink link: String, completion: @escaping ((_ filePath: URL)->Void)){
        let urlString = link.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
        if let url  = URL.init(string: urlString ?? ""){
            let fileManager = FileManager.default
            if let documentDirectory = try? fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create: false){
    
                let filePath = documentDirectory.appendingPathComponent(url.lastPathComponent, isDirectory: false)
    
                do {
                    if try filePath.checkResourceIsReachable() {
                        print("file exist")
                        completion(filePath)
    
                    } else {
                        print("file doesnt exist")
                        downloadFile(withUrl: url, andFilePath: filePath, completion: completion)
                    }
                } catch {
                    print("file doesnt exist")
                    downloadFile(withUrl: url, andFilePath: filePath, completion: completion)
                }
            }else{
                 print("file doesnt exist")
            }
        }else{
                print("file doesnt exist")
        }
    }
    

    如果该文件不存在,您将使用以下函数下载它:

    func downloadFile(withUrl url: URL, andFilePath filePath: URL, completion: @escaping ((_ filePath: URL)->Void)){
        DispatchQueue.global(qos: .background).async {
            do {
                let data = try Data.init(contentsOf: url)
                try data.write(to: filePath, options: .atomic)
                print("saved at \(filePath.absoluteString)")
                DispatchQueue.main.async {
                    completion(filePath)
                }
            } catch {
                print("an error happened while downloading or saving the file")
            }
        }
    }
    

    该功能将保存它,你可以玩它:

      func play(url: URL) {
        print("playing \(url)")
    
        do {
    
            audioPlayer = try AVAudioPlayer(contentsOf: url)
            audioPlayer?.prepareToPlay()
            audioPlayer?.delegate = self
            audioPlayer?.play()
            let percentage = (audioPlayer?.currentTime ?? 0)/(audioPlayer?.duration ?? 0)
            DispatchQueue.main.async {
                // do what ever you want with that "percentage"
            }
    
        } catch let error {
            audioPlayer = nil
        }
    
    }
    

    【讨论】:

    • 嘿,你检查我的答案了吗?
    • 如果duration 无法解决,(audioPlayer?.duration ?? 0) 会不会给出除以零的错误?
    猜你喜欢
    • 1970-01-01
    • 2019-11-26
    • 1970-01-01
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    相关资源
    最近更新 更多