TL; DR:如果我将视频存储在Assets.xcassets中,我该如何播放视频?
我想在应用中存储大约50个视频。然后我将使用按需资源获取来使我的应用程序大小更轻。但我只能通过将视频保存在Assets.xcassets中来实现这一目标。而且我找不到从那里加载视频的方法,因为AVPlayer似乎只接受网址,而我真的不确定如何才能获得像这样的本地存储资产。
更新
所以我做了进一步的挖掘,发现它实际上无法将视频存储在资产目录中,仍然可以使用它们。我最终不得不将它们从资产目录中移出。至于随需应变资源提取,目录之外的资源仍然可能。您可以找到类似的方法here。
答案 0 :(得分:1)
尝试使用Apple Developer Documentation中所述的 AVAsset 。
AVPlayerItem可以加载AVAsset并播放它。有关加载AVAssets的文档的片段:
func prepareToPlay() {
let url: URL = // Local or Remote Asset URL
let asset = AVAsset(url: url)
let assetKeys = [
"playable",
"hasProtectedContent"
]
// Create a new AVPlayerItem with the asset and an
// array of asset keys to be automatically loaded
playerItem = AVPlayerItem(asset: asset,
automaticallyLoadedAssetKeys: assetKeys)
// Register as an observer of the player item's status property
playerItem.addObserver(self,
forKeyPath: #keyPath(AVPlayerItem.status),
options: [.old, .new],
context: &playerItemContext)
// Associate the player item with the player
player = AVPlayer(playerItem: playerItem)
}
获取资产的网址可能看起来像这样:
let urlpath = Bundle.main.path(forResource: "myvideo", ofType: "mp4")
let url = NSURL.fileURL(withPath: urlpath!)
答案 1 :(得分:0)
您可以在资产目录中存储所需的任何数据。但是,您只能将其加载为NSDataAsset
,这会给您NSData
。结果,您做了一些URL资源处理程序,以获取直接从NSData读取的URL。
它是这样的。
let videoUrl = URL(string: "my-custom-scheme-not-important://\(assetName)")!
let asset = AVURLAsset(url: videoUrl)
guard let dataAsset = NSDataAsset(name: assetName) else {
fatalError("Data asset not found with name \(assetName)")
}
let resourceDelegate = DataAssetAVResourceLoader(dataAsset: dataAsset)
assetLoaderDelegate = resourceDelegate
asset.resourceLoader.setDelegate(resourceDelegate, queue: .global(qos: .userInteractive))
let item = AVPlayerItem(asset: asset)
...
@objc
fileprivate class DataAssetAVResourceLoader: NSObject, AVAssetResourceLoaderDelegate {
let dataAsset: NSDataAsset
let data: Data
init(dataAsset: NSDataAsset) {
self.dataAsset = dataAsset
data = dataAsset.data
}
@objc
public func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
if let infoRequest = loadingRequest.contentInformationRequest {
infoRequest.contentType = kUTTypeQuickTimeMovie as String
infoRequest.contentLength = Int64(data.count)
infoRequest.isByteRangeAccessSupported = true
}
if let dataRequest = loadingRequest.dataRequest {
let range = Range(NSRange(location: Int(dataRequest.requestedOffset), length: dataRequest.requestedLength))!
dataRequest.respond(with: data.subdata(in:range))
loadingRequest.finishLoading()
return true
}
return false
}
}
答案 2 :(得分:0)
现在可以将视频加载到Assets.xcassets中,并且仍然可以播放它们。 在Xcode 12.0.1 Swift 5上测试
import UIKit
import AVKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
func createLocalUrl(for filename: String, ofType: String) -> URL? {
let fileManager = FileManager.default
let cacheDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)[0]
let url = cacheDirectory.appendingPathComponent("\(filename).\(ofType)")
guard fileManager.fileExists(atPath: url.path) else {
guard let video = NSDataAsset(name: filename) else { return nil }
fileManager.createFile(atPath: url.path, contents: video.data, attributes: nil)
return url
}
return url
}
@IBAction func playLocalVideo(_ sender: Any) {
guard let videoURL = createLocalUrl(for: "video", ofType: "mp4") else {
return
}
// Create an AVPlayer, passing it the local video url path
let player = AVPlayer(url: videoURL as URL)
let controller = AVPlayerViewController()
controller.player = player
present(controller, animated: true) {
player.play()
}
}
}
相信如何创建本地网址:https://stackoverflow.com/a/39748919/4267092