| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
A Swift wrapper around libVLC for iOS, macOS, tvOS, visionOS, and Mac Catalyst.
AVFoundation is excellent for Apple's native media stack, but its container, codec, subtitle, and network-protocol support is limited to what Apple ships. Apps that need MKV, SSA/ASS subtitles, SMB, UPnP, or other VLC-backed formats and protocols need a broader engine.
VLC's engine, libVLC, supports a broad set of codecs, containers, subtitles, and network protocols through embeddable C APIs.
VideoLAN's Apple wrapper, VLCKit, is written primarily in Objective-C. It uses delegates, KVO, NSNotificationCenter, and manual thread management, which is a faithful reflection of the era it was designed in.
SwiftVLC wraps libVLC 4.0 directly in Swift, with no Objective-C layer in between. It is built for @Observable, async/await, and VideoView(player).
| SwiftVLC | VLCKit | |
|---|---|---|
| Language | Swift 6 | Objective-C |
| Bindings | Direct C → Swift | C → Objective-C → Swift bridging |
| State management | @Observable, drives SwiftUI directly | KVO, NSNotificationCenter, and delegates |
| Concurrency | @MainActor, Sendable, async/await | Manual thread dispatch, no isolation |
| Video rendering | VideoView(player) | App-supplied view setup plus drawable configuration |
| Errors | Library failures use throws(VLCError), typed and exhaustive | NSError codes |
| Events | AsyncStream<PlayerEvent> with multiple consumers | NSNotificationCenter |
| libVLC generation | 4.0 | 3.x stable line; 4.0 alpha packages exist |
| SwiftUI PiP | iOS via libVLC's native AVKit-backed drawable path; macOS private backend is SPI opt-in | App-supplied integration |
| Swift 6 safe | Yes, with strict concurrency | No |
In Xcode, choose File → Add Package Dependencies, paste the repo URL, and Xcode will pick up the latest release automatically:
https://github.com/harflabs/SwiftVLC.git
From a Package.swift manifest, add a dependency and pin to the current release. The version string lives on the releases page.
.package(url: "https://github.com/harflabs/SwiftVLC.git", from: "1.0.0")The pre-built libVLC xcframework downloads automatically via SPM. It's a large binary (multi-GB unstripped; the release zip is a few hundred MB).
import SwiftUI
import SwiftVLC
struct PlayerView: View {
@State private var player = Player()
var body: some View {
VideoView(player)
.onAppear {
try? player.play(url: URL(string: "https://example.com/video.mp4")!)
}
}
}Player.play(url:) expects a direct media stream or file URL. It does not auto-resolve .pls or classic .m3u playlist containers; use MediaListPlayer or fetch and parse the playlist to its inner stream URL before passing it to Player. HLS .m3u8 URLs are supported here because they are streaming manifests rather than playlists of separate media URLs.
// Playback
let player = Player()
try player.play(url: videoURL)
player.pause()
player.stop()
try player.seek(to: PlaybackPosition(0.5)) // Seek to 50%
try player.setPlaybackRate(1.5) // 1.5x speed
try player.setAudioVolume(0.8) // 80% volume
player.isMuted = true
// Tracks
player.selectedSubtitleTrack = player.subtitleTracks[1]
// Metadata
let media = try Media(url: videoURL)
let metadata = try await media.parse()
print(metadata.title, metadata.duration)
// Events
for await event in player.events {
switch event {
case .stateChanged(let state): ...
case .timeChanged(let time): ...
default: break
}
}The API reference for the latest published release is hosted on Swift Package Index. The unversioned link follows the most recent tag that the service has finished building: swiftpackageindex.com/harflabs/swiftvlc/documentation
The Showcase/ directory contains separate folders, targets, and schemes for each showcase lane:
Every showcase target accepts an app-wide test stream URL. The override is kept in memory for the current app session, redacted to its scheme, host, and a hidden path in the UI, and used by showcases that otherwise load bundled or public sample media. HTTP, HTTPS, UDP, and other URL schemes supported by the bundled libVLC are accepted, including HLS through its .m3u8 HTTP(S) URL.
The development showcase targets allow arbitrary network loads so user-entered HTTP hosts work with libVLC. This broad App Transport Security exception is for the Showcase apps only. Applications embedding SwiftVLC should define the narrowest transport policy appropriate for their own media sources.
Showcase UI tests live under Showcase/UITests/. iOSUITests covers the broad showcase flows, macOSUITests covers native macOS PiP, and tvOSUITests is a placeholder target. The visionOS showcase does not have a UI-test target.
The core package uses a comprehensive Swift Testing suite against the real libVLC binary, so regressions in the C bridge surface immediately rather than hiding behind a fake. Showcase UI tests use XCTest separately. CI runs package tests, lint, doc coverage, and Showcase builds on pull requests and on main.
swift testSee ARCHITECTURE.md for test tags, fixtures, and structure.
git clone https://github.com/harflabs/SwiftVLC.git
cd SwiftVLC
./scripts/setup-dev.sh
swift testmain records an exact libVLC release URL and checksum. setup-dev.sh verifies that tag against the GitHub asset digest, downloads that exact artifact into Vendor/, and flips Package.swift plus the Showcase package reference to repo-local sources. It never follows GitHub's mutable “latest” pointer.
| setup-dev.sh flag | Effect |
|---|---|
| (none) | Install the exact release declared by Package.swift; replace an unverified or stale Vendor/ copy. |
| vX.Y.Z (positional) | Pin to a specific release tag. |
| --force | Re-download even if Vendor/ already exists. |
| --skip-download | Only flip local references (Package.swift and the Showcase app). Expects Vendor/ to already exist, which is useful after running build-libvlc.sh. |
Needed only when bumping VLC_HASH, modifying build patches, or preparing a release. Day-to-day Swift development doesn't require it.
brew install autoconf automake libtool cmake pkg-config gettext
./scripts/build-libvlc.sh --allExpect a full --all build to take tens of minutes on Apple Silicon. The script clones VLC at a pinned commit into scripts/.build-libvlc/, applies the source patches below, builds every contrib (FFmpeg, dav1d, x264, libass, …) per slice, and assembles the result into Vendor/libvlc.xcframework.
| Flag | Platforms |
|---|---|
| (default) | iOS device + simulator |
| --all | iOS, tvOS, visionOS, macOS, Mac Catalyst (eight slices) |
| --ios-only / --tvos-only / --visionos-only / --macos-only / --catalyst-only | Replaces Vendor/ with that single platform |
| --tvos / --visionos / --macos / --catalyst | Adds a platform to the default set |
| --clean / --clean-build | Wipe scripts/.build-libvlc/ (the latter rebuilds afterwards) |
| --hash=<sha> | Override the pinned VLC commit |
*-only flags replace the xcframework; any slices already in Vendor/ are lost.
VLC master requires several build adjustments for SwiftVLC's supported Apple toolchains. The script applies them in-tree on every invocation, idempotently:
The script also applies these checked-in VLC source patches in order:
git reset --hard only runs when HEAD is not at VLC_HASH, so the patches and per-platform build dirs survive repeated runs.
Releases advance main, but stable releases can only consume an immutable, previously prepared and device-qualified candidate. setup-dev.sh flips a working checkout back to local sources for day-to-day development.
Before publishing a stable release, run the connected-device validator against the exact source and libVLC artifact that will ship:
./Validate\ SwiftVLC.command --yesRun it from the candidate tag or checkout whose Package.swift pins the candidate artifact. The command verifies and downloads that immutable artifact, then builds, signs, installs, and exercises every matrix scenario that applies to the connected iPhone or iPad, then creates one shareable SwiftVLC-Device-Report-*.zip. No manual in-app checklist is required. A full current-iPhone run is intentionally comprehensive and can take 8–10 hours; keep the Mac and device powered, unlocked, and connected. Runs on simulators or beta and unknown OS builds remain exploratory and cannot satisfy the stable gate.
One device normally covers only one hardware/OS row. Repeat the same command on each device required by scripts/qualification/matrix.json, retain the raw report.json from each run, assemble those reports, and run the fail-closed qualification check before publishing stable. See scripts/qualification/README.md for the exact candidate-binding, report assembly, and release commands.
./scripts/build-libvlc.sh --all # produces Vendor/libvlc.xcframework
./scripts/release.sh X.Y.Z --dry-run # strip + zip + checksum, no push
./scripts/release.sh X.Y.Z --prepare /absolute/path/to/candidate
./Validate\ SwiftVLC.command --yes # from the candidate tag; repeat per device row
python3 scripts/qualification/assemble-record.py --help
./scripts/check-qualification.sh X.Y.Z /absolute/path/to/candidate/libvlc.xcframework
./scripts/release.sh X.Y.Z --candidate /absolute/path/to/candidateWhat release.sh does:
Candidate preparation and publishing refuse non-main branches, any dirty working tree, a local main that differs from origin/main, pre-existing tags, and unauthenticated gh. If publication fails after asset upload, the release remains a non-public draft until it is fixed or removed.
After publication, verify that Swift Package Index has finished building the tagged API reference and that the unversioned documentation link above resolves to 1.0.0. Its documentation build is asynchronous and may temporarily serve the previous release while the new tag is queued.
For internals, including module design, C interop, the concurrency model, the event system, memory management, and the PiP rendering pipeline, see ARCHITECTURE.md.
MIT. See LICENSE.
libVLC is licensed under LGPLv2.1. Static linking may have licensing implications. See the VLC licensing FAQ.
SwiftVLC stands on the work of the VideoLAN community. VLC and libVLC represent decades of media playback work by hundreds of contributors.
Thanks also to VLCKit for establishing libVLC on Apple platforms.
| Back | FazBrowse Home | New Git URL |