ios - AVFragmentedAssetMinder 不能在 iPhone 设备上运行,但可以在模拟器上运行
问题描述
我们有来自 WebSecureSocket (wss://) 的片段电影数据。我们将其写入temp.mp4并同时播放写入文件的片段。因此,我们为此使用了 AVFragmentedAsset和AVFragmentedAssetMinder。它在模拟器中按预期工作。但在设备中,不会更新资产的持续时间,也不会发布.AVAssetDurationDidChange通知。不知道可能是什么问题。已经花了 2 天时间弄清楚这一点,但没有运气。有人可以帮我解决这个问题吗,
执行..
public class WssPlayerSource: WebSocketDelegate {
static let ASSET_MINDER = AVFragmentedAssetMinder()
private let socketClient: WebSocketStreamingClient
private var tempMovieFile:FileHandle? = nil
private var startedPlay = false
private var fragmentedAsset: AVFragmentedAsset? = nil
let player = AVPlayer()
init(withUrl url: URL) {
socketClient = WebSocketStreamingClient(wssUrl: url)
socketClient.delegate = self
do {
self.tempMovieFile = try getTemporaryMovieFileWriter()
}catch {
print("Error opening file")
}
NotificationCenter.default.addObserver(self, selector: #selector(onVideoUpdate), name: .AVAssetDurationDidChange, object: nil)
socketClient.connect()
}
// Socket delegate
public func didReceive(event: WebSocketEvent, client: WebSocket) {
switch event {
case .binary(let data):
self.tempMovieFile?.write(data)
if !startedPlay {
startedPlay = true
DispatchQueue.global().async { [weak self] in
self?.didReceivedInitialData()
}
}
break;
default:
break;
}
}
func didReceivedInitialData() {
fragmentedAsset = AVFragmentedAsset(url: getTemporaryMovieFile()!)
fragmentedAsset?.loadValuesAsynchronously(forKeys: ["duration", "containsFragments", "canContainFragments"], completionHandler: {
WssPlayerSource.ASSET_MINDER.mindingInterval = 1
WssPlayerSource.ASSET_MINDER.addFragmentedAsset(self.fragmentedAsset!)
self.player.replaceCurrentItem(with: AVPlayerItem(asset: self.fragmentedAsset!))
self.player.play()
})
}
@objc
func onVideoUpdate() {
print("Video duration updated..")
// This is not called in device.. but in simulator it works as expected
}
func stop() {
socketClient.forceDisconnect()
NotificationCenter.default.removeObserver(self)
if let asset = self.fragmentedAsset {
WssPlayerSource.ASSET_MINDER.addFragmentedAsset(asset)
}
}
}
和
class ViewController: UIViewController {
@IBOutlet var playerView:PlayerView!
private static let SOCKET_URL = "wss://..."
private var playerSource:WssPlayerSource? = nil
private var playerLayer:AVPlayerLayer? = nil
override func viewDidLoad() {
super.viewDidLoad()
self.playerSource = WssPlayerSource(withUrl: URL(string: ViewController.SOCKET_URL)!)
self.playerLayer = AVPlayerLayer(player: self.playerSource!.player)
self.playerLayer?.videoGravity = .resize
self.playerView.layer.addSublayer(self.playerLayer!)
}
}
解决方案
推荐阅读
- angular - 在 Azure 中托管时,Angular 应用程序刷新不起作用
- javascript - Vue.js 附加多个类
- machine-learning - 这是过拟合的例子吗?
- ruby-on-rails-4 - Redirect_to 声称可以工作,但实际上并没有在浏览器中发生
- wix - Windows 安装程序:哪些文件被视为“版本化”
- android - 在手机上运行应用程序失败(Android Studio)
- java - 来自 Android 的“网络无法访问”,但在 Python 客户端上运行良好
- parsing - 在 LUA 中解析字符串
- java - 从 Java 调用存储过程
- java - 为什么 compareTo BigInteger while 循环不退出?