【问题标题】:Objective C/IOS - Save Audio Stream To FileObjective C/IOS - 将音频流保存到文件
【发布时间】:2015-12-24 13:28:02
【问题描述】:

有可能/有没有办法将音频流保存到本地文件?我非常缺乏经验,我不知道从哪里开始 - 一个正确方向的点将不胜感激。

我正在构建一个从 URL 流式传输音频的应用程序(例如 http://audiostream.mp3)。我希望用户能够将音频保存到文件中,从他们开始收听时开始。由于音频将是一个流,我担心的是我没有处理完整的 mp3 文件——我猜这比简单地下载完整的 mp3 更棘手。

在此先感谢您的帮助。

【问题讨论】:

  • 如果你能得到整个文件,你应该可以trim it。如果您正在构建一个流媒体应用程序,您应该能够将其解码并保存为 mp3。
  • 太棒了——谢谢。如果我有任何问题,我会阅读并报告:)
  • 嗨——我还在玩这个方法。需要先尝试解决一些问题......但我可能需要回到你身边。
  • 这个方法好像会报错:(.
  • 嗨——对不起,我不明白你的意思。我没有完全理解,这就是我寻求指导的原因;)。这件事你能帮我吗?

标签: ios objective-c xcode file audio


【解决方案1】:

您可以无限期保存实时音频流。您需要使用ResourceLoaderURlSessionDataTask

这个过程有点棘手,所以我会一步一步解释:

  1. 制作一个 AVURLAsset:

    let asset = AVURLAsset(url: urlWithCustomScheme)
    
  2. 设置委托:

    asset.resourceLoader.setDelegate(resourceLoaderDelegate, queue: DispatchQueue.main)
    
  3. 以下委托函数将被调用:

    func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool
    
  4. 现在在这个函数内部我们将调用一个函数来开始数据请求,这样就可以开始下载声音缓冲区了:

    func startDataRequest(with url: URL) {
        var recordingName = "default.mp3"
        if let recording = owner?.recordingName{
            recordingName = recording
        }
        fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            .appendingPathComponent(recordingName)
        let configuration = URLSessionConfiguration.default
        configuration.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
        session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
        session?.dataTask(with: url).resume()
        outputStream = OutputStream(url: fileURL, append: true)
        outputStream?.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
        outputStream?.open()
    }
    

    如您所见,我们打开了一个输出流。我们将使用这个流将缓冲区写入我们的磁盘。

  5. 现在,当我们使用给定的 URL 启动 dataTask 时,我们将开始将数据字节接收到委托函数中:

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
    
  6. 现在我们已经开始接收实时音频流了。最后一块拼图是存储音频流。这是最简单的部分。我们只需创建一个 OutputStream 对象,打开它,然后在上面的委托函数中附加我们接收到的字节,就是这样,我们保存了实时音频流的所需部分。

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        let bytesWritten = data.withUnsafeBytes{outputStream?.write($0, maxLength: data.count)}
        print("bytes written :\(bytesWritten!) to \(fileURL)")
    }
    

这是我在 Medium 博客上写的源代码,解决了你遇到的问题:https://github.com/pandey-mohan/LiveAudioCapture

【讨论】:

    【解决方案2】:

    您可以在播放的同时保存缓冲的歌曲。

      NSData *aData = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.noiseaddicts.com/samples_1w72b820/274.mp3"]];
        NSError *aError;
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
        NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"/MyFolder.mp3"];
        NSLog(@"%@",dataPath);
        [aData writeToFile:dataPath atomically:YES];
    
        aPlayer = [[AVAudioPlayer alloc]initWithData:aData error:&aError];
        if (aError) {
            NSLog(@"Erri %@",aError.description);
        }
        aPlayer.volume = 1;
        [aPlayer play];
    

    【讨论】:

    • 嗨——我无法让它工作。使用我的 url 时,代码停留在第一行(NSData)。我认为这是因为 URL 是一个流(如无线电广播)而不是一个完整的文件(例如一首歌曲)。你有什么想法?
    • 你的音频文件有多大?
    • URL是音频流;因此我猜你访问它的时间越长它就越大。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多