我第一次使用AVPlayer,我想使用带有直播的HTTP请求播放mp3文件。我使用AVPlayer
工作正常播放mp3文件,但问题是AVPlayer
需要首先下载mp3然后播放它。我不知道为什么var audioPlayer = AVPlayer()
var avplayerItem : AVPlayerItem?
override func viewDidLoad() {
super.viewDidLoad()
let fileurl:URL = URL(string : "http://www.noiseaddicts.com/samples_1w72b820/2514.mp3")!
avplayerItem = AVPlayerItem(url : fileurl)
audioPlayer = AVPlayer(playerItem : avplayerItem)
audioPlayer.rate = 1.0
audioPlayer.play()
}
下载文件然后播放而不是实时播放。我的Xcode 8.2.1和我正在使用Swift 3.
这是我的代码段。
AVPlayer
如果{{1}}要求在播放之前下载整个文件,我该怎么办音频直播?
感谢。
答案 0 :(得分:0)
另外编辑:Luaan也正确。 “ 实时流传输需要服务器支持-至少能够进行部分下载。其他播放器是否允许使用该URL进行实时流传输?”您还应该尝试使用未定义持续时间的声音URL。
您是否尝试过将其定义为持续时间不确定的音频流?
avplayerItem = CachingPlayerItem(url: url, recordingName: recordingName ?? "default.mp3")
CachingPlayerItem将从URL准备一个AVURLAsset。
init(url: URL, customFileExtension: String?, recordingName: String) {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
let scheme = components.scheme,
var urlWithCustomScheme = url.withScheme(cachingPlayerItemScheme) else {
fatalError("Urls without a scheme are not supported")
}
self.recordingName = recordingName
self.url = url
self.initialScheme = scheme
if let ext = customFileExtension {
urlWithCustomScheme.deletePathExtension()
urlWithCustomScheme.appendPathExtension(ext)
self.customFileExtension = ext
}
let asset = AVURLAsset(url: urlWithCustomScheme)
asset.resourceLoader.setDelegate(resourceLoaderDelegate, queue: DispatchQueue.main)
super.init(asset: asset, automaticallyLoadedAssetKeys: nil)
resourceLoaderDelegate.owner = self
addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.new, context: nil)
NotificationCenter.default.addObserver(self, selector: #selector(playbackStalledHandler), name:NSNotification.Name.AVPlayerItemPlaybackStalled, object: self)
}
初始化AVPlayerItem之后,从中创建一个AVPlayer对象,以便它可以启动从给定URL加载音频流的过程:
player = AVPlayer(playerItem: playerItem)
player.automaticallyWaitsToMinimizeStalling = false
func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
if playingFromData {
// Nothing to load.
} else if session == nil {
// If we're playing from a url, we need to download the file.
// We start loading the file on first request only.
guard let initialUrl = owner?.url else {
fatalError("internal inconsistency")
}
startDataRequest(with: initialUrl)
}
pendingRequests.insert(loadingRequest)
processPendingRequests()
return true
}
一旦安装了资源:
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()
}
然后,开始将数据字节接收到委托函数中:
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
现在您已经开始接收实时音频流。
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)")
}
现在创建一个OutputStream对象,打开它,然后在上面的委托函数中附加我们要接收的字节,就这样,我们保存了实时音频流的所需部分。