8

实在是想不通了,我又要请教各位了。。。

我正在构建一个使用三个 AVPlayer 实例的 iPhone 应用程序。他们都在同一时间比赛,他们这样做非常重要。我曾经运行此代码:

CMClockRef syncTime = CMClockGetHostTimeClock();
CMTime hostTime = CMClockGetTime(hostTime);
[self.playerOne setRate:1.0f time:kCMTimeInvalid atHostTime:hostTime];
[self.playerTwo setRate:1.0f time:kCMTimeInvalid atHostTime:hostTime];
[self.playerThree setRate:1.0f time:kCMTimeInvalid atHostTime:hostTime];

效果很好。但是几天前它刚刚停止工作,三个播放器延迟了大约 300-400 毫秒(这太多了,100 毫秒以下的一切都可以)。其中两个 AVPlayer 有一些音频处理,这比“正常” AVPlayer 需要一些时间,但它以前可以工作,并且 currentTime 属性告诉我,这些播放器被延迟,所以同步似乎失败了。

我不知道它为什么停止工作,我并没有真正改变什么,但我使用了一个观察者,我可以在其中询问 self.playerX.currentTime 属性,这给了我大约 0.3-.4 秒的延迟。 .. 如果延迟>.1f,我已经尝试重新同步播放器,但延迟仍然存在。所以我认为 player1 和 2 的音频处理不能对延迟负责,因为 currentTime 属性确实知道它们被延迟了(我希望你知道我的意思)。也许你们中的一些人知道我为什么会有如此可怕的延迟,或者能够为我提供另一个想法。

提前致谢!

4

2 回答 2

18

所以,我找到了解决方案。我忘了 [self.playerX prerollAtRate:]。我想如果观察者是 AVPlayerReadyToPlay 这意味着玩家“真的”准备好了。事实上,事实并非如此。AVPlayer readyToPlay 后,必须进行预滚动。完成后,您可以同步您的放置器。延迟现在是 0.000006 秒。

于 2013-10-31T16:28:28.023 回答
0

跨多个 iOS 设备同步 avplayer 的完整功能

private func startTribePlayer() {
    let dateFormatterGet = DateFormatter()
    dateFormatterGet.dateFormat = "yyyy-MM-dd"
    guard let refDate = dateFormatterGet.date(from: "2019-01-01") else { return }
    let tsRef = Date().timeIntervalSince(refDate)
    //currentDuration is avplayeritem.duration().seconds
    let remainder = tsRef.truncatingRemainder(dividingBy: currentDuration)
    let ratio = remainder / currentDuration
    let seekTime = ratio * currentDuration
    let bufferTime = 0.5
    let bufferSeekTime = seekTime + bufferTime
    let mulFactor = 10000.0
    let timeScale = CMTimeScale(mulFactor)
    let seekCMTime = CMTime(value: CMTimeValue(CGFloat(bufferSeekTime * mulFactor)), timescale: timeScale)
    let syncTime = CMClockGetHostTimeClock()
    let hostTime = CMClockGetTime(syncTime)
    tribeMusicPlayer?.seek(to: seekCMTime, toleranceBefore: .zero, toleranceAfter: .zero, completionHandler: { [weak self] (successSeek) in
        guard let tvc = self, tvc.tribeMusicPlayer?.currentItem?.status == .readyToPlay else { return }
        tvc.tribeMusicPlayer?.preroll(atRate: 1.0, completionHandler: { [tvc] (successPreroll) in
            tvc.tribePlayerDidPlay = true
            tvc.tribeMusicPlayer?.setRate(1.0, time: seekCMTime, atHostTime: hostTime)
        })
    })
}
于 2019-06-04T12:26:05.670 回答