get ready for adaptable bitrate streaming

This commit is contained in:
Aiden Vigue 2021-05-24 23:04:58 -04:00
parent 901a60639d
commit 96beaa5771
6 changed files with 114 additions and 46 deletions

View File

@ -313,6 +313,13 @@ struct ContentView: View {
SentrySDK.capture(error: error)
break
}
let defaults = UserDefaults.standard;
if(defaults.integer(forKey: "InNetworkBandwidth") == 0) {
defaults.setValue(40000000, forKey: "inNetworkBandwidth")
}
if(defaults.integer(forKey: "OutOfNetworkBandwidth") == 0) {
defaults.setValue(40000000, forKey: "OutOfNetworkBandwidth")
}
_isLoading.wrappedValue = false;
}
} catch {

View File

@ -93,9 +93,15 @@ struct DeviceProfileRoot: Codable {
}
class DeviceProfileBuilder {
public var bitrate: Int = 0;
public func setMaxBitrate(bitrate: Int) {
self.bitrate = bitrate
}
public func buildProfile() -> DeviceProfileRoot {
let MaxStreamingBitrate = 120000000;
let MaxStaticBitrate = 100000000
let MaxStreamingBitrate = bitrate;
let MaxStaticBitrate = bitrate;
let MusicStreamingTranscodingBitrate = 384000;
//Build direct play profiles

View File

@ -19,10 +19,6 @@ struct LibraryView: View {
@State private var selected_library_id: String = "";
@State private var isLoading: Bool = true;
@State private var startIndex: Int = 0;
@State private var endIndex: Int = 60;
@State private var totalItems: Int = 0;
@State private var viewDidLoad: Bool = false;
@State private var filterString: String = "&SortBy=SortName&SortOrder=Descending";
@State private var showFiltersPopover: Bool = false;
@ -92,7 +88,6 @@ struct LibraryView: View {
let body = response.body
do {
let json = try JSON(data: body)
_totalItems.wrappedValue = json["TotalRecordCount"].int ?? 0;
for (_,item):(String, JSON) in json["Items"] {
// Do something you want
let itemObj = ResumeItem()
@ -229,21 +224,6 @@ struct LibraryView: View {
}.frame(width: 100)
}
}
if(startIndex + endIndex < totalItems) {
HStack() {
Spacer()
Button() {
startIndex += endIndex;
loadItems()
} label: {
HStack() {
Text("Load more").font(.callout)
Image(systemName: "arrow.clockwise")
}
}
Spacer()
}
}
Spacer().frame(height: 2)
}
}
@ -255,8 +235,6 @@ struct LibraryView: View {
.onAppear(perform: onAppear)
.onChange(of: filterString) { tag in
isLoading = true;
startIndex = 0;
totalItems = 0;
items = [];
loadItems();
}

View File

@ -8,6 +8,13 @@
import SwiftUI
import CoreData
struct UserSettings: Codable {
var LocalMaxBitrate: Int;
var RemoteMaxBitrate: Int;
var AutoSelectSubtitles: Bool;
var AutoSelectSubtitlesLangcode: String;
}
struct SettingsView: View {
@Binding var close: Bool;
@Environment(\.managedObjectContext) private var viewContext
@ -15,9 +22,13 @@ struct SettingsView: View {
@EnvironmentObject var jsi: justSignedIn
@State private var username: String = "";
@State private var inNetworkStreamBitrate: Int = 40000000;
@State private var outOfNetworkStreamBitrate: Int = 40000000;
func onAppear() {
_username.wrappedValue = globalData.user?.username ?? "";
let defaults = UserDefaults.standard
_inNetworkStreamBitrate.wrappedValue = defaults.integer(forKey: "InNetworkBandwidth");
_outOfNetworkStreamBitrate.wrappedValue = defaults.integer(forKey: "OutOfNetworkBandwidth");
}
var body: some View {
@ -33,16 +44,19 @@ struct SettingsView: View {
Text("1080p - 10 Mbps").tag(10000000)
}
Group {
Text("720p - 8 Mbps").tag(80000000)
Text("720p - 6 Mbps").tag(60000000)
Text("720p - 4 Mbps").tag(40000000)
Text("720p - 8 Mbps").tag(8000000)
Text("720p - 6 Mbps").tag(6000000)
Text("720p - 4 Mbps").tag(4000000)
}
Text("480p - 3 Mbps").tag(30000000)
Text("480p - 1.5 Mbps").tag(20000000)
Text("480p - 740 Kbps").tag(10000000)
Text("480p - 3 Mbps").tag(3000000)
Text("480p - 1.5 Mbps").tag(2000000)
Text("480p - 740 Kbps").tag(1000000)
}.onChange(of: inNetworkStreamBitrate) { _ in
let defaults = UserDefaults.standard
defaults.setValue(_inNetworkStreamBitrate.wrappedValue, forKey: "InNetworkBandwidth")
}
Picker("Default remote playback bitrate", selection: $inNetworkStreamBitrate) {
Picker("Default remote playback bitrate", selection: $outOfNetworkStreamBitrate) {
Group {
Text("1080p - 60 Mbps").tag(60000000)
Text("1080p - 40 Mbps").tag(40000000)
@ -51,13 +65,16 @@ struct SettingsView: View {
Text("1080p - 10 Mbps").tag(10000000)
}
Group {
Text("720p - 8 Mbps").tag(80000000)
Text("720p - 6 Mbps").tag(60000000)
Text("720p - 4 Mbps").tag(40000000)
Text("720p - 8 Mbps").tag(8000000)
Text("720p - 6 Mbps").tag(6000000)
Text("720p - 4 Mbps").tag(4000000)
}
Text("480p - 3 Mbps").tag(30000000)
Text("480p - 1.5 Mbps").tag(20000000)
Text("480p - 740 Kbps").tag(10000000)
Text("480p - 3 Mbps").tag(3000000)
Text("480p - 1.5 Mbps").tag(2000000)
Text("480p - 740 Kbps").tag(1000000)
}.onChange(of: outOfNetworkStreamBitrate) { _ in
let defaults = UserDefaults.standard
defaults.setValue(_outOfNetworkStreamBitrate.wrappedValue, forKey: "OutOfNetworkBandwidth")
}
}

View File

@ -62,7 +62,7 @@ class PlayerUIView: UIView, VLCMediaPlayerDelegate {
mediaPlayer.wrappedValue.stop()
mediaPlayer.wrappedValue.media = VLCMedia(url: url.wrappedValue.videoUrl)
self.url.wrappedValue.subtitles.forEach() { sub in
if(sub.id != -1 && sub.delivery == "External") {
if(sub.id != -1 && sub.delivery == "External" && sub.codec != "subrip") {
mediaPlayer.wrappedValue.addPlaybackSlave(sub.url, type: .subtitle, enforce: false)
}
}

View File

@ -18,6 +18,7 @@ struct Subtitle {
var id: Int32;
var url: URL;
var delivery: String;
var codec: String;
}
extension String {
@ -57,6 +58,7 @@ struct VideoPlayerView: View {
@State private var iterations: Int = 0;
@State private var startTime: Int = 0;
@State private var hasSentPlayReport: Bool = false;
@State private var selectedVideoQuality: Int = 0;
@State private var captionConfiguration: Bool = false {
didSet {
if(captionConfiguration == false) {
@ -72,6 +74,9 @@ struct VideoPlayerView: View {
}
}
};
@State private var playbackSettings: Bool = false;
@State private var selectedCaptionTrack: Int32 = -1;
@State private var selectedAudioTrack: Int32 = -1;
var playing: Binding<Bool>;
@ -224,6 +229,15 @@ struct VideoPlayerView: View {
func startStream() {
let builder = DeviceProfileBuilder()
let defaults = UserDefaults.standard;
if(globalData.isInNetwork) {
builder.setMaxBitrate(bitrate: defaults.integer(forKey: "InNetworkBandwidth"))
} else {
builder.setMaxBitrate(bitrate: defaults.integer(forKey: "OutOfNetworkBandwidth"))
}
_selectedVideoQuality.wrappedValue = builder.bitrate;
let DeviceProfile = builder.buildProfile()
let jsonEncoder = JSONEncoder()
@ -254,18 +268,18 @@ struct VideoPlayerView: View {
let streamURL: URL = URL(string: "\(globalData.server?.baseURI ?? "")\((json["MediaSources"][0]["TranscodingUrl"].string ?? ""))")!
print(streamURL)
let item = PlaybackItem(videoType: VideoType.hls, videoUrl: streamURL, subtitles: [])
let disableSubtitleTrack = Subtitle(name: "Disabled", id: -1, url: URL(string: "https://example.com")!, delivery: "Embed")
let disableSubtitleTrack = Subtitle(name: "Disabled", id: -1, url: URL(string: "https://example.com")!, delivery: "Embed", codec: "")
_subtitles.wrappedValue.append(disableSubtitleTrack);
for (_,stream):(String, JSON) in json["MediaSources"][0]["MediaStreams"] {
if(stream["Type"].string == "Subtitle" && stream["Codec"] != "subrip") { //ignore ripped subtitles - we don't want to extract subtitles
let deliveryUrl = URL(string: "\(globalData.server?.baseURI ?? "")\(stream["DeliveryUrl"].string ?? "")")!
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["DeliveryMethod"].string ?? "")
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["DeliveryMethod"].string ?? "", codec: stream["Codec"].string ?? "")
_subtitles.wrappedValue.append(subtitle);
}
if(stream["Type"].string == "Audio") {
let deliveryUrl = URL(string: "https://example.com")!
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["IsExternal"].boolValue ? "External" : "Embed")
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["IsExternal"].boolValue ? "External" : "Embed", codec: stream["Codec"].string ?? "")
if(stream["IsDefault"].boolValue) {
_selectedAudioTrack.wrappedValue = Int32(stream["Index"].int ?? 0);
}
@ -281,7 +295,6 @@ struct VideoPlayerView: View {
let streamUrl = streamURL.absoluteString;
let segmentUrl = URL(string: streamUrl.replacingOccurrences(of: "master.m3u8", with: "hls1/main/0.ts"))!
print(segmentUrl)
var request2 = URLRequest(url: segmentUrl)
request2.httpMethod = "GET"
@ -298,18 +311,18 @@ struct VideoPlayerView: View {
print("Direct playing!");
let streamURL: URL = URL(string: "\(globalData.server?.baseURI ?? "")/Videos/\(item.Id)/stream?Static=true&mediaSourceId=\(item.Id)&deviceId=\(globalData.user?.device_uuid ?? "")&api_key=\(globalData.authToken)&Tag=\(json["MediaSources"][0]["ETag"])")!;
let item = PlaybackItem(videoType: VideoType.direct, videoUrl: streamURL, subtitles: [])
let disableSubtitleTrack = Subtitle(name: "Disabled", id: -1, url: URL(string: "https://example.com")!, delivery: "Embed")
let disableSubtitleTrack = Subtitle(name: "Disabled", id: -1, url: URL(string: "https://example.com")!, delivery: "Embed", codec: "")
_subtitles.wrappedValue.append(disableSubtitleTrack);
for (_,stream):(String, JSON) in json["MediaSources"][0]["MediaStreams"] {
if(stream["Type"].string == "Subtitle") {
if(stream["Type"].string == "Subtitle" && stream["Codec"] != "subrip") {
let deliveryUrl = URL(string: "\(globalData.server?.baseURI ?? "")\(stream["DeliveryUrl"].string ?? "")")!
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["DeliveryMethod"].string ?? "")
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["DeliveryMethod"].string ?? "", codec: stream["Codec"].string ?? "")
_subtitles.wrappedValue.append(subtitle);
}
if(stream["Type"].string == "Audio") {
let deliveryUrl = URL(string: "https://example.com")!
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["IsExternal"].boolValue ? "External" : "Embed")
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["IsExternal"].boolValue ? "External" : "Embed", codec: stream["Codec"].string ?? "")
if(stream["IsDefault"].boolValue) {
_selectedAudioTrack.wrappedValue = Int32(stream["Index"].int ?? 0);
}
@ -391,6 +404,14 @@ struct VideoPlayerView: View {
Spacer()
Text(item.Name).font(.headline).fontWeight(.semibold).foregroundColor(.white).offset(x:-4)
Spacer()
Button() {
vlcplayer.pause()
self.playbackSettings = true;
} label: {
HStack() {
Image(systemName: "gear").font(.system(size: 20)).foregroundColor(.white)
}
}.frame(width: 20).padding(.trailing,15)
Button() {
vlcplayer.pause()
self.captionConfiguration = true;
@ -516,5 +537,44 @@ struct VideoPlayerView: View {
}
}.edgesIgnoringSafeArea(.bottom)
}
EmptyView()
.fullScreenCover(isPresented: $playbackSettings) {
NavigationView() {
Form() {
Picker("Quality", selection: $selectedVideoQuality) {
Group {
Text("1080p - 60 Mbps").tag(60000000)
Text("1080p - 40 Mbps").tag(40000000)
Text("1080p - 20 Mbps").tag(20000000)
Text("1080p - 15 Mbps").tag(15000000)
Text("1080p - 10 Mbps").tag(10000000)
}
Group {
Text("720p - 8 Mbps").tag(8000000)
Text("720p - 6 Mbps").tag(6000000)
Text("720p - 4 Mbps").tag(4000000)
}
Text("480p - 3 Mbps").tag(3000000)
Text("480p - 1.5 Mbps").tag(2000000)
Text("480p - 740 Kbps").tag(1000000)
}.onChange(of: selectedVideoQuality) { quality in
print(quality)
}
}
.navigationBarTitle("Playback Settings", displayMode: .inline)
.toolbar {
ToolbarItemGroup(placement: .navigationBarLeading) {
Button {
playbackSettings = false;
playPauseButtonSystemName = "pause";
} label: {
HStack() {
Text("Back").font(.callout)
}
}
}
}
}.edgesIgnoringSafeArea(.bottom)
}
}
}