AVPlayer 播放更新标签导致问题
AVPlayer play with update label cause an issue
我在 AVPlayer
播放和同时更新标签时遇到问题。
我有计时器可以根据播放器的进度更新标签,但它会把我的视频卡在同一个位置...检查下图...按钮单击后计时器启动并导致问题..
代码:
func playVideo() {
let path = NSBundle.mainBundle().pathForResource("videoname", ofType:"mp4")
let fileURL = NSURL(fileURLWithPath: path!)
moviePlayer = AVPlayer(URL: fileURL)
// Play the video
moviePlayer!.play()
}
@IBAction func progresss(sender: UIButton) {
self.meterTimer = NSTimer.scheduledTimerWithTimeInterval(0.1,
target:self,
selector:"updateAudioMeter:",
userInfo:nil,
repeats:true)
}
func updateAudioMeter(timer:NSTimer) {
lbltime.text = "\(CMTimeGetSeconds(moviePlayer!.currentItem.currentTime()))"
}
示例项目link
Note:please add video in bundle if you are use sample project.I just delete video because of file size
问题
- 如何避免这种情况?以及为什么会发生这种情况,因为当我使用 MPMovieController 时它工作得很好。
我已经为 Objective-C
编写了示例代码,您可以在 swift
中相应地为您的项目转换相同的代码。
// Implement following code in AVPlayer observer method for `AVPlayerStatusReadyToPlay` state
[avPlayer addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(interval, NSEC_PER_SEC)
queue:NULL
usingBlock:
^(CMTime time)
{
// update label value here, it keeps invoking periodically internally.
CMTime playerDuration = [self playerItemDuration];
}];
// Method to get Player current time
- (CMTime)playerItemDuration
{
AVPlayerItem *thePlayerItem = [avPlayer currentItem];
if (thePlayerItem.status == AVPlayerItemStatusReadyToPlay)
{
return([avPlayerItem duration]);
}
return(kCMTimeInvalid);
}
如果你只是想更新它然后调用 playerItemDuration
来获取当前时间,但是让它 asynchronous
过程。
根据您的示例代码,问题出在函数以下:
override func viewDidLayoutSubviews() {
let layer = AVPlayerLayer(player: moviePlayer)
layer.frame = self.viewPlayer.frame
self.viewPlayer.layer.addSublayer(layer)
}
这将在每次标签更新时调整图层视图的大小,因此只需删除该代码并将其添加到 playVideo
方法中,您的方法将是:
func playVideo() {
let path = NSBundle.mainBundle().pathForResource("video", ofType: "MOV")
let url = NSURL.fileURLWithPath(path!)
moviePlayer = AVPlayer(URL: url)
moviePlayer!.allowsExternalPlayback = false
var introPlayerLayer = AVPlayerLayer(player: moviePlayer)
viewPlayer.layer.addSublayer(introPlayerLayer)
introPlayerLayer.frame = viewPlayer.bounds
moviePlayer!.play()
}
并在 viewDidAppear
中调用此方法而不是 viewDidLoad
方法,您的完整代码将是:
import UIKit
import MediaPlayer
import AVFoundation
class ViewController: UIViewController {
var moviePlayer : AVPlayer?
var meterTimer : NSTimer!
@IBOutlet weak var viewPlayer: UIView!
@IBOutlet weak var lbltime: UILabel!
override func viewDidAppear(animated: Bool) {
playVideo()
}
func playVideo() {
let path = NSBundle.mainBundle().pathForResource("video", ofType: "MOV")
let url = NSURL.fileURLWithPath(path!)
moviePlayer = AVPlayer(URL: url)
moviePlayer!.allowsExternalPlayback = false
var introPlayerLayer = AVPlayerLayer(player: moviePlayer)
viewPlayer.layer.addSublayer(introPlayerLayer)
introPlayerLayer.frame = viewPlayer.bounds
moviePlayer!.play()
}
@IBAction func progresss(sender: UIButton) {
moviePlayer?.seekToTime(kCMTimeZero)
moviePlayer?.addPeriodicTimeObserverForInterval(CMTimeMakeWithSeconds(1, 1), queue: nil, usingBlock: {
(CMTime) -> Void in
self.updateProgressBar()
})
}
func updateProgressBar(){
var timeNow = Int(self.moviePlayer!.currentTime().value) / Int(self.moviePlayer!.currentTime().timescale)
var currentMins = timeNow / 60
var currentSec = timeNow % 60
var duration: String = "\(currentMins):\(currentSec)"
self.lbltime.text = duration
}
}
我在 AVPlayer
播放和同时更新标签时遇到问题。
我有计时器可以根据播放器的进度更新标签,但它会把我的视频卡在同一个位置...检查下图...按钮单击后计时器启动并导致问题..
代码:
func playVideo() {
let path = NSBundle.mainBundle().pathForResource("videoname", ofType:"mp4")
let fileURL = NSURL(fileURLWithPath: path!)
moviePlayer = AVPlayer(URL: fileURL)
// Play the video
moviePlayer!.play()
}
@IBAction func progresss(sender: UIButton) {
self.meterTimer = NSTimer.scheduledTimerWithTimeInterval(0.1,
target:self,
selector:"updateAudioMeter:",
userInfo:nil,
repeats:true)
}
func updateAudioMeter(timer:NSTimer) {
lbltime.text = "\(CMTimeGetSeconds(moviePlayer!.currentItem.currentTime()))"
}
示例项目link
Note:please add video in bundle if you are use sample project.I just delete video because of file size
问题
- 如何避免这种情况?以及为什么会发生这种情况,因为当我使用 MPMovieController 时它工作得很好。
我已经为 Objective-C
编写了示例代码,您可以在 swift
中相应地为您的项目转换相同的代码。
// Implement following code in AVPlayer observer method for `AVPlayerStatusReadyToPlay` state
[avPlayer addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(interval, NSEC_PER_SEC)
queue:NULL
usingBlock:
^(CMTime time)
{
// update label value here, it keeps invoking periodically internally.
CMTime playerDuration = [self playerItemDuration];
}];
// Method to get Player current time
- (CMTime)playerItemDuration
{
AVPlayerItem *thePlayerItem = [avPlayer currentItem];
if (thePlayerItem.status == AVPlayerItemStatusReadyToPlay)
{
return([avPlayerItem duration]);
}
return(kCMTimeInvalid);
}
如果你只是想更新它然后调用 playerItemDuration
来获取当前时间,但是让它 asynchronous
过程。
根据您的示例代码,问题出在函数以下:
override func viewDidLayoutSubviews() {
let layer = AVPlayerLayer(player: moviePlayer)
layer.frame = self.viewPlayer.frame
self.viewPlayer.layer.addSublayer(layer)
}
这将在每次标签更新时调整图层视图的大小,因此只需删除该代码并将其添加到 playVideo
方法中,您的方法将是:
func playVideo() {
let path = NSBundle.mainBundle().pathForResource("video", ofType: "MOV")
let url = NSURL.fileURLWithPath(path!)
moviePlayer = AVPlayer(URL: url)
moviePlayer!.allowsExternalPlayback = false
var introPlayerLayer = AVPlayerLayer(player: moviePlayer)
viewPlayer.layer.addSublayer(introPlayerLayer)
introPlayerLayer.frame = viewPlayer.bounds
moviePlayer!.play()
}
并在 viewDidAppear
中调用此方法而不是 viewDidLoad
方法,您的完整代码将是:
import UIKit
import MediaPlayer
import AVFoundation
class ViewController: UIViewController {
var moviePlayer : AVPlayer?
var meterTimer : NSTimer!
@IBOutlet weak var viewPlayer: UIView!
@IBOutlet weak var lbltime: UILabel!
override func viewDidAppear(animated: Bool) {
playVideo()
}
func playVideo() {
let path = NSBundle.mainBundle().pathForResource("video", ofType: "MOV")
let url = NSURL.fileURLWithPath(path!)
moviePlayer = AVPlayer(URL: url)
moviePlayer!.allowsExternalPlayback = false
var introPlayerLayer = AVPlayerLayer(player: moviePlayer)
viewPlayer.layer.addSublayer(introPlayerLayer)
introPlayerLayer.frame = viewPlayer.bounds
moviePlayer!.play()
}
@IBAction func progresss(sender: UIButton) {
moviePlayer?.seekToTime(kCMTimeZero)
moviePlayer?.addPeriodicTimeObserverForInterval(CMTimeMakeWithSeconds(1, 1), queue: nil, usingBlock: {
(CMTime) -> Void in
self.updateProgressBar()
})
}
func updateProgressBar(){
var timeNow = Int(self.moviePlayer!.currentTime().value) / Int(self.moviePlayer!.currentTime().timescale)
var currentMins = timeNow / 60
var currentSec = timeNow % 60
var duration: String = "\(currentMins):\(currentSec)"
self.lbltime.text = duration
}
}