Objective C/IOS - 将音频流保存到文件

Posted

技术标签:

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

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

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

在此先感谢您的帮助。

【问题讨论】:

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

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

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

    制作一个 AVURLAsset:

    let asset = AVURLAsset(url: urlWithCustomScheme)
    

    设置委托:

    asset.resourceLoader.setDelegate(resourceLoaderDelegate, queue: DispatchQueue.main)
    

    以下委托函数将被调用:

    func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool
    

    现在在这个函数内部我们将调用一个函数来开始数据请求,这样就可以开始下载声音缓冲区了:

    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()
    
    

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

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

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
    

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

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) 
        let bytesWritten = data.withUnsafeBytesoutputStream?.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是音频流;因此我猜你访问它的时间越长它就越大。

以上是关于Objective C/IOS - 将音频流保存到文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 MPMoviePlayerController 将音频流保存到文件中

音频文件可以像照片和电影一样使用objective C保存在iphone中吗?

将音频流保存到磁盘的推荐方法

将音频流保存到 mp3 文件 (iOS)

ffmpeg仅将传入的RTP音频流保存到文件中

如何从 Objective C、iOS 中的 NSUserDefaults 获取准确数据?