There has been some discussion before about how to loop an AVPlayer
's video item, but no 'solution' is seamless enough to provide lag-less looping of a video.
I am developing a tvOS app that has a high-quality 10 second clip of 'scenery' in the background of one of its views, and simply restarting its AVPlayer the 'standard' way (subscribing to NSNotification
to catch it) is too jumpy not to notice and detract from user experience.
It seems as though the only way to achieve a truly seamless loop is to manually manage frames, at a lower-level (in OpenGL)...
Despite best efforts to read up on this, and as a novice in manipulating video pipelines, I have not come close enough to a comprehensible solution.
I am aware that external libraries exist to be able to perform this behaviour more easily; most notably GPUImage. However, the app I am developing is for tvOS and therefore has difficulty using quite a lot of the 3rd party iOS libraries in existence, GPUImage included. Another library I have come across is AVAnimator, which provides great functionality for light-weight animation videos, but not for dense, high-quality video clips of source footage encoded in .H264.
The closest I have come so far is Apple's own AVCustomEdit source code, however this primarily deals with static production of a 'transition' that, while seamless, is too complex for me to be able to discern how to make it perform simple looping functionality.
If anybody can chip in with experience of manipulating AVPlayer
at a lower level, i.e. with image processing/buffers (or iOS development that doesn't rest on external libraries), I would be incredibly interested to know how I could make a start.
I had the same problem when streaming a video. After playing for the first time, there was a black screen when loading the video for second time. I got rid of the black screen by seeking video to 5ms ahead. It made nearly a seamless video loop. (Swift 2.1)
// Create player here..
let player = AVPlayer(URL: videoURL)
// Add notification block
NSNotificationCenter.defaultCenter().addObserverForName(AVPlayerItemDidPlayToEndTimeNotification, object: player.currentItem, queue: nil)
{ notification in
let t1 = CMTimeMake(5, 100);
player.seekToTime(t1)
player.play()
}