ios 从NSData分配AVAsset

tquggr8v  于 2023-03-09  发布在  iOS
关注(0)|答案(4)|浏览(180)

我可以从NSData初始化AVAsset吗?我知道我可以使用如下函数从url初始化AVData

[[AVURLAsset alloc] initWithURL:url options:nil];

有人能给我一个类似的方法,直接从NSData赋值AVAsset吗?

apeeds0o

apeeds0o1#

据我所知,AVAsset表示设备的(内部)媒体库中的项目,因此使用自定义数据初始化它没有多大意义。也许值得一提的是,该类没有NSData的公共初始化器。
我猜想,如果需要的话,您很可能需要重新设计代码逻辑。

rta7y2nd

rta7y2nd2#

接受的答案不正确。
可以通过AVAssetResourceLoaderDelegate实现从NSData创建AVAsset
具体实施:

func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool

它必须:
1.正确填写loadingRequest.contentInformationRequest,提示使用loadingRequest.contentInformationRequest.contentType = AVFileType.mycontenttype.rawValue
1.正确响应数据
稍后我将发布一些代码,但是您可以在Google上搜索“AVAssetResourceLoaderDelegategithub”以获取示例

yb3bgrhw

yb3bgrhw3#

这是我解决这个问题的另一种方法。我间接地先将NSData写入/保存到本地目录,然后从该文件路径初始化AVAsset。

AVAsset *asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:locationUrl]];

您可以尝试先将nsdata写入文件路径,然后从该路径初始化为AVAsset。

[videoData writeToFile: locationUrl atomically:YES];

只要确保文件位置的URL是正确的,也测试确认如果数据被保存到该文件路径,如果加载时发生任何错误。最后不要忘记清理您的文件,如果你不再需要他们。

nwlls2ji

nwlls2ji4#

不确定NSData与Data的区别,
但我使用安装了AVAssetResourceLoaderDelegate的子类AVDataAsset来解决@ iamcomputer建议的问题,如下所示:

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")

显然,这里有些位是硬编码的,需要更改,但原则应该是清楚的。
同样值得注意的是,URL方案不能是要调用的委托的已知方案(+SchemeSuffix可以做到这一点)

相关问题