ios - 如何使用Swift Concurrency加载AVQueuePlayer?

标签 ios swift avfoundation avplayer avqueueplayer

我有大约 200 个音频资源,每个资源大约 5 秒,已加载到 AVQueuePlayer 中。我这样做是为了将所有资源作为一首完整的歌曲播放,但允许用户查看或跳转到特定的诗句。

问题是当我像这样加载它们时主线程被锁定:

let items = urls
    .map(AVAsset.init)
    .map(AVPlayerItem.init)

let player = AVQueuePlayer(items: items)

然后我发现我必须将它们异步加载到播放器中,所以尝试了这样的事情:

let items = urls
    .map(AVAsset.init)
    .map(AVPlayerItem.init)

let player = AVQueuePlayer()

// Below does NOT compile!!
await withThrowingTaskGroup(of: Void.self) { group in
    for var item in items {
        group.addTask { _ = try await item.asset.load(.duration) }
        for try await result in group {
            player?.insert(item, after: nil)
        }
    }
}

我仅支持 iOS 16+,因此我尝试使用 AVFoundation 中提供的新 Swift Concurrency API。我尝试遵循 this document但还有很多我无法完全理解的差距。在不锁定主线程的情况下将这么多资源加载到队列播放器中的正确方法是什么?

最佳答案

因为您似乎试图直接影响itemsplayer,所以我会使用actor。让一切保持在一起并同步。

要绕过在并发执行的代码中捕获的var“item”,您可以使用.enumerated()

actor PlayerLoader{
    let items = [URL(string: "https://v.ftcdn.net/01/53/82/41/700_F_153824165_dN7n9QftImnClb7z1IJIjbLgLlkHyYDS_ST.mp4")!]
        .map(AVAsset.init)
        .map(AVPlayerItem.init)
    
    let player = AVQueuePlayer()
    
    func loadItems() async throws{
        try await withThrowingTaskGroup(of: Void.self) { group in
            for (idx, _) in items.enumerated() {
                group.addTask { [weak self] in
                    _ = try await self?.items[idx].asset.load(.duration)
                }
                for try await _ in group {
                    player.insert(items[idx], after: nil)
                }
            }
        }
    }
}

然后只需使用 TaskTask.detached 调用 loadItems

let loader = PlayerLoader()

let task = Task{ //or Task.detached   depending on where you will be calling this line of code
    do{
        try await loader.loadItems()
        print("total number of items loaded \(loader.player.items().count)")
    }catch{
        print(error)
        throw error
    }
}

关于ios - 如何使用Swift Concurrency加载AVQueuePlayer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74748934/

相关文章:

ios - 写类别时,我应该使用self还是类别名称

ios - 沿特定角度的方向移动 View

ios - 没有完整引用的 Firebase 查询 2 级深度

ios - 在 Storyboard 中将 ViewController 嵌入另一个 ViewController

ios - UI 在连接到新 View Controller 时不会改变

ios - 在 iOS 中通过 URL 播放视频

swift - 映射 Documents 目录下的 mp3 并转换为 AVPlayerItems

ios - 延迟后在后台播放一系列音频片段

ios - 在 Swift 2 中创建 MTAudioProcessingTapCallbacks

ios - CoreData 可以在我的模拟器上使用 xCode 6 在 iOS 8 Swift 的 iPhone 上使用但不能在我的 iPhone 上使用