AVPlayer播放更新标签会导致问题

时间:2015-09-17 06:23:41

标签: ios swift avplayer

我遇到AVPlayer播放和同时更新标签的问题。

我有计时器,用播放器的进度更新标签,但是我的视频卡在同一位置...检查下面的图像...按钮点击计时器启动后导致问题..

enter image description here

代码:

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()))"
}  

示例项目链接

  

Source code

     

注意:如果您使用示例项目,请在视频中添加视频。我只是因为文件大小而删除视频

问题

  • 如何避免这种情况?为什么会发生这种情况,因为当我使用MPMovieController时它运行得很好。

2 个答案:

答案 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进程。