2

たくさんの投稿があることは知っていますが、どれも役に立ちませんでした。デバイスで異なる FPS のビデオを持っています (何らかの形で問題がある場合)。正確に計算してCMTimeいます (秒に換算すると、10.33333、10.4444 などになります)。私はこのコードを使用して探しています:

  self.player.seekToTime( time, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)

前進のみスムーズに進みますが、後退はスムーズに進みません。理由はありますか?

4

3 に答える 3

4

これは、圧縮されたビデオが「キーフレーム」で機能するためです。キー フレームは完全にレンダリングされたビデオ フレームですが、すべてのフレームがキー フレームというわけではありません。キー フレームに続くフレームは、そのキー フレームからの増分差分としてのみ保存されます。これは、ビデオを前方に移動しているときに、プレーヤーがキー フレームを表示し、次のフレームに移動して変更を描画し、次のフレームに移動するなどを意味します。ビデオを後方に移動する場合、プレーヤーが実際に表示できるのは唯一のものです。キーフレームです。通常、エンコードされたデータを使用して、キー フレームとキー フレームの数フレーム後に表示されるため、ビデオのその時点で何が起こっているかがわかります。これを回避する唯一の方法は、ビデオをバッファに解凍し、それを逆方向にスキャンすることです。明らかな理由から、これはほとんどの目的に対して遅すぎます。

http://www.dacast.com/blog/what-is-a-key-frame-for-video/

于 2016-04-14T08:22:36.440 に答える
1

このホープを試してみてください

     let timeScale: Int32 = (self.playerController1.player?.currentItem!.asset.duration.timescale)!

    let time: CMTime = CMTimeMakeWithSeconds(77.000000, timeScale)

    self.playerController1.player?.seekToTime(time,toleranceBefore:kCMTimeZero ,toleranceAfter:kCMTimeZero)
于 2016-04-12T14:04:13.077 に答える
1

seekToTime を呼び出すと、プレーヤー アイテムは進行中の以前のシークをキャンセルするため、多くのシークが行われ、フレーム表示が少なくなります。bool var isSeekInProgressを使用して、プレイヤー アイテムがシーク中かどうかを示します。

次のように試してみましょう:

var isSeekInProgress = false
let player = <#A valid player object #>
var chaseTime = kCMTimeZero
// your player.currentItem.status
var playerCurrentItemStatus:AVPlayerItemStatus = .Unknown

...

func stopPlayingAndSeekSmoothlyToTime(newChaseTime:CMTime)
{
    player.pause()

    if CMTimeCompare(newChaseTime, chaseTime) != 0
    {
        chaseTime = newChaseTime;

        if !isSeekInProgress
        {
            trySeekToChaseTime()
        }
    }
}

func trySeekToChaseTime()
{
    if playerCurrentItemStatus == .Unknown
    {
        // wait until item becomes ready (KVO player.currentItem.status)
    }
    else if playerCurrentItemStatus == .ReadyToPlay
    {
        actuallySeekToTime()
    }
}

func actuallySeekToTime()
{
    isSeekInProgress = true
    let seekTimeInProgress = chaseTime
    player.seekToTime(seekTimeInProgress, toleranceBefore: kCMTimeZero,
            toleranceAfter: kCMTimeZero, completionHandler:
    { (isFinished:Bool) -> Void in

        if CMTimeCompare(seekTimeInProgress, chaseTime) == 0
        {
            isSeekInProgress = false
        }
        else
        {
            trySeekToChaseTime()
        }
    })
}

詳細情報: https://developer.apple.com/library/content/qa/qa1820/_index.html

于 2017-04-27T08:18:57.760 に答える