为什么要先下载AVPlayer而不是实时流媒体? [英] Why AVPlayer downloading first instead live streaming?

查看:114
本文介绍了为什么要先下载AVPlayer而不是实时流媒体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我第一次使用AVPlayer,我想使用HTTP请求和实时流播放mp3文件.我使用AVPlayer可以正常播放mp3文件,但是问题是AVPlayer需要先下载mp3然后再播放.我不知道为什么AVPlayer下载文件然后播放而不是实时播放.我的Xcode 8.2.1和我正在使用Swift3.

First time I am working with AVPlayer and I want to play a mp3 file using HTTP request with live streaming. I use AVPlayer that is working fine to play mp3 files, but the problem is AVPlayer needs to download the mp3 first then play it. I don't know why AVPlayer downloads the file and then play it instead of live playing. My Xcode 8.2.1 and I am using Swift 3.

这是我的代码段.

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

如果AVPlayer需要在播放之前下载整个文件,我该如何进行音频实时流传输?

In case of AVPlayer requires to download the whole file before playing it, what should I do for audio live streaming?

谢谢.

推荐答案

另外 Luaan 是正确的. "实时流传输需要服务器支持-至少能够进行部分下载.其他播放器是否允许使用该URL进行实时流传输?"您还应该尝试使用未定义持续时间的声音URL.

Edit for in addition: Also Luaan is right. "Live streaming needs server support - at least the ability to do partial downloads. Does some other player allow live streaming with that URL?" You should also try with an undefined duration sound url.

您是否尝试过将其定义为持续时间不确定的音频流?

Have you tried to approach like it is an undefined duration audio stream ?

  avplayerItem = CachingPlayerItem(url: url, recordingName: recordingName ?? "default.mp3")

CachingPlayerItem将从URL准备一个AVURLAsset.

CachingPlayerItem going to prepare an AVURLAsset from the url.

 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加载音频流的过程:

After AVPlayerItem is initialized, make an AVPlayer object from it so that it can kick start the process of loading audio stream from the given 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()
}

然后,开始将数据字节接收到委托函数中:

Then, start receiving data bytes into the delegate function:

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

现在您已经开始接收实时音频流.

Now you have started receiving live audio stream.

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对象,打开它,然后在上面的委托函数中附加我们要接收的字节,就这样,我们保存了实时音频流的所需部分.

Now create an OutputStream object, open it then append the bytes we are receiving in the above delegate function and thats it, we saved the desired part of the live audio stream.

来自:媒体文章,Mohan Pandey

这篇关于为什么要先下载AVPlayer而不是实时流媒体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆