Sha*_*ang 7 video objective-c avfoundation ios swift
我去创建AVPlayerItem经过AVURLAsset,我的代码:
let asset = AVURLAsset(URL: safeURL, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
asset.loadValuesAsynchronouslyForKeys([assetKeyPlayable, self.assetKeyTracks, self.assetKeyHasProtectedContent]) {
() -> Void in
dispatch_async(dispatch_get_main_queue(), {
() -> Void in
// Use the AVAsset playable property to detect whether the asset can be played
if !asset.playable {
let localizedDescription = "Item cannot be played,Item cannot be played description"
let localizedFailureReason = "The assets tracks were loaded, but could not be made playable,Item cannot be played failure reason"
let userInfo = [NSLocalizedDescriptionKey: localizedDescription, NSLocalizedFailureReasonErrorKey: localizedFailureReason]
let error = NSError(domain: "domain", code: 0, userInfo: userInfo)
self.videoPlayerDelegate?.videoPlayer?(self, playerItemStatusDidFail: error)
self.cleanPlayer()
return
}
// At this point we're ready to set up for playback of the asset. Stop observing
if let _ = self.player?.currentItem {
self.cleanPlayer()
}
if asset.URL.absoluteString != safeURL.absoluteString {
return
}
var error: NSError?
let status = asset.statusOfValueForKey(self.assetKeyTracks, error: &error)
var playerItem = AVPlayerItem(URL: safeURL)
if status == .Loaded {
playerItem = AVPlayerItem(asset: asset)
} else {
// You should deal with the error appropriately.If Loaded fails, create an AVPlayerItem directly from the URL
playerItem = AVPlayerItem(URL: safeURL)
}
self.player = self.playerWithPlayerItem(playerItem)
self.registerMonitoring()
self.registerNotification()
self.addTimeObserver()
completionBlock?(loadURLString: playerURL.absoluteString)
})
}
Run Code Online (Sandbox Code Playgroud)
AVPlayerLayer在我的视图中添加显示视频,我的代码:
// MARK: - 财产
var player: AVPlayer? {
get {
return playerLayer.player
}
set {
playerLayer.player = newValue
}
}
var playerLayer: AVPlayerLayer {
return layer as! AVPlayerLayer
}
Run Code Online (Sandbox Code Playgroud)
完成加载后显示视频
self.videoPlayer?.loadPlayer({
[weak self](loadURLString) in
if let strongSelf = self {
strongSelf.player = strongSelf.videoPlayer?.player
strongSelf.startPlay()
}
})
Run Code Online (Sandbox Code Playgroud)
调用seekToTime方法来指定播放:
self.player?.currentItem?.seekToTime(CMTimeMakeWithSeconds(time, Int32(NSEC_PER_SEC)), toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero) {
[weak self] finished in
if let weakSelf = self {
if weakSelf.isPlaying {
weakSelf.videoPlayerDelegate?.videoPlayerDidplayerItemSeekToTime?(weakSelf)
}
}
}
Run Code Online (Sandbox Code Playgroud)
卡住界面的一些图片:

在第一张图片中,声音是可听见的,但界面卡住了.

在第二张图片中,视频有效,但我没有声音.
我的问题:
当我seekToTime在完成时调用该方法时,有时视频会有声音,但界面会卡住,有时视频会正常工作.我试图调用CALayer setNeedsDisplay方法,更新AVPlayerLayer图片,但这没有帮助.我不知道该怎么办,我会感激每一个和任何帮助.
由于这种情况以不同的方式发生在我们许多人身上并且没有得到回答,所以我在这里回答它,对我来说,当我尝试使用 AVPlayer 和 AVPlayerLayer 在 UIView 中播放视频时,但当我使用相同的 AVPlayer 来播放视频时,就会发生这种情况在 AVPlayerViewController 中加载视频,视频卡住,音频继续播放。
诀窍是在其他地方使用相同的 AVPlayer 之前销毁 AVPlayerLayer ,不敢相信我在这里找到了这个启示。
https://twitter.com/skumancer/status/294605708073263104
我是如何实现这个的?
我在主故事板中创建了 2 个视图控制器。
1) 视图控制器场景 i) 其中有一个引用 IBOutlet 'videoView' 的 UIView ii) 带有连续导航的按钮,用于“显示”引用 IBOutlet '全屏' 的 AV 播放器视图控制器场景 2) AV 播放器视图控制器场景
// Code in your controller class.
// Make sure to reference your IBOutlet in your StoryBoard.
@IBOutlet weak var videoView : UIView!
@IBOutlet weak var fullscreen : UIButton!
var player:AVPlayer? = nil;
var playerLayer:AVPlayerLayer? = nil;
override func viewDidLoad() {
super.viewDidLoad()
// Your Url to play, could be hls type video
let url = URL(string: "https://your_url.m3u8");
let asset = AVAsset(url : url!)
let playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: playerItem)
}
override func viewDidAppear(_ animated: Bool) {
playInUIView()
pauseVideo()
}
// Creates An AVPlayerLayer and adds it as a sublayer in UIView.
func playInUIView(){
// Creating player layer to render video.
playerLayer = AVPlayerLayer(player: player)
playerLayer?.frame = self.videoView.bounds
playerLayer?.videoGravity = .resizeAspect
// Adding a sub layer to display it in UIView
self.videoView.layer.addSublayer(playerLayer!)
}
// Destroyes an AVPlayerLayer and Sublayer of your UIView
func destroyPlayInView(){
self.videoView.layer.sublayers=nil
playerLayer = nil
}
// On button click open AVPlayerViewController.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destination = segue.destination as! AVPlayerViewController
// Destroy AVPlayerLayer before rendering video in AVPlayerViewController.
destroyPlayInView()
// Set same AVPlayer in AVPlayerViewController.
destination.player = self.player
self.present(destination, animated: true) {
destination.player!.play()
}
}Run Code Online (Sandbox Code Playgroud)
PS - 我还没有实现任何控件,并且可能存在编码不当的情况,因为我几天前才开始进行 swift 和 IOS 开发,所以请让我知道我哪里错了。
尝试这种方法,因为我遇到了同样的问题并通过这种方法解决它。
player.pause()
player.currentItem?.seek(to: CMTime(), completionHandler: { (_) in
player.play()
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1932 次 |
| 最近记录: |