AVFoundation
AVPlayer
video looping
iOS development
Swift programming

Looping a video with AVFoundation AVPlayer?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Looping video with AVPlayer can be done in more than one way, but not all approaches are equally smooth. Restarting playback manually at the end of the item works, yet it can introduce visible gaps. For seamless looping, AVQueuePlayer with AVPlayerLooper is usually the best solution.

Use AVPlayerLooper for Seamless Looping

Apple provides a dedicated looping API for this exact use case.

swift
1import AVFoundation
2
3let url = Bundle.main.url(forResource: "demo", withExtension: "mp4")!
4let item = AVPlayerItem(url: url)
5let queuePlayer = AVQueuePlayer()
6let looper = AVPlayerLooper(player: queuePlayer, templateItem: item)
7
8queuePlayer.play()

This approach is designed for smooth repeated playback and is usually better than manually seeking back to the start.

Display It with AVPlayerLayer

To show the video, attach the player to a layer.

swift
1import UIKit
2import AVFoundation
3
4final class VideoView: UIView {
5    override static var layerClass: AnyClass {
6        AVPlayerLayer.self
7    }
8
9    var playerLayer: AVPlayerLayer {
10        layer as! AVPlayerLayer
11    }
12}
13
14let videoView = VideoView(frame: .zero)
15videoView.playerLayer.player = queuePlayer
16videoView.playerLayer.videoGravity = .resizeAspectFill

Now the looping player is attached to the UI in a standard AVFoundation way.

Manual Looping Is the Older Fallback

If AVPlayerLooper is not an option in your context, you can observe the end-of-playback notification and seek back to time zero.

swift
1import AVFoundation
2
3let player = AVPlayer(url: url)
4
5NotificationCenter.default.addObserver(
6    forName: .AVPlayerItemDidPlayToEndTime,
7    object: player.currentItem,
8    queue: .main
9) { _ in
10    player.seek(to: .zero)
11    player.play()
12}

This works, but it is more likely to produce a small visible or audible gap at the loop point.

Keep Strong References to the Player Objects

If the player or looper is not retained, playback may stop unexpectedly. This is a common issue in view controllers where the player is created locally inside a setup method and then deallocated.

Store both the player and the looper as properties of the owning object.

That detail is easy to miss because the code may compile and even appear to work briefly. The failure usually shows up only after the setup method returns and the temporary objects are released.

Think About App Lifecycle and Audio

Looping media interacts with app lifecycle, mute state, audio session setup, and battery use. A loop that is fine on a splash screen may be inappropriate in a scrolling feed or on a screen that frequently appears and disappears.

That is why the looping code should be paired with a clear start and stop lifecycle, not just a one-time play() call.

If the player sits inside a reusable view or cell, cleanup matters even more. Reused UI containers that keep old players alive are a common source of overlapping playback and hard-to-find media bugs.

That is why looped playback is easiest to maintain when ownership is explicit: one view, one player lifecycle, one cleanup path. The simpler the ownership, the safer the loop.

In practice, most looping bugs are not about the loop API itself. They come from view reuse, deallocation, audio-session surprises, or starting playback before the asset is ready for the intended screen state.

Common Pitfalls

  • Using manual seek-based looping when seamless playback is required.
  • Forgetting to retain AVQueuePlayer or AVPlayerLooper.
  • Attaching looping playback to the UI without considering view lifecycle cleanup.
  • Assuming AVPlayer alone provides the smoothest loop behavior.
  • Ignoring battery and audio implications of always-on looping media.

Summary

  • 'AVPlayerLooper with AVQueuePlayer is the preferred way to loop video smoothly.'
  • 'AVPlayerLayer is the standard rendering surface for displaying the player.'
  • Manual notification-based seeking is a workable fallback but can introduce gaps.
  • Keep strong references to both player and looper objects.
  • Treat looping as a lifecycle-managed media feature, not just a playback flag.

Course illustration
Course illustration

All Rights Reserved.