Non sûr de la différence entre NSData et Data,
mais j'utilise une sous-classe AVDataAsset qui a installé un AVAssetResourceLoaderDelegate pour résoudre le problème comme suggéré par @iamacomputer comme ci-dessous:
class AVDataAsset: AVURLAsset, AVAssetResourceLoaderDelegate {
private let myUrl: URL
private var mediaData = Data()
init(url: URL,data: Data?) {
myUrl = url
let retURL: URL
if let data {
mediaData = data
guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
fatalError()
}
components.scheme = (components.scheme ?? "") + "SchemeSuffix"
guard let newURL = components.url else {
fatalError()
}
retURL = newURL
} else {
retURL = url
}
super.init(url: retURL, options: nil)
self.resourceLoader.setDelegate(self, queue: DispatchQueue.main)
// print("Size: \(mediaData.count)")
}
func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
let request = loadingRequest
if let ri = request.contentInformationRequest {
ri.isByteRangeAccessSupported = true
ri.contentType = "video/quicktime"
ri.contentLength = Int64(mediaData.count)
}
if let dataRequest = request.dataRequest {
let downloadedData = self.mediaData
let downloadedDataLength = Int64(downloadedData.count)
let requestCurrentOffset = dataRequest.currentOffset
let requestRequestedOffset = dataRequest.requestedOffset
let requestRequestedLength = Int64(dataRequest.requestedLength)
let downloadedUnreadDataLength = downloadedDataLength - requestCurrentOffset
let requestUnreadDataLength = requestRequestedOffset + requestRequestedLength - requestCurrentOffset
let respondDataLength = min(requestUnreadDataLength, downloadedUnreadDataLength)
dataRequest.respond(with: downloadedData.subdata(in:
Range(NSMakeRange(Int(requestCurrentOffset), Int(respondDataLength)))!))
}
request.finishLoading()
return true
}
}
let url = URL(string: "file:///Users/thilo/Desktop/Input/IMG_0128%20copy.MOV")!
guard let data = try? Data(contentsOf: url)
else { fatalError() }
let dataAsset = AVDataAsset(url: url, data: data)
Task{
let asset = dataAsset
if let tracks = try? await asset.load(.tracks),
let frameRate = try? await tracks[0].load(.minFrameDuration),
let duration = try? await asset.load(.duration) {
print("frame: \(1/frameRate.seconds) Dura: \(duration.seconds)")
}
}
print("Done AVDataAsset")
Évidemment, certains éléments sont codés en dur ici et doivent être modifiés mais le principe devrait être clair.
Il est également bon de noter que le schéma d'URL ne doit pas être un schéma connu pour que le délégué soit appelé (+SchemeSuffix le fait)