gpt4 book ai didi

swift - AVAudioFile 中的 URL 为 nil

转载 作者:行者123 更新时间:2023-11-28 05:43:40 24 4
gpt4 key购买 nike

我正在尝试使用 AVAudioEngine 在背景音频文件之上播放多个音频文件。当我尝试初始化 backgroundAudioFile 时,应用程序崩溃并显示 :Thread 1: Fatal error: 'try!'表达式意外引发错误:Error Domain=com.apple.coreaudio.avfaudio Code=2003334207 "(null)"UserInfo={failed call=ExtAudioFileOpenURL((CFURLRef)fileURL, &_extAudioFile)}。

传递给初始化程序的 url 是有效的。打印出来。

import Foundation
import AVFoundation

class AudioPlayer {

var timeIndex = 0 // keeps track of the index of the item transveersed within `timesToTransverse` by `player?.addBoundaryTimeObserver`


var topAudioFiles: [AVAudioFile] = []
var engine:AVAudioEngine
var backgroundAudioNode: AVAudioPlayerNode
var backgroundAudioFile: AVAudioFile
var topAudioAudioNodes = [AVAudioPlayerNode]()
var mixer: AVAudioMixerNode
var timer: Timer!
var urls: [URL] = []
var player: AVPlayer!
var timesToTransverse = [NSValue]() //contains timeValues in seconds such as ["1.54",2.64, 67.20]
var delays = [UInt64]()

fileprivate var timeObserverToken: Any?

init (url: URL, urls: [URL] = [], timesToTransverse: [NSValue]) {

self.urls = urls
self.timesToTransverse = timesToTransverse
topAudioFiles = urls.map { try! AVAudioFile(forReading: $0) }

print("the remote url is \(url)")
// it prints the url is https://firebasestorage.googleapis.com/v0/b/salsaworld-658f3.appspot.com/o/adminAudioFiles%2F-LWv5rnKiLawXvsSsQgG.m4a?alt=media&token=19e8eac0-2b47-49e2-acd3-9a459903f84b

//it crashes on this line
backgroundAudioFile = try! AVAudioFile(forReading: url)


player = AVPlayer(url: url)
engine = AVAudioEngine()
mixer = AVAudioMixerNode()

engine.attach(mixer)
engine.connect(mixer, to: engine.outputNode, format: nil)
backgroundAudioNode = AVAudioPlayerNode()

initTopAudioNodes()
try! engine.start()
}


func initTopAudioNodes() {
for _ in topAudioFiles {
topAudioAudioNodes += [AVAudioPlayerNode()]
}

for node in topAudioAudioNodes {
engine.attach(node)
engine.connect(node, to: mixer, format: nil)
}
}//end initTopAudioNodes


func playWithAudioPlayerAndNodes() {
player.play()
var i = 1

timeObserverToken = player.addBoundaryTimeObserver(forTimes: timesToTransverse, queue: nil) {
[weak self] in

guard let self = self else {return}

let index = i % self.topAudioAudioNodes.count
let node = self.topAudioAudioNodes[index]
node.scheduleFile(self.topAudioFiles[index], at: nil, completionHandler: nil)
node.play()
i += 1

/* Because there are no time signature changes,
we can simply increment timeIndex with + 1 every time
`addBoundaryTimeObserver`'s completion handler is called.
Then, we subscript timesToTransverse with timeIndex
in order to get the subsequent timeInSeconds
*/
guard self.timeIndex < self.timesToTransverse.count else {return}
print("timeIndex is now \(self.timeIndex)")

let timeElement = self.timesToTransverse[self.timeIndex]
let timeInSeconds = CMTimeGetSeconds(timeElement.timeValue)

//use reminder operator to determine the beat count
let beat = (self.timeIndex + 1) % 8 == 0 ? 8 : ((self.timeIndex + 1) % 8)
print("Beat would be: ", beat)

/*
0: (0 + 1) % 8 = 1
1: (1 + 1) % 8 = 2
6: (6 + 1) % 8 = 7
7: (7 + 1) % 8 = 0
*/

self.timeIndex += 1

}//end class AudioPlayer




// create instance of class AudioPlayer and call func playWithAudioPlayerAndNodes



class HomeViewController {

override func viewDidLoad() {
super.viewDidLoad()

let bundle = Bundle.main
let one = bundle.url(forResource: "1", withExtension: "wav")!
let two = bundle.url(forResource: "2", withExtension: "wav")!
let three = bundle.url(forResource: "3", withExtension: "wav")!
let five = bundle.url(forResource: "5", withExtension: "wav")!
let six = bundle.url(forResource: "6", withExtension: "wav")!
let seven = bundle.url(forResource: "7", withExtension: "wav")!

// mediaArray contains string URL's downloaded from FirebaseDatabse
let mediaItem = mediaArray[tableIndexPath.row]
guard let backgroundAudio = URL(string: mediaItem.mediaAudioUrlStringRepresentation ?? "") else {return}

let audioPlayer = AudioPlayer(url:
backgroundAudio,
urls: [one, two, three, five, six, seven],
timesToTransverse: timesToTransverse)

//start playing
audioPlayer.playWithAudioPlayerAndNodes()
}
}

最佳答案

您不能在远程文件上调用 AVAudioFile(forReading:)。您需要下载二进制数据并使用 audio file stream services 将其解析为数据包。 .这样,您就可以将数据包提供给缓冲区并通过音频引擎从缓冲区播放。

关于swift - AVAudioFile 中的 URL 为 nil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55688901/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com