我遇到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()))"
}
示例项目链接
注意:如果您使用示例项目,请在视频中添加视频。我只是因为文件大小而删除视频
问题
答案 0 :(得分:2)
从示例代码中,问题出现在函数下面:
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
}
}
答案 1 :(得分:0)
我已经为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
进程。