iOS 27 introduces Apple Intelligence-powered on-device generated subtitles that automatically transcribe or translate audio/subtitles during playback, plus a new subtitle style preview API that lets users change caption styling live while watching video.
⢠Generated subtitles require zero code changes ā they appear automatically in AVPlayerViewController for HLS, VOD, and file-based content, dramatically widening accessibility reach
⢠The new subtitle style preview API (on AVPlayerLayer) lets users audition caption styles in-context during playback, removing the friction of hunting through Settings
⢠Both features close critical accessibility gaps: users can now get subtitles in languages the content author never provided, and style them without leaving the player
Demonstrates how to fetch all system subtitle style profile IDs, show a live in-player style preview using AVPlayerLayer, and commit the chosen style ā the core of the new subtitle style preview API.
import SwiftUI
import AVFoundation
import AVKit
struct SubtitleStylePreviewDemo: View {
private let player: AVPlayer
private let playerLayer: AVPlayerLayer
@State private var styleProfiles: [AVCaptionStyleProfile] = []
@State private var selectedProfile: AVCaptionStyleProfile?
@State private var isPreviewing = false
init() {
let url = URL(string: "https://devstreaming-cdn.apple.com/videos/wwdc/2023/101/4/5BFC93F8-C8D2-4A74-B7C5-8C1E8CF77345/cmaf/hvc/2160p_16800/prog_index.m3u8")!
let item = AVPlayerItem(url: url)
let p = AVPlayer(playerItem: item)
player = p
playerLayer = AVPlayerLayer(player: p)
}
var body: some View {
VStack(spacing: 16) {
PlayerLayerView(playerLayer: playerLayer)
.frame(height: 220)
.cornerRadius(12)
.onAppear {
loadStyleProfiles()
player.play()
}
.onDisappear {
player.pause()
if isPreviewing {
stopPreview()
}
}
Text("Subtitle Styles").font(.headline)
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 12) {
ForEach(styleProfiles, id: \.profileID) { profile in
Button(action: {
previewStyle(profile)
}) {
Text(profile.localizedName)
.padding(.horizontal, 14)
.padding(.vertical, 8)
.background(
selectedProfile?.profileID == profile.profileID
? Color.accentColor : Color(.systemGray5)
)
.foregroundColor(
selectedProfile?.profileID == profile.profileID
? .white : .primary
)
.cornerRadius(8)
}
}
}
.padding(.horizontal)
}
HStack(spacing: 16) {
Button("Stop Preview") {
stopPreview()
}
.disabled(!isPreviewing)
Button("Apply Style") {
applySelectedStyle()
}
.disabled(selectedProfile == nil)
.buttonStyle(.borderedProminent)
}
}
.padding()
}
private func loadStyleProfiles() {
styleProfiles = AVCaptionStyleProfile.availableProfiles()
}
private func previewStyle(_ profile: AVCaptionStyleProfile) {
selectedProfile = profile
isPreviewing = true
// Pass nil for text to show localized system placeholder text.
// Use position offset to avoid overlapping custom controls at the bottom.
playerLayer.showSubtitleStylePreview(
forProfileID: profile.profileID,
text: nil,
position: CGPoint(x: 0, y: -40)
)
}
private func stopPreview() {
isPreviewing = false
playerLayer.stopSubtitleStylePreview()
}
private func applySelectedStyle() {
guard let profile = selectedProfile else { return }
stopPreview()
AVCaptionStyleProfile.setCurrentProfile(profile)
}
}
// UIViewRepresentable wrapper to host AVPlayerLayer
struct PlayerLayerView: UIViewRepresentable {
let playerLayer: AVPlayerLayer
func makeUIView(context: Context) -> UIView {
let view = UIView()
view.backgroundColor = .black
playerLayer.videoGravity = .resizeAspect
view.layer.addSublayer(playerLayer)
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
playerLayer.frame = uiView.bounds
}
}
Generated subtitles are marked with a sparkle symbol in selection UI ā make sure your custom subtitle selection UI surfaces this distinction. When showing the style preview via AVPlayerLayer, existing subtitles are automatically hidden; call stopSubtitleStylePreview() or equivalent to restore them. Passing nil for the preview text parameter shows localized system placeholder text. Use the position offset parameter to avoid overlapping your own playback controls.
On-device Speech-To-Text and translation models require Apple Intelligence-capable devices; English speech transcription supported on iOS/macOS/tvOS/visionOS 27; multi-language translation from English subtitles on iOS/macOS 27 only
More iOS 27 APIs land every week.
Get notified when new capabilities are published ā no noise, just signal.