mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 23:59:08 +00:00
350 lines
9.6 KiB
Markdown
350 lines
9.6 KiB
Markdown
# KSOptions
|
|
|
|
`KSOptions` is the configuration class for KSPlayer. It contains both instance properties (per-player settings) and static properties (global defaults).
|
|
|
|
## Creating Options
|
|
|
|
```swift
|
|
let options = KSOptions()
|
|
|
|
// Configure instance properties
|
|
options.isLoopPlay = true
|
|
options.startPlayTime = 30.0 // Start at 30 seconds
|
|
|
|
// Use with player
|
|
playerView.set(url: url, options: options)
|
|
```
|
|
|
|
## Instance Properties
|
|
|
|
### Buffering
|
|
|
|
| Property | Type | Default | Description |
|
|
|----------|------|---------|-------------|
|
|
| `preferredForwardBufferDuration` | `TimeInterval` | `3.0` | Minimum buffer duration before playback starts |
|
|
| `maxBufferDuration` | `TimeInterval` | `30.0` | Maximum buffer duration |
|
|
| `isSecondOpen` | `Bool` | `false` | Enable fast open (instant playback) |
|
|
|
|
### Seeking
|
|
|
|
| Property | Type | Default | Description |
|
|
|----------|------|---------|-------------|
|
|
| `isAccurateSeek` | `Bool` | `false` | Enable frame-accurate seeking |
|
|
| `seekFlags` | `Int32` | `1` | FFmpeg seek flags (AVSEEK_FLAG_BACKWARD) |
|
|
| `isSeekedAutoPlay` | `Bool` | `true` | Auto-play after seeking |
|
|
|
|
### Playback
|
|
|
|
| Property | Type | Default | Description |
|
|
|----------|------|---------|-------------|
|
|
| `isLoopPlay` | `Bool` | `false` | Loop playback (for short videos) |
|
|
| `startPlayTime` | `TimeInterval` | `0` | Initial playback position (seconds) |
|
|
| `startPlayRate` | `Float` | `1.0` | Initial playback rate |
|
|
| `registerRemoteControll` | `Bool` | `true` | Enable system remote control |
|
|
|
|
### Video
|
|
|
|
| Property | Type | Default | Description |
|
|
|----------|------|---------|-------------|
|
|
| `display` | `DisplayEnum` | `.plane` | Display mode (`.plane`, `.vr`, `.vrBox`) |
|
|
| `videoDelay` | `Double` | `0.0` | Video delay in seconds |
|
|
| `autoDeInterlace` | `Bool` | `false` | Auto-detect interlacing |
|
|
| `autoRotate` | `Bool` | `true` | Auto-rotate based on metadata |
|
|
| `destinationDynamicRange` | `DynamicRange?` | `nil` | Target HDR mode |
|
|
| `videoAdaptable` | `Bool` | `true` | Enable adaptive bitrate |
|
|
| `videoFilters` | `[String]` | `[]` | FFmpeg video filters |
|
|
| `syncDecodeVideo` | `Bool` | `false` | Synchronous video decoding |
|
|
| `hardwareDecode` | `Bool` | `true` | Use hardware decoding |
|
|
| `asynchronousDecompression` | `Bool` | `false` | Async hardware decompression |
|
|
| `videoDisable` | `Bool` | `false` | Disable video track |
|
|
|
|
### Audio
|
|
|
|
| Property | Type | Default | Description |
|
|
|----------|------|---------|-------------|
|
|
| `audioFilters` | `[String]` | `[]` | FFmpeg audio filters |
|
|
| `syncDecodeAudio` | `Bool` | `false` | Synchronous audio decoding |
|
|
|
|
### Subtitles
|
|
|
|
| Property | Type | Default | Description |
|
|
|----------|------|---------|-------------|
|
|
| `autoSelectEmbedSubtitle` | `Bool` | `true` | Auto-select embedded subtitles |
|
|
| `isSeekImageSubtitle` | `Bool` | `false` | Seek for image subtitles |
|
|
|
|
### Picture-in-Picture
|
|
|
|
| Property | Type | Default | Description |
|
|
|----------|------|---------|-------------|
|
|
| `canStartPictureInPictureAutomaticallyFromInline` | `Bool` | `true` | Auto-start PiP when app backgrounds |
|
|
|
|
### Window (macOS)
|
|
|
|
| Property | Type | Default | Description |
|
|
|----------|------|---------|-------------|
|
|
| `automaticWindowResize` | `Bool` | `true` | Auto-resize window to video aspect ratio |
|
|
|
|
### Network/HTTP
|
|
|
|
| Property | Type | Default | Description |
|
|
|----------|------|---------|-------------|
|
|
| `referer` | `String?` | `nil` | HTTP referer header |
|
|
| `userAgent` | `String?` | `"KSPlayer"` | HTTP user agent |
|
|
| `cache` | `Bool` | `false` | Enable FFmpeg HTTP caching |
|
|
| `outputURL` | `URL?` | `nil` | URL to record/save stream |
|
|
|
|
### FFmpeg Options
|
|
|
|
| Property | Type | Default | Description |
|
|
|----------|------|---------|-------------|
|
|
| `avOptions` | `[String: Any]` | `[:]` | AVURLAsset options |
|
|
| `formatContextOptions` | `[String: Any]` | See below | FFmpeg format context options |
|
|
| `decoderOptions` | `[String: Any]` | See below | FFmpeg decoder options |
|
|
| `probesize` | `Int64?` | `nil` | FFmpeg probe size |
|
|
| `maxAnalyzeDuration` | `Int64?` | `nil` | Max analyze duration |
|
|
| `lowres` | `UInt8` | `0` | Low resolution decoding |
|
|
| `nobuffer` | `Bool` | `false` | Disable buffering |
|
|
| `codecLowDelay` | `Bool` | `false` | Low delay codec mode |
|
|
|
|
#### Default formatContextOptions
|
|
|
|
```swift
|
|
[
|
|
"user_agent": "KSPlayer",
|
|
"scan_all_pmts": 1,
|
|
"reconnect": 1,
|
|
"reconnect_streamed": 1
|
|
]
|
|
```
|
|
|
|
#### Default decoderOptions
|
|
|
|
```swift
|
|
[
|
|
"threads": "auto",
|
|
"refcounted_frames": "1"
|
|
]
|
|
```
|
|
|
|
### Read-Only Timing Properties
|
|
|
|
| Property | Type | Description |
|
|
|----------|------|-------------|
|
|
| `formatName` | `String` | Detected format name |
|
|
| `prepareTime` | `Double` | Time when prepare started |
|
|
| `dnsStartTime` | `Double` | DNS lookup start time |
|
|
| `tcpStartTime` | `Double` | TCP connection start time |
|
|
| `tcpConnectedTime` | `Double` | TCP connected time |
|
|
| `openTime` | `Double` | File open time |
|
|
| `findTime` | `Double` | Stream find time |
|
|
| `readyTime` | `Double` | Ready to play time |
|
|
| `readAudioTime` | `Double` | First audio read time |
|
|
| `readVideoTime` | `Double` | First video read time |
|
|
| `decodeAudioTime` | `Double` | First audio decode time |
|
|
| `decodeVideoTime` | `Double` | First video decode time |
|
|
|
|
## Static Properties (Global Defaults)
|
|
|
|
### Player Types
|
|
|
|
```swift
|
|
// Primary player type (default: AVPlayer)
|
|
KSOptions.firstPlayerType: MediaPlayerProtocol.Type = KSAVPlayer.self
|
|
|
|
// Fallback player type (default: FFmpeg)
|
|
KSOptions.secondPlayerType: MediaPlayerProtocol.Type? = KSMEPlayer.self
|
|
```
|
|
|
|
### Buffering Defaults
|
|
|
|
```swift
|
|
KSOptions.preferredForwardBufferDuration: TimeInterval = 3.0
|
|
KSOptions.maxBufferDuration: TimeInterval = 30.0
|
|
KSOptions.isSecondOpen: Bool = false
|
|
```
|
|
|
|
### Playback Defaults
|
|
|
|
```swift
|
|
KSOptions.isAccurateSeek: Bool = false
|
|
KSOptions.isLoopPlay: Bool = false
|
|
KSOptions.isAutoPlay: Bool = true
|
|
KSOptions.isSeekedAutoPlay: Bool = true
|
|
```
|
|
|
|
### Decoding
|
|
|
|
```swift
|
|
KSOptions.hardwareDecode: Bool = true
|
|
KSOptions.asynchronousDecompression: Bool = false
|
|
KSOptions.canStartPictureInPictureAutomaticallyFromInline: Bool = true
|
|
```
|
|
|
|
### UI Options
|
|
|
|
```swift
|
|
// Top bar visibility: .always, .horizantalOnly, .none
|
|
KSOptions.topBarShowInCase: KSPlayerTopBarShowCase = .always
|
|
|
|
// Auto-hide controls delay
|
|
KSOptions.animateDelayTimeInterval: TimeInterval = 5.0
|
|
|
|
// Gesture controls
|
|
KSOptions.enableBrightnessGestures: Bool = true
|
|
KSOptions.enableVolumeGestures: Bool = true
|
|
KSOptions.enablePlaytimeGestures: Bool = true
|
|
|
|
// Background playback
|
|
KSOptions.canBackgroundPlay: Bool = false
|
|
```
|
|
|
|
### PiP
|
|
|
|
```swift
|
|
KSOptions.isPipPopViewController: Bool = false
|
|
```
|
|
|
|
### Logging
|
|
|
|
```swift
|
|
// Log levels: .panic, .fatal, .error, .warning, .info, .verbose, .debug, .trace
|
|
KSOptions.logLevel: LogLevel = .warning
|
|
KSOptions.logger: LogHandler = OSLog(lable: "KSPlayer")
|
|
```
|
|
|
|
### System
|
|
|
|
```swift
|
|
KSOptions.useSystemHTTPProxy: Bool = true
|
|
KSOptions.preferredFrame: Bool = true
|
|
```
|
|
|
|
### Subtitle Data Sources
|
|
|
|
```swift
|
|
KSOptions.subtitleDataSouces: [SubtitleDataSouce] = [DirectorySubtitleDataSouce()]
|
|
```
|
|
|
|
## Methods
|
|
|
|
### HTTP Headers
|
|
|
|
```swift
|
|
let options = KSOptions()
|
|
options.appendHeader(["Referer": "https://example.com"])
|
|
options.appendHeader(["Authorization": "Bearer token123"])
|
|
```
|
|
|
|
### Cookies
|
|
|
|
```swift
|
|
let cookies = [HTTPCookie(properties: [
|
|
.name: "session",
|
|
.value: "abc123",
|
|
.domain: "example.com",
|
|
.path: "/"
|
|
])!]
|
|
options.setCookie(cookies)
|
|
```
|
|
|
|
## Overridable Methods
|
|
|
|
Subclass `KSOptions` to customize behavior:
|
|
|
|
### Buffering Algorithm
|
|
|
|
```swift
|
|
class CustomOptions: KSOptions {
|
|
override func playable(capacitys: [CapacityProtocol], isFirst: Bool, isSeek: Bool) -> LoadingState {
|
|
// Custom buffering logic
|
|
super.playable(capacitys: capacitys, isFirst: isFirst, isSeek: isSeek)
|
|
}
|
|
}
|
|
```
|
|
|
|
### Adaptive Bitrate
|
|
|
|
```swift
|
|
override func adaptable(state: VideoAdaptationState?) -> (Int64, Int64)? {
|
|
// Return (currentBitrate, targetBitrate) or nil
|
|
super.adaptable(state: state)
|
|
}
|
|
```
|
|
|
|
### Track Selection
|
|
|
|
```swift
|
|
// Select preferred video track
|
|
override func wantedVideo(tracks: [MediaPlayerTrack]) -> Int? {
|
|
// Return index of preferred track or nil for auto
|
|
return tracks.firstIndex { $0.bitRate > 5_000_000 }
|
|
}
|
|
|
|
// Select preferred audio track
|
|
override func wantedAudio(tracks: [MediaPlayerTrack]) -> Int? {
|
|
// Return index of preferred track or nil for auto
|
|
return tracks.firstIndex { $0.languageCode == "en" }
|
|
}
|
|
```
|
|
|
|
### Display Layer
|
|
|
|
```swift
|
|
override func isUseDisplayLayer() -> Bool {
|
|
// Return true to use AVSampleBufferDisplayLayer (supports HDR10+)
|
|
// Return false for other display modes
|
|
display == .plane
|
|
}
|
|
```
|
|
|
|
### Track Processing
|
|
|
|
```swift
|
|
override func process(assetTrack: some MediaPlayerTrack) {
|
|
super.process(assetTrack: assetTrack)
|
|
// Custom processing before decoder creation
|
|
}
|
|
```
|
|
|
|
### Live Playback Rate
|
|
|
|
```swift
|
|
override func liveAdaptivePlaybackRate(loadingState: LoadingState) -> Float? {
|
|
// Return adjusted playback rate for live streams
|
|
// Return nil to keep current rate
|
|
if loadingState.loadedTime > preferredForwardBufferDuration + 5 {
|
|
return 1.2 // Speed up if too far behind
|
|
}
|
|
return nil
|
|
}
|
|
```
|
|
|
|
## Example: Custom Options
|
|
|
|
```swift
|
|
class StreamingOptions: KSOptions {
|
|
override init() {
|
|
super.init()
|
|
|
|
// Low latency settings
|
|
preferredForwardBufferDuration = 1.0
|
|
isSecondOpen = true
|
|
nobuffer = true
|
|
codecLowDelay = true
|
|
|
|
// Custom headers
|
|
appendHeader(["X-Custom-Header": "value"])
|
|
}
|
|
|
|
override func wantedAudio(tracks: [MediaPlayerTrack]) -> Int? {
|
|
// Prefer English audio
|
|
return tracks.firstIndex { $0.languageCode == "en" }
|
|
}
|
|
}
|
|
|
|
// Usage
|
|
let options = StreamingOptions()
|
|
playerView.set(url: streamURL, options: options)
|
|
```
|
|
|