VersaPlayer

josejuanqmMIT活跃维护

面向 iOS、macOS 和 tvOS 的可扩展视频播放器,基于 AVPlayer 封装,支持广告插入、AirPlay 和画中画等常见播放需求。

Versatile Video Player implementation for iOS, macOS, and tvOS

4.0.0发布于 2026-10-29 05:42 UTC819star121fork同步于 2026-11-10 23:53 UTC

怎么上手

由 README 提炼,执行前请确认
Swift Package Manager 添加:.package(url: "https://github.com/josejuanqm/VersaPlayer.git", from: "4.0.0")
硬件要求按 README 说明

README 未说明;仅要求 iOS 17、tvOS 17、macOS 14、visionOS 1 及 Swift 6 系统环境

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

基于 AVFoundation 的 SwiftUI 视频播放器,跨 iOS、tvOS、macOS、visionOS,自带控件与自定义积木

面向 iOS、macOS 和 tvOS 的可扩展视频播放器,基于 AVPlayer 封装,支持广告插入、AirPlay 和画中画等常见播放需求。

核心能力

  • 用 @Observable 的 VersaPlayerModel 驱动视图自动更新
  • 提供 PlayPauseButton、Scrubber 等控件积木,可自由拼装
  • 支持 HLS 自适应码率与 setQuality 峰值码率限制
  • 内置 FairPlay DRM 与 ContentKeyProvider 自定义协议
  • 支持画中画、AirPlay 及 tvOS 遥控器焦点导航

容易踩的坑

4.0 是 SwiftUI 重写版,从 3.x 升级需先看 MIGRATION.md;iOS 画中画需开启 Audio 后台模式并把音频会话类别设为 .playback;FairPlay 仅用假实现做过单元测试,需对接自己的 license 服务器验证

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

2 个版本4.0.0
  1. 4.0.0VersaPlayer 4.0.0最新正式版2026-10-29 · 2026-10-29 05:42 UTC

    4.0 rewrites VersaPlayer for SwiftUI. It's a breaking release: 3.x stays available at tag 3.0.2. See MIGRATION.md to upgrade.

    .package(url: "https://github.com/josejuanqm/VersaPlayer.git", from: "4.0.0")
    

    What's new

    • Requirements: iOS/tvOS 17, macOS 14, visionOS 1. Swift 6 with strict concurrency. Swift Package Manager only; CocoaPods is no longer supported.
    • VersaPlayerCore: an @Observable VersaPlayerModel wrapping AVPlayer. It covers playback state, an AsyncStream of events, error mapping, audio/subtitle tracks, caption styling, quality caps, FairPlay through AVContentKeySession, Picture in Picture, plugins, and a built-in NowPlayingPlugin for the lock screen and remote commands.
    • VersaPlayer (SwiftUI): VersaVideoPlayer with default controls that hide on their own, plus building blocks for custom controls (PlayPauseButton, Scrubber, TrackPicker, PiPButton, AirPlayButton, …). VersaPlayerViewController wraps it for UIKit and AppKit apps.
    • tvOS: Siri Remote support: the seek bar scrubs, and the track and Picture in Picture menus can take focus.
    • Demo: one XcodeGen app for all four platforms (Examples/VersaPlayerDemo).
  2. 3.0.0Version 3.0.02019-07-04 · 2019-07-04 07:29 UTC
    查看更新说明

    Carthage support.

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    CI Platforms Swift License

    News

    :tada: VersaPlayer 4.0 is a SwiftUI rewrite. Coming from 3.x? See MIGRATION.md.

    VersaPlayer is a SwiftUI video player built on AVFoundation: an observable player model, a ready-made controls overlay, and building blocks for your own controls. Supports HLS, tracks, caption styling, FairPlay, Picture in Picture and AirPlay on iOS, tvOS, macOS and visionOS.

    Installation

    Swift Package Manager:

    .package(url: "https://github.com/josejuanqm/VersaPlayer.git", from: "4.0.0")
    

    Or in Xcode: File › Add Package Dependencies… and paste the repository URL.

    Usage

    Basic

    import SwiftUI
    import VersaPlayer
    
    struct PlayerScreen: View {
        @State private var model = VersaPlayerModel()
    
        var body: some View {
            VersaVideoPlayer(model: model)
                .aspectRatio(16 / 9, contentMode: .fit)
                .task { model.load(VersaPlayerItem(url: url)) }
        }
    }
    

    load autoplays by default. Pass autoplay: false to start paused.

    State and events

    VersaPlayerModel is @Observable, so views update on their own:

    model.isPlaying, model.isBuffering, model.currentTime, model.duration, model.isLive, model.status
    

    For one-off events (ready, ended, failed, ...):

    .task {
        for await event in model.events {
            if case .failed(let error) = event { print(error) }
        }
    }
    

    To block playback (for example, to show an ad first):

    model.shouldBeginPlayback = { _ in
        await ads.playPreRoll()
        return true
    }
    

    Custom controls

    Pass any view as controls. Use the building blocks, which read the player from the environment:

    VersaVideoPlayer(model: model) {
        VStack {
            Spacer()
            HStack {
                PlayPauseButton()
                Scrubber()
                TimeLabel(.remaining)
                TrackPicker(.legible)
            }
            .padding()
        }
    }
    

    Building blocks: PlayPauseButton, SkipButton(seconds:), RateButton(rate:), Scrubber, TimeLabel, BufferingIndicator, TrackPicker, PiPButton, AirPlayButton, FullscreenButton. For video without any overlay, use VideoSurface(model:).

    Options

    VersaVideoPlayer(model: model)
        .videoGravity(.resizeAspectFill)
        .controlsAutohide(after: .seconds(5))   // nil keeps controls visible
        .doubleTapTogglesGravity(false)
    

    Fullscreen

    The player asks your app to toggle fullscreen; your app presents it. The fullscreen button appears once you register the request:

    @State private var isFullscreen = false
    
    VersaVideoPlayer(model: model)
        .onFullscreenRequest(isFullscreen: false) { isFullscreen = true }
        .fullScreenCover(isPresented: $isFullscreen) {
            VersaVideoPlayer(model: model)
                .onFullscreenRequest(isFullscreen: true) { isFullscreen = false }
                .ignoresSafeArea()
        }
    

    Tracks

    model.tracks(of: .audio)        // [MediaTrack]
    model.tracks(of: .legible)      // subtitles and captions
    model.select(track)
    model.deselect(.legible)        // subtitles off
    model.selectedTracks[.audio]
    

    For adaptive (HLS) quality caps:

    model.setQuality(QualityPreference(peakBitRate: 2_000_000))
    

    Caption styling

    var style = CaptionStyle()
    style.foregroundColor = .init(red: 1, green: 0.85, blue: 0)
    style.relativeFontSize = 150
    style.edgeStyle = .dropShadow
    model.setCaptionStyle(style)
    

    FairPlay

    let provider = FairPlayHTTPProvider(
        certificateURL: URL(string: "https://example.com/fps/cert")!,
        licenseURL: URL(string: "https://example.com/fps/license")!
    )
    model.load(VersaPlayerItem(url: url, drm: DRMConfiguration(provider: provider)))
    

    For a custom license protocol, implement ContentKeyProvider. The FairPlay flow is unit tested with fakes only; test it against your own license server.

    tvOS

    The default controls work with the Siri Remote. While the controls are hidden, select shows them, left/right skips 10 seconds, and play/pause toggles playback. While they're visible, the seek bar has focus: left/right scrubs (faster with quick repeated presses), and select jumps there. Swipe up for audio, subtitles and Picture in Picture. Menu hides the controls.

    Custom controls with focusable buttons should add .controlsTakeFocus(), so focus moves into them while they're visible.

    Picture in Picture and AirPlay

    PiPButton and AirPlayButton are in the default controls. For Picture in Picture on iOS, enable the Audio background mode and set the audio session category to .playback.

    Plugins

    final class Analytics: VersaPlayerPlugin {
        func attach(to model: VersaPlayerModel) {
            Task { for await event in model.events { track(event) } }
        }
    }
    model.add(Analytics())
    

    Built in: NowPlayingPlugin shows the title, artwork and progress on the lock screen and in Control Center, and handles remote play/pause/skip/seek. It uses VersaPlayerItem.metadata:

    model.add(NowPlayingPlugin())
    model.load(VersaPlayerItem(url: url, metadata: .init(title: "Episode 1", subtitle: "My Show", artworkURL: artwork)))
    

    UIKit / AppKit

    let controller = VersaPlayerViewController()
    controller.model.load(VersaPlayerItem(url: url))
    

    Example

    brew install xcodegen
    cd Examples/VersaPlayerDemo && xcodegen generate && open VersaPlayerDemo.xcodeproj
    

    One app target for iOS, tvOS, macOS and visionOS.

    Author

    Jose Quintero - [email protected]

    Star History

    Star History Chart

    Contributors

    People that make VersaPlayer possible, Thank you!

    Donation

    If you like this project or has been helpful to you, you can buy me a cup of coffe :) Appreciate it!

    paypal

    License

    VersaPlayer is available under the MIT license. See the LICENSE file for more info.