Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SwiftStreamExtractor

A small, native-Swift library for extracting direct video stream URLs from web pages — no Python, no server. Pure Swift Concurrency, with a pluggable per-site extractor architecture.

It fills a gap in the ecosystem: the only existing native-Swift extractors are YouTube-only. SwiftStreamExtractor is site-agnostic at its core and lets you add site-specific handlers as needed.

import StreamExtractor

let extractor = StreamExtractor()
let streams = try await extractor.streams(for: pageURL)

if let best = streams.first {
    // best.url        -> direct .m3u8 / .mp4 URL
    // best.kind       -> .hls or .progressive
    // best.httpHeaders -> e.g. ["Referer": ...] to hand to your player
    play(best.url, headers: best.httpHeaders)
}

Why

Most "watch this web video elsewhere" features need one thing: the real media URL behind a page. Doing that on Apple platforms usually means either embedding a Python runtime to run yt-dlp (heavy, and awkward on visionOS) or reverse-engineering each site by hand. This library is the lightweight middle ground — Foundation + WebKit, nothing else — and it runs anywhere Swift does, including visionOS.

Install

Swift Package Manager:

.package(url: "https://github.com/tgeselle/SwiftStreamExtractor.git", from: "0.1.0")

Then add "StreamExtractor" to your target's dependencies.

Platforms: iOS 15+, macOS 12+, tvOS 15+, visionOS 1+, watchOS 8+.

How it works

Extraction runs as an ordered chain of SiteExtractors. The first one that handles the URL and yields a result wins. Two strategies ship by default:

  1. GenericExtractor (Foundation only) — fetches the page HTML and looks for media URLs that are server-rendered: og:video meta tags, JSON-LD VideoObject contentUrl/embedUrl, and any .m3u8/.mp4 URL in the markup or inline scripts (including \/-escaped ones). Fast, works everywhere.

  2. WebViewExtractor (WebKit; iOS/macOS/visionOS) — loads the page in an off-screen WKWebView, hooks fetch/XMLHttpRequest and scans the DOM in every frame, and captures media URLs the page requests at playback time. This is what catches custom and MSE/blob: players that never expose a URL in the HTML. Often needs the media to start playing, so allow a couple of seconds.

The default StreamExtractor() tries GenericExtractor first (cheap), then falls back to WebViewExtractor where available.

Adding a site-specific extractor

struct MySiteExtractor: SiteExtractor {
    let name = "mysite"
    func canHandle(_ url: URL) -> Bool { url.host?.contains("mysite.com") == true }

    func extract(_ url: URL, context: ExtractionContext) async throws -> [MediaStream] {
        let (html, finalURL) = try await context.fetchHTML(url)
        // ...parse the site's player config...
        return MediaPatterns.mediaURLs(in: html).map {
            MediaStream(url: $0, kind: MediaPatterns.kind(for: $0),
                        quality: MediaPatterns.quality(for: $0),
                        httpHeaders: ["Referer": finalURL.absoluteString])
        }
    }
}

let extractor = StreamExtractor(extractors: [MySiteExtractor()] + StreamExtractor.defaultExtractors)

MediaPatterns exposes the reusable helpers (mediaURLs(in:), kind(for:), quality(for:), rank(_:), isMedia(_:)).

Limitations

This is a focused library, not a full yt-dlp replacement:

  • DRM (FairPlay/Widevine) is out of scope and impossible to bypass.
  • Players that build the stream entirely in JavaScript and feed MSE without ever fetching a manifest URL expose nothing to capture.
  • Login/cookie-gated streams need you to pass the right cookies via MediaStream.httpHeaders / your player.
  • Sites change. Site-specific extractors are inherently maintenance-prone.

Using the result with AVFoundation

let asset = AVURLAsset(
    url: best.url,
    options: best.httpHeaders.isEmpty ? nil
        : ["AVURLAssetHTTPHeaderFieldsKey": best.httpHeaders]
)
player.replaceCurrentItem(with: AVPlayerItem(asset: asset))

License

MIT © Thomas Geselle

About

Native-Swift library to extract direct video stream URLs (.m3u8/.mp4) from web pages — no Python. Works on visionOS/iOS/macOS.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages