首页 文章

使用Swift AVPlayer显示视频轨道的时间码

提问于
浏览
0

我正在开发一个小应用程序来导航和播放包含 framerate 和初始 timecode 信息的视频(例如: "TimeCode" : "09:25:15:08" ) . 我正在使用 AVKit Player View Controller 来显示我的视频,我想添加一个显示当前时间码的UILabel .

我'm all set about the way to add up custom UI elements, but I'迷失了关于如何计算 timecode 并让它在视频播放的每一帧都自动更新 .

我已经阅读了AVFoundation - Timecode Support with AVAssetWriter and AVAssetReader,但我不确定我是否理解它 .

任何解释,指导或内容都将非常感激 .

更新:

经过一段时间的思考,我虽然可以使用帧数来 Build 我自己的时间码参考 .

注意 item is the AVPlayer

使用 var totalTime = CMTimeGetSeconds(item.currentItem.asset.duration) 我可以获得视频轨道的总长度(以秒为单位),以及 currentTime = CMTimeGetSeconds(item.currentItem.currentTime()) 来获取其当前时间位置 .

然后我可以做 var fps = item.currentItem.asset.tracks[0].nominalFrameRate 来获取帧速率并使用此变量来划分 totalTimecurrentTime 以获得总帧数以及当前帧 .

考虑到从总帧数中为每帧构建预标准化时间阵列的想法 . 这样我就可以知道确切的帧与时间戳有什么关系 .

我从来没有使用时间码或日期,所以如果有人知道如何做到这一点我会很感激帮助 .

基本上,时间码看起来像这样: HH:MM:SS:FF (FF是当前帧) . 如果fps = 24,则每秒每24帧添加到SS,依此类推 .

测试用例:

import UIKit
import AVKit
import AVFoundation

class ViewController: UIViewController {
    var player = AVPlayer()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        var url=NSURL(string: "http://km.support.apple.com/library/APPLE/APPLECARE_ALLGEOS/HT1211/sample_iTunes.mov")
        player = AVPlayer(URL: url)
        let playerController = AVPlayerViewController()

        playerController.player = player
        self.addChildViewController(playerController)
        self.view.addSubview(playerController.view)
        playerController.view.frame = self.view.frame

        //Debug btn
        var btn = UIButton()
        btn.frame = CGRect(x:10, y:50, width:100, height:30)
        btn.setTitle("FPS", forState: .Normal)
        btn.addTarget(self, action: "buttonTapAction:", forControlEvents: UIControlEvents.TouchUpInside)
        playerController.view.addSubview(btn)

        player.play()
//        getFps(player)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func getFps(item:AVPlayer) {
        var fps = item.currentItem.asset.tracks[0].nominalFrameRate
        println("FPS: \(fps)")

        var timeRange_src = CMTimeGetSeconds(item.currentItem.asset.duration)
        var timeRange = Float(timeRange_src)
        println("time Range: \(timeRange)")
        var frameCount = timeRange * fps
        println("total frames: \(frameCount)")

        var timeIs = Float(CMTimeGetSeconds(item.currentItem.currentTime()))
        var frameIs = timeIs * fps
        println("current time: \(timeIs)")
        println("current frame: \(frameIs)")

    }

    func buttonTapAction(sender:UIButton!)
    {
        getFps(player)
    }


}

2 回答

  • -1

    以下是我最近使用Swift 3的方法:

    func formatTimecode(frame: Int, fps: Double) -> String {
        let FF = Int(Double(frame).truncatingRemainder(dividingBy: fps))
        let seconds = Int(Double(frame - FF) / fps)
        let SS = seconds % 60
        let MM = (seconds % 3600) / 60
        let HH = seconds / 3600
    
        let timecode = [String(format: "%02d", HH), String(format: "%02d", MM), String(format: "%02d", SS), String(format: "%02d", FF)];
    
        return timecode.joined(separator: ":")
    }
    
  • 1

    好的,这就是我如何解决我的问题,并根据我的变量构建时间码:

    func pad(fps:Float, currentFrame:Float) -> (String){
            var fps = fps
            var frame = currentFrame + f
            var ff = frame % fps
            var seconds = s + ((currentFrame) / fps)
            var ss = seconds % 60
            var minutes = m + ((seconds - ss) / 60)
            var mm = minutes % 60
            var hh = h + ((minutes - mm) / 60)
            return "\(showTwoDigits(hh)):\(showTwoDigits(mm)):\(showTwoDigits(ss)):\(showTwoDigits(ff))"
        }
    
        func showTwoDigits(number:Float) -> (String){
            var string = ("00" + String(format:"%.f", number))
            var range = Range(start: (advance(string.endIndex, -2)), end: string.endIndex)
            var cutStr = string.substringWithRange(range)
            return cutStr
        }
    

相关问题