Content-Length: 20084 | pFad | http://github.com/muxinc/mux-player-swift/commit/87865e66bd2192937f23fd36d8c419b97c5fc230.diff

4A diff --git a/Examples/MuxAVPlayerSDKExample/MuxAVPlayerSDKExample/MainViewController.swift b/Examples/MuxAVPlayerSDKExample/MuxAVPlayerSDKExample/MainViewController.swift index e20d0a87..929e5f06 100644 --- a/Examples/MuxAVPlayerSDKExample/MuxAVPlayerSDKExample/MainViewController.swift +++ b/Examples/MuxAVPlayerSDKExample/MuxAVPlayerSDKExample/MainViewController.swift @@ -27,7 +27,7 @@ struct MainView: UIViewControllerRepresentable { class MainViewController: UIViewController { lazy var playerViewController = AVPlayerViewController( - publicPlaybackID: playbackID + playbackID: playbackID ) var playbackID: String = "qxb01i6T202018GFS02vp9RIe01icTcDCjVzQpmaB00CUisJ4" @@ -75,9 +75,10 @@ class MainViewController: UIViewController { playerViewController.player?.play() } - override func viewDidDisappear(_ animated: Bool) { + override func viewWillDisappear(_ animated: Bool) { + playerViewController.player?.pause() playerViewController.stopMonitoring() - super.viewDidDisappear(animated) + super.viewWillDisappear(animated) } } diff --git a/LICENSE b/LICENSE index 261eeb9e..0e9d5cf4 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2023 Mux, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Package.swift b/Package.swift index 527c0929..f0e550af 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.8 +// swift-tools-version: 5.9 import PackageDescription diff --git a/Package@swift-5.8.swift b/Package@swift-5.8.swift new file mode 100644 index 00000000..dcf9063c --- /dev/null +++ b/Package@swift-5.8.swift @@ -0,0 +1,44 @@ +// swift-tools-version: 5.8 + +import PackageDescription + +let package = Package( + name: "MuxAVPlayerSDK", + platforms: [ + .iOS(.v15) + ], + products: [ + .library( + name: "MuxAVPlayerSDK", + targets: ["MuxAVPlayerSDK"] + ), + ], + dependencies: [ + .package( + url: "https://github.com/muxinc/mux-stats-sdk-avplayer", + exact: "3.3.1" + ), + .package( + url: "https://github.com/apple/swift-docc-plugin", + from: "1.2.0" + ), + ], + targets: [ + .target( + name: "MuxAVPlayerSDK", + dependencies: [ + .product( + name: "MUXSDKStats", + package: "mux-stats-sdk-avplayer" + ) + ] + ), + .testTarget( + name: "MuxAVPlayerSDKTests", + dependencies: [ + "MuxAVPlayerSDK" + ] + ), + ] +) + diff --git a/Sources/MuxAVPlayerSDK/PublicAPI/Extensions/AVPlayerItem+Mux.swift b/Sources/MuxAVPlayerSDK/PublicAPI/Extensions/AVPlayerItem+Mux.swift index 8bf73b0d..c50c68bf 100644 --- a/Sources/MuxAVPlayerSDK/PublicAPI/Extensions/AVPlayerItem+Mux.swift +++ b/Sources/MuxAVPlayerSDK/PublicAPI/Extensions/AVPlayerItem+Mux.swift @@ -5,7 +5,67 @@ import AVFoundation import Foundation -extension AVPlayerItem { +fileprivate func makePlaybackURL( + playbackID: String, + playbackOptions: PlaybackOptions +) -> URL { + + var components = URLComponents() + components.scheme = "https" + + if let customDomain = playbackOptions.customDomain { + components.host = "stream.\(customDomain)" + } else { + components.host = "stream.mux.com" + } + + components.path = "/\(playbackID).m3u8" + + if case PlaybackOptions.PlaybackPolicy.public(let publicPlaybackOptions) = playbackOptions.playbackPolicy { + var queryItems: [URLQueryItem] = [] + + if publicPlaybackOptions.useRedundantStreams { + queryItems.append( + URLQueryItem( + name: "redundant_streams", + value: "true" + ) + ) + } + + if publicPlaybackOptions.maximumResolutionTier != .default { + queryItems.append( + URLQueryItem( + name: "max_resolution", + value: publicPlaybackOptions.maximumResolutionTier.queryValue + ) + ) + } + + components.queryItems = queryItems + } else if case PlaybackOptions.PlaybackPolicy.signed(let signedPlaybackOptions) = playbackOptions.playbackPolicy { + + var queryItems: [URLQueryItem] = [] + + queryItems.append( + URLQueryItem( + name: "token", + value: signedPlaybackOptions.playbackToken + ) + ) + + components.queryItems = queryItems + + } + + guard let playbackURL = components.url else { + preconditionFailure("Invalid playback URL components") + } + + return playbackURL +} + +internal extension AVPlayerItem { //github.com/ Initializes a player item with a playback URL that //github.com/ references your Mux Video at the supplied playback ID. @@ -17,20 +77,11 @@ extension AVPlayerItem { //github.com/ //github.com/ - Parameter playbackID: playback ID of the Mux Asset //github.com/ you'd like to play - convenience init(publicPlaybackID: String) { - guard let baseURL = URL(string: "https://stream.mux.com") else { - preconditionFailure("Invalid base URL string") - } - - var components = URLComponents( - url: baseURL, - resolvingAgainstBaseURL: false + convenience init(playbackID: String) { + let playbackURL = makePlaybackURL( + playbackID: playbackID, + playbackOptions: PlaybackOptions() ) - components?.path = "/\(publicPlaybackID).m3u8" - - guard let playbackURL = components?.url else { - preconditionFailure("Invalid playback URL components") - } self.init(url: playbackURL) } @@ -40,20 +91,16 @@ extension AVPlayerItem { //github.com/ The playback ID must be public. //github.com/ //github.com/ - Parameters: - //github.com/ - publicPlaybackID: playback ID of the Mux Asset + //github.com/ - playbackID: playback ID of the Mux Asset //github.com/ you'd like to play - //github.com/ - customDomain: custom playback domain, custom domains - //github.com/ need to be configured as described [here](https://docs.mux.com/guides/video/use-a-custom-domain-for-streaming#use-your-own-domain-for-delivering-videos-and-images) first - convenience init(publicPlaybackID: String, customDomain: URL) { - var components = URLComponents( - url: customDomain, - resolvingAgainstBaseURL: false + convenience init( + playbackID: String, + playbackOptions: PlaybackOptions + ) { + let playbackURL = makePlaybackURL( + playbackID: playbackID, + playbackOptions: playbackOptions ) - components?.path = "/\(publicPlaybackID).m3u8" - - guard let playbackURL = components?.url else { - preconditionFailure("Invalid playback URL components") - } self.init(url: playbackURL) } diff --git a/Sources/MuxAVPlayerSDK/PublicAPI/Extensions/AVPlayerViewController+Mux.swift b/Sources/MuxAVPlayerSDK/PublicAPI/Extensions/AVPlayerViewController+Mux.swift index 5b760b42..90093279 100644 --- a/Sources/MuxAVPlayerSDK/PublicAPI/Extensions/AVPlayerViewController+Mux.swift +++ b/Sources/MuxAVPlayerSDK/PublicAPI/Extensions/AVPlayerViewController+Mux.swift @@ -10,18 +10,20 @@ extension AVPlayerViewController { //github.com/ Initializes an AVPlayerViewController that's configured //github.com/ to play your Mux Asset as well as monitor and report //github.com/ back it's playback performance. - //github.com/ - Parameter publicPlaybackID: playback ID of the Mux + //github.com/ - Parameter playbackID: playback ID of the Mux //github.com/ Asset you'd like to play - public convenience init(publicPlaybackID: String) { + public convenience init(playbackID: String) { self.init() - let playerItem = AVPlayerItem(publicPlaybackID: publicPlaybackID) + let playerItem = AVPlayerItem(playbackID: playbackID) let player = AVPlayer(playerItem: playerItem) self.player = player - let monitoringOptions = MonitoringOptions(playbackID: publicPlaybackID) + let monitoringOptions = MonitoringOptions( + playbackID: playbackID + ) Monitor.shared.setupMonitoring( playerViewController: self, @@ -33,7 +35,7 @@ extension AVPlayerViewController { //github.com/ to play your Mux Asset as well as monitor and report //github.com/ back it's playback performance. //github.com/ - Parameters: - //github.com/ - publicPlaybackID: playback ID of the Mux Asset + //github.com/ - playbackID: playback ID of the Mux Asset //github.com/ you'd like to play //github.com/ - monitoringOptions: Options to customize monitoring //github.com/ data reported by Mux @@ -43,7 +45,7 @@ extension AVPlayerViewController { ) { self.init() - let playerItem = AVPlayerItem(publicPlaybackID: publicPlaybackID) + let playerItem = AVPlayerItem(playbackID: publicPlaybackID) let player = AVPlayer(playerItem: playerItem) @@ -59,23 +61,27 @@ extension AVPlayerViewController { //github.com/ to play your Mux Asset as well as monitor and report //github.com/ back it's playback performance. //github.com/ - Parameters: - //github.com/ - publicPlaybackID: playback ID of the Mux Asset + //github.com/ - playbackID: playback ID of the Mux Asset //github.com/ you'd like to play - //github.com/ - customDomain: custom playback domain, custom domains - //github.com/ need to be configured as described [here](https://docs.mux.com/guides/video/use-a-custom-domain-for-streaming#use-your-own-domain-for-delivering-videos-and-images) first - convenience init(publicPlaybackID: String, customDomain: URL) { + //github.com/ - play + convenience init( + playbackID: String, + playbackOptions: PlaybackOptions + ) { self.init() let playerItem = AVPlayerItem( - publicPlaybackID: publicPlaybackID, - customDomain: customDomain + playbackID: playbackID, + playbackOptions: playbackOptions ) let player = AVPlayer(playerItem: playerItem) self.player = player - let monitoringOptions = MonitoringOptions(playbackID: publicPlaybackID) + let monitoringOptions = MonitoringOptions( + playbackID: playbackID + ) Monitor.shared.setupMonitoring( playerViewController: self, @@ -87,22 +93,22 @@ extension AVPlayerViewController { //github.com/ to play your Mux Asset as well as monitor and report //github.com/ back it's playback performance. //github.com/ - Parameters: - //github.com/ - publicPlaybackID: playback ID of the Mux Asset + //github.com/ - playbackID: playback ID of the Mux Asset //github.com/ you'd like to play //github.com/ - customDomain: custom playback domain, custom //github.com/ domains need to be configured as described [here](https://docs.mux.com/guides/video/use-a-custom-domain-for-streaming#use-your-own-domain-for-delivering-videos-and-images) first //github.com/ - monitoringOptions: Options to customize monitoring //github.com/ data reported by Mux convenience init( - publicPlaybackID: String, - customDomain: URL, + playbackID: String, + playbackOptions: PlaybackOptions, monitoringOptions: MonitoringOptions ) { self.init() let playerItem = AVPlayerItem( - publicPlaybackID: publicPlaybackID, - customDomain: customDomain + playbackID: playbackID, + playbackOptions: playbackOptions ) let player = AVPlayer(playerItem: playerItem) diff --git a/Sources/MuxAVPlayerSDK/PublicAPI/Options/PlaybackOptions.swift b/Sources/MuxAVPlayerSDK/PublicAPI/Options/PlaybackOptions.swift index c4355b24..86710ea0 100644 --- a/Sources/MuxAVPlayerSDK/PublicAPI/Options/PlaybackOptions.swift +++ b/Sources/MuxAVPlayerSDK/PublicAPI/Options/PlaybackOptions.swift @@ -5,7 +5,7 @@ import Foundation //github.com/ The resolution tier you'd like your asset to be streamed at -enum ResolutionTier { +public enum ResolutionTier { //github.com/ By default no resolution tier is specified and Mux //github.com/ selects the optimal resolution and bitrate based on //github.com/ network and player conditions. @@ -15,12 +15,124 @@ enum ResolutionTier { case upTo720p } +extension ResolutionTier { + var queryValue: String { + switch self { + case .default: + return "" + case .upTo720p: + return "720p" + } + } +} + //github.com/ Options for playback -struct PlaybackOptions { +public struct PlaybackOptions { + + struct PublicPlaybackOptions { + + var maximumResolutionTier: ResolutionTier + + + var useRedundantStreams: Bool + } + + struct SignedPlaybackOptions { + var playbackToken: String + } + + enum PlaybackPolicy { + case `public`(PublicPlaybackOptions) + case signed(SignedPlaybackOptions) + } + + var playbackPolicy: PlaybackPolicy + + var customDomain: String? +} + +extension PlaybackOptions { + + //github.com/ Initializes playback options for a public + //github.com/ playback ID + //github.com/ - Parameters: + //github.com/ - maximumResolutionTier: maximum resolution of the + //github.com/ video the player will download + public init( + maximumResolutionTier: ResolutionTier = .default + ) { + self.playbackPolicy = .public( + PublicPlaybackOptions( + maximumResolutionTier: maximumResolutionTier, + useRedundantStreams: true + ) + ) + } + + + //github.com/ Initializes playback options for a public + //github.com/ playback ID + //github.com/ - Parameters: + //github.com/ //github.com/ - customDomain: custom playback domain, custom domains + //github.com/ need to be configured as described [here](https://docs.mux.com/guides/video/use-a-custom-domain-for-streaming#use-your-own-domain-for-delivering-videos-and-images) first. + //github.com/ The custom domain argument must have the format: + //github.com/ media.example.com. + //github.com/ + //github.com/ Based on the above example, constructed playback + //github.com/ URLs will use https://stream.media.example.com/ as + //github.com/ their base URL. + //github.com/ - maximumResolutionTier: maximum resolution of the + //github.com/ video the player will download + public init( + customDomain: String, + maximumResolutionTier: ResolutionTier = .default + ) { + self.customDomain = customDomain + self.playbackPolicy = .public( + PublicPlaybackOptions( + maximumResolutionTier: maximumResolutionTier, + useRedundantStreams: true + ) + ) + } + + //github.com/ Initializes playback options with a + //github.com/ signed playback token + //github.com/ - Parameter playbackToken: JSON web token signed + //github.com/ with a signing key + public init( + playbackToken: String + ) { + self.playbackPolicy = .signed( + SignedPlaybackOptions( + playbackToken: playbackToken + ) + ) + } - //github.com/ The resolution tier for playback - var resolutionTier: ResolutionTier - //github.com/ Uses either CDN to stream your video - var useRedundantStreams: Bool + //github.com/ Initializes playback options with a + //github.com/ signed playback token + //github.com/ - Parameters: + //github.com/ - customDomain: custom playback domain, custom domains + //github.com/ need to be configured as described [here](https://docs.mux.com/guides/video/use-a-custom-domain-for-streaming#use-your-own-domain-for-delivering-videos-and-images) first. + //github.com/ The custom domain argument must have the format: + //github.com/ media.example.com. + //github.com/ + //github.com/ Based on the above example, constructed playback + //github.com/ URLs will use https://stream.media.example.com/ as + //github.com/ their base URL. + //github.com/ - playbackToken: JSON web token signed + //github.com/ with a signing key + public init( + customDomain: String, + playbackToken: String + ) { + self.customDomain = customDomain + self.playbackPolicy = .signed( + SignedPlaybackOptions( + playbackToken: playbackToken + ) + ) + } } diff --git a/Tests/MuxAVPlayerSDKTests/PlaybackURLTests.swift b/Tests/MuxAVPlayerSDKTests/PlaybackURLTests.swift index de51e133..1248d6a8 100644 --- a/Tests/MuxAVPlayerSDKTests/PlaybackURLTests.swift +++ b/Tests/MuxAVPlayerSDKTests/PlaybackURLTests.swift @@ -9,12 +9,80 @@ import XCTest final class PlaybackURLTests: XCTestCase { func testPlaybackURL() throws { let playerItem = AVPlayerItem( - publicPlaybackID: "abc" + playbackID: "abc" ) XCTAssertEqual( (playerItem.asset as! AVURLAsset).url.absoluteString, - "https://stream.mux.com/abc.m3u8" + "https://stream.mux.com/abc.m3u8?redundant_streams=true" + ) + } + + func testMaximumResolution() throws { + let playbackOptions = PlaybackOptions( + maximumResolutionTier: .upTo720p + ) + + let playerItem = AVPlayerItem( + playbackID: "abc", + playbackOptions: playbackOptions + ) + + XCTAssertEqual( + (playerItem.asset as! AVURLAsset).url.absoluteString, + "https://stream.mux.com/abc.m3u8?redundant_streams=true&max_resolution=720p" + ) + } + + func testCustomDomainPlaybackURL() throws { + + let playbackOptions = PlaybackOptions( + customDomain: "play.example.com" + ) + + let playerItem = AVPlayerItem( + playbackID: "abc", + playbackOptions: playbackOptions + ) + + XCTAssertEqual( + (playerItem.asset as! AVURLAsset).url.absoluteString, + "https://stream.play.example.com/abc.m3u8?redundant_streams=true" + ) + } + + func testSignedPlaybackURL() throws { + + let playbackOptions = PlaybackOptions( + playbackToken: "WhoooopsNotAnActualToken" + ) + + let playerItem = AVPlayerItem( + playbackID: "abc", + playbackOptions: playbackOptions + ) + + XCTAssertEqual( + (playerItem.asset as! AVURLAsset).url.absoluteString, + "https://stream.mux.com/abc.m3u8?token=WhoooopsNotAnActualToken" + ) + } + + func testCustomDomainSignedPlaybackURL() throws { + + let playbackOptions = PlaybackOptions( + customDomain: "play.example.com", + playbackToken: "WhoooopsNotAnActualToken" + ) + + let playerItem = AVPlayerItem( + playbackID: "abc", + playbackOptions: playbackOptions + ) + + XCTAssertEqual( + (playerItem.asset as! AVURLAsset).url.absoluteString, + "https://stream.play.example.com/abc.m3u8?token=WhoooopsNotAnActualToken" ) } }








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/muxinc/mux-player-swift/commit/87865e66bd2192937f23fd36d8c419b97c5fc230.diff

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy