Integrating AVPlayer for Video Playback in iOS Application
AVPlayer is a native iOS player with support for HLS, MPEG-4, progressive download, AirPlay, Picture in Picture and subtitles. Before using third-party players (VLCKit, IJKPlayer), it's worth understanding what AVPlayer can do — in most cases it's sufficient.
Basic Integration
AVPlayer doesn't display video by itself — it manages playback. For display you need AVPlayerLayer, embedded in UIView.layer, or AVPlayerViewController from AVKit — a ready-made controller with system controls.
let player = AVPlayer(url: videoURL)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = containerView.bounds
playerLayer.videoGravity = .resizeAspect
containerView.layer.addSublayer(playerLayer)
player.play()
For SwiftUI — VideoPlayer from AVKit, a wrapper over AVPlayerViewController.
Where Problems Appear
Buffering and state. player.currentItem?.status doesn't reflect real-time readiness for playback. The correct approach — KVO on player.currentItem and timeControlStatus:
player.publisher(for: \.timeControlStatus)
.receive(on: DispatchQueue.main)
.sink { status in
switch status {
case .playing: hideLoader()
case .waitingToPlayAtSpecifiedRate: showLoader()
case .paused: break
}
}
HLS and quality. For HLS (m3u8) AVPlayer automatically selects stream by bandwidth. You can manage selection via AVPlayerItem.preferredPeakBitRate (limitation) or AVPlayerItem.preferredMaximumResolution. Manual quality selection — through AVMediaSelectionGroup with AVAssetVariant.
Background playback. Audio stream when app goes to background requires: enabled capability "Background Modes → Audio, AirPlay" in Xcode and AVAudioSession.shared.setCategory(.playback) before player.play(). Without setCategory audio is cut off immediately when app goes to background.
Picture in Picture. AVPictureInPictureController requires AVPlayerLayer or AVPlayerViewController. Add AVPictureInPictureControllerDelegate, in Info.plist — UIBackgroundModes: audio. Enable pictureInPictureController.startPictureInPicture() on button click. PiP works only on physical devices, not in simulator.
Custom Controls
If AVPlayerViewController doesn't suit the design, build a custom player on top of AVPlayer + AVPlayerLayer:
- Progress bar:
player.addPeriodicTimeObserver(forInterval: CMTime(seconds: 0.5), queue: .main)to update position - Seeking:
player.seek(to: CMTime(seconds: targetSeconds, preferredTimescale: 600), toleranceBefore: .zero, toleranceAfter: .zero)—toleranceBefore/After: .zerogives exact position but is slower - Subtitles:
AVMediaCharacteristic.legible+AVPlayerItem.select(_:in:)for switching tracks
What's Included in the Work
- Integrating
AVPlayerwithAVPlayerLayerorAVPlayerViewController - Custom UI controls (play/pause, seek bar, fullscreen)
- Background playback and AirPlay
- Picture in Picture (if iOS 14+ required)
- HLS with quality selection capability
- Network and buffering error handling with retry logic
Timeline
Basic player with system controls: half a day. Fully custom player with subtitles, PiP and HLS quality selector: 2–3 days. Cost is calculated individually.







