2012-07-13 66 views
27

我有一個播放HLS視頻流的AVPlayer。我的用戶界面提供了一排按鈕,視頻中每個「章節」都有一個按鈕(按鈕標記爲「1」,「2」,「3」)。該應用程序從包含以秒錶示的章節切入點列表的服務器下載一些元數據。例如,一個視頻長度爲12分鐘 - 章節切入點列表爲0,58,71,230,530等等。AVPlayer seekToTime不能播放正確的位置

當用戶點擊其中一個「章節按鈕」時,按鈕處理程序代碼執行以下操作:

  [self.avPlayer pause]; 

    [self.avPlayer seekToTime: CMTimeMakeWithSeconds(seekTime, 600) 
       toleranceBefore: kCMTimeZero 
       toleranceAfter: kCMTimeZero 
      completionHandler: ^(BOOL finished) 
      { 
       [self.avPlayer play]; 
      }]; 

其中「seekTime」是包含切入點的本地變量(如上所述)。

問題是,視頻並不總是從正確的位置開始。有時候確實如此。但有時在請求的seekTime之前,它從十分之一秒到2秒。它永遠不會在請求的seekTime後啓動。

下面是對視頻編碼的一些統計數據:

編碼器:handbrakeCLI 編解碼器:H.264 幀速率:24(實際上,23.976 - 同樣,因爲它是怎麼拍) 視頻比特率:多種比特率( 64/150/300/500/800/1200) 音頻比特率:128K 關鍵幀:23.976(每秒1次)

我使用的是蘋果mediafilesegmenter工具,當然,並生成播放列表中的variantplaylistcreator。

這些文件是從Amazon Cloud/S3存儲桶提供的。

我還不清楚的一個領域是CMTimeMakeWithSeconds - 我根據不同的文章/文檔嘗試了幾個不同的變體。例如,在上面的摘錄我使用:

CMTimeMakeWithSeconds(seekTime,600)

我也曾嘗試:

CMTimeMakeWithSeconds(seekTime,1)

我不能告訴哪個是正確的,雖然兩者似乎產生相同的不一致的結果!

我也曾嘗試:

CMTimeMakeWithSeconds(seekTime,23.967)

有些文章聲稱這就像一個分子/ denomenator,因此n/1應該是正確的,其中 'n' 是的秒數(如在CMTimeMakeWithseconds(n,1)中)。但是,代碼最初是由另一位程序員創建的(他現在已經離開了),他使用600號碼作爲preferredTimeScale(即CMTimeMakeWithseconds(n,600))。

任何人都可以提供任何線索,我做錯了什麼,或者即使我試圖達到的那種準確性甚至是可能的?

如果有人想要提供「替代」解決方案,我們已經在考慮將視頻分成不同的流,每章一個,但我們不相信這會給我們提供相同的性能,由於必須創建和加載新的AVPlayerItem等,所以章節將花費更長的時間等等。因此,如果您認爲這是唯一可行的解​​決方案(而且我們希望這將實現我們想要的結果 - 即每一章將開始在我們想要的位置)我們可以自由地這麼說。

在此先感謝!

回答

2

請使用[player seekToTime:CMTimeMakeWithSeconds(seekTime,1)]等功能。
由於您的容差值kCMTimeZero將需要更多時間來尋找。您可以使用kCMTimeIndefinite,而不是使用公差值kCMTimeZero,這與我之前指定的函數等效。

+0

對不起,這是怎麼回答的? – 2013-04-11 08:08:34

+1

錯誤。時間刻度爲1意味着您只能指定整秒尋找。時間刻度是每秒鐘的部分數量。正如Apple推薦的那樣,視頻採用600,因爲它是每秒50,60,25和24幀等常見視頻幀率的產品。 – 2015-10-27 02:41:25

3

我的建議: 1)請勿使用[avplayer seekToTime:toleranceBefore:toleranceAfter:],這會延遲您的尋找時間4-5秒。 2)將HLS視頻剪輯爲每段10秒。你的章節起始位置應該符合10的多值性。由於該段以I幀開始,因此可以快速找到時間和準確的時間。

+7

如果不使用'[avplayer seekToTime:toleranceBefore:toleranceAfter:]'那麼應該使用什麼方法? – Fennelouski 2015-02-04 18:06:20

+1

我不同意這一點。問題是「AVPlayer seekToTime無法播放正確的位置」。通過添加toleranceBefore:toleranceAfter:參數將seekToTime()設置爲kCMTimeZero,您將解決此問題,因此這是問題的正確答案。如果你不使用這個,玩家開始的時候是任意的。 – Bocaxica 2015-11-17 16:17:10

+0

感謝您指出了這一點,我用替代方法解決了滯後問題。 – 2015-12-03 13:01:22

76
int32_t timeScale = self.player.currentItem.asset.duration.timescale; 
CMTime time = CMTimeMakeWithSeconds(77.000000, timeScale); 
[self.player seekToTime:time toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; 

我遇到了'seekToTime'的問題。我用這段代碼解決了我的問題。 '時間尺度'是這個問題的竅門。

+6

@ jordan-bigel這應該被選爲正確的答案。 – 2016-01-14 02:56:21

+0

不錯的解決方案@Muhmd – 2016-04-28 05:09:41

+0

感謝的人,它拯救了我的一天, – 2016-07-27 06:47:39

0

把這段代碼可以解決你的問題。

let targetTime = CMTimeMakeWithSeconds(videoLastDuration, 1) // videoLastDuration hold the previous video state. 
self.playerController.player?.currentItem?.seekToTime(targetTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)