mirror of
https://github.com/jellyfin/Swiftfin.git
synced 2025-02-24 09:12:19 +00:00
rebase added hlsStreamURL param
This commit is contained in:
parent
56b60dafdc
commit
0749fa0520
@ -169,125 +169,156 @@ extension BaseItemDto {
|
||||
|
||||
func createLiveTVVideoPlayerViewModel() -> AnyPublisher<[VideoPlayerViewModel], Error> {
|
||||
|
||||
LogManager.shared.log.debug("Creating liveTV video player view model for item: \(id ?? "")")
|
||||
|
||||
let builder = DeviceProfileBuilder()
|
||||
// TODO: fix bitrate settings
|
||||
let tempOverkillBitrate = 360_000_000
|
||||
builder.setMaxBitrate(bitrate: tempOverkillBitrate)
|
||||
let profile = builder.buildProfile()
|
||||
|
||||
let playbackInfo = PlaybackInfoDto(userId: SessionManager.main.currentLogin.user.id,
|
||||
maxStreamingBitrate: tempOverkillBitrate,
|
||||
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
||||
deviceProfile: profile,
|
||||
autoOpenLiveStream: true)
|
||||
|
||||
return MediaInfoAPI.getPostedPlaybackInfo(itemId: self.id!,
|
||||
userId: SessionManager.main.currentLogin.user.id,
|
||||
maxStreamingBitrate: tempOverkillBitrate,
|
||||
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
||||
autoOpenLiveStream: true,
|
||||
playbackInfoDto: playbackInfo)
|
||||
.map { response -> [VideoPlayerViewModel] in
|
||||
let mediaSources = response.mediaSources!
|
||||
|
||||
var viewModels: [VideoPlayerViewModel] = []
|
||||
|
||||
for currentMediaSource in mediaSources {
|
||||
let audioStreams = currentMediaSource.mediaStreams?.filter { $0.type == .audio } ?? []
|
||||
let subtitleStreams = currentMediaSource.mediaStreams?.filter { $0.type == .subtitle } ?? []
|
||||
|
||||
let defaultAudioStream = audioStreams.first(where: { $0.index! == currentMediaSource.defaultAudioStreamIndex! })
|
||||
|
||||
let defaultSubtitleStream = subtitleStreams
|
||||
.first(where: { $0.index! == currentMediaSource.defaultSubtitleStreamIndex ?? -1 })
|
||||
|
||||
var directStreamURL: URL
|
||||
let transcodedStreamURL: URLComponents?
|
||||
let mediaSourceID: String
|
||||
let streamType: ServerStreamType
|
||||
|
||||
if let transcodeURL = currentMediaSource.transcodingUrl {
|
||||
streamType = .transcode
|
||||
transcodedStreamURL = URLComponents(string: SessionManager.main.currentLogin.server.currentURI
|
||||
.appending(transcodeURL))!
|
||||
} else {
|
||||
streamType = .direct
|
||||
transcodedStreamURL = nil
|
||||
}
|
||||
|
||||
if mediaSources.count > 1 {
|
||||
mediaSourceID = currentMediaSource.id!
|
||||
} else {
|
||||
mediaSourceID = self.id!
|
||||
}
|
||||
|
||||
let requestBuilder = VideosAPI.getVideoStreamWithRequestBuilder(itemId: self.id!,
|
||||
_static: true,
|
||||
tag: self.etag,
|
||||
minSegments: 6,
|
||||
mediaSourceId: mediaSourceID)
|
||||
directStreamURL = URL(string: requestBuilder.URLString)!
|
||||
|
||||
// MARK: VidoPlayerViewModel Creation
|
||||
|
||||
var subtitle: String?
|
||||
|
||||
// MARK: Attach media content to self
|
||||
|
||||
var modifiedSelfItem = self
|
||||
modifiedSelfItem.mediaStreams = currentMediaSource.mediaStreams
|
||||
|
||||
// TODO: other forms of media subtitle
|
||||
if self.itemType == .episode {
|
||||
if let seriesName = self.seriesName, let episodeLocator = self.getEpisodeLocator() {
|
||||
subtitle = "\(seriesName) - \(episodeLocator)"
|
||||
}
|
||||
}
|
||||
|
||||
let subtitlesEnabled = defaultSubtitleStream != nil
|
||||
|
||||
let shouldShowAutoPlay = Defaults[.shouldShowAutoPlay] && itemType == .episode
|
||||
let autoplayEnabled = Defaults[.autoplayEnabled] && shouldShowAutoPlay
|
||||
|
||||
let overlayType = Defaults[.overlayType]
|
||||
|
||||
let shouldShowPlayPreviousItem = Defaults[.shouldShowPlayPreviousItem] && itemType == .episode
|
||||
let shouldShowPlayNextItem = Defaults[.shouldShowPlayNextItem] && itemType == .episode
|
||||
|
||||
var fileName: String?
|
||||
if let lastInPath = currentMediaSource.path?.split(separator: "/").last {
|
||||
fileName = String(lastInPath)
|
||||
}
|
||||
|
||||
let videoPlayerViewModel = VideoPlayerViewModel(item: modifiedSelfItem,
|
||||
title: modifiedSelfItem.name ?? "",
|
||||
subtitle: subtitle,
|
||||
directStreamURL: directStreamURL,
|
||||
transcodedStreamURL: transcodedStreamURL?.url,
|
||||
streamType: streamType,
|
||||
response: response,
|
||||
audioStreams: audioStreams,
|
||||
subtitleStreams: subtitleStreams,
|
||||
chapters: modifiedSelfItem.chapters ?? [],
|
||||
selectedAudioStreamIndex: defaultAudioStream?.index ?? -1,
|
||||
selectedSubtitleStreamIndex: defaultSubtitleStream?.index ?? -1,
|
||||
subtitlesEnabled: subtitlesEnabled,
|
||||
autoplayEnabled: autoplayEnabled,
|
||||
overlayType: overlayType,
|
||||
shouldShowPlayPreviousItem: shouldShowPlayPreviousItem,
|
||||
shouldShowPlayNextItem: shouldShowPlayNextItem,
|
||||
shouldShowAutoPlay: shouldShowAutoPlay,
|
||||
container: currentMediaSource.container ?? "",
|
||||
filename: fileName,
|
||||
versionName: currentMediaSource.name)
|
||||
|
||||
viewModels.append(videoPlayerViewModel)
|
||||
}
|
||||
|
||||
return viewModels
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
LogManager.shared.log.debug("Creating liveTV video player view model for item: \(id ?? "")")
|
||||
|
||||
let builder = DeviceProfileBuilder()
|
||||
// TODO: fix bitrate settings
|
||||
let tempOverkillBitrate = 360_000_000
|
||||
builder.setMaxBitrate(bitrate: tempOverkillBitrate)
|
||||
let profile = builder.buildProfile()
|
||||
|
||||
let playbackInfo = PlaybackInfoDto(userId: SessionManager.main.currentLogin.user.id,
|
||||
maxStreamingBitrate: tempOverkillBitrate,
|
||||
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
||||
deviceProfile: profile,
|
||||
autoOpenLiveStream: true)
|
||||
|
||||
return MediaInfoAPI.getPostedPlaybackInfo(itemId: self.id!,
|
||||
userId: SessionManager.main.currentLogin.user.id,
|
||||
maxStreamingBitrate: tempOverkillBitrate,
|
||||
startTimeTicks: self.userData?.playbackPositionTicks ?? 0,
|
||||
autoOpenLiveStream: true,
|
||||
playbackInfoDto: playbackInfo)
|
||||
.map { response -> [VideoPlayerViewModel] in
|
||||
let mediaSources = response.mediaSources!
|
||||
|
||||
var viewModels: [VideoPlayerViewModel] = []
|
||||
|
||||
for currentMediaSource in mediaSources {
|
||||
let videoStream = currentMediaSource.mediaStreams?.filter { $0.type == .video }.first
|
||||
let audioStreams = currentMediaSource.mediaStreams?.filter { $0.type == .audio } ?? []
|
||||
let subtitleStreams = currentMediaSource.mediaStreams?.filter { $0.type == .subtitle } ?? []
|
||||
|
||||
let defaultAudioStream = audioStreams.first(where: { $0.index! == currentMediaSource.defaultAudioStreamIndex! })
|
||||
|
||||
let defaultSubtitleStream = subtitleStreams
|
||||
.first(where: { $0.index! == currentMediaSource.defaultSubtitleStreamIndex ?? -1 })
|
||||
|
||||
// MARK: Build Streams
|
||||
|
||||
let directStreamURL: URL
|
||||
let transcodedStreamURL: URLComponents?
|
||||
var hlsStreamURL: URL
|
||||
let mediaSourceID: String
|
||||
let streamType: ServerStreamType
|
||||
|
||||
if mediaSources.count > 1 {
|
||||
mediaSourceID = currentMediaSource.id!
|
||||
} else {
|
||||
mediaSourceID = self.id!
|
||||
}
|
||||
|
||||
let directStreamBuilder = VideosAPI.getVideoStreamWithRequestBuilder(itemId: self.id!,
|
||||
_static: true,
|
||||
tag: self.etag,
|
||||
playSessionId: response.playSessionId,
|
||||
minSegments: 6,
|
||||
mediaSourceId: mediaSourceID)
|
||||
directStreamURL = URL(string: directStreamBuilder.URLString)!
|
||||
|
||||
if let transcodeURL = currentMediaSource.transcodingUrl {
|
||||
streamType = .transcode
|
||||
transcodedStreamURL = URLComponents(string: SessionManager.main.currentLogin.server.currentURI
|
||||
.appending(transcodeURL))!
|
||||
} else {
|
||||
streamType = .direct
|
||||
transcodedStreamURL = nil
|
||||
}
|
||||
|
||||
let hlsStreamBuilder = DynamicHlsAPI.getMasterHlsVideoPlaylistWithRequestBuilder(itemId: id ?? "",
|
||||
mediaSourceId: id ?? "",
|
||||
_static: true,
|
||||
tag: currentMediaSource.eTag,
|
||||
deviceProfileId: nil,
|
||||
playSessionId: response.playSessionId,
|
||||
segmentContainer: "ts",
|
||||
segmentLength: nil,
|
||||
minSegments: 2,
|
||||
deviceId: UIDevice.vendorUUIDString,
|
||||
audioCodec: audioStreams
|
||||
.compactMap(\.codec)
|
||||
.joined(separator: ","),
|
||||
breakOnNonKeyFrames: true,
|
||||
requireAvc: true,
|
||||
transcodingMaxAudioChannels: 6,
|
||||
videoCodec: videoStream?.codec,
|
||||
videoStreamIndex: videoStream?.index,
|
||||
enableAdaptiveBitrateStreaming: true)
|
||||
|
||||
var hlsStreamComponents = URLComponents(string: hlsStreamBuilder.URLString)!
|
||||
hlsStreamComponents.addQueryItem(name: "api_key", value: SessionManager.main.currentLogin.user.accessToken)
|
||||
|
||||
hlsStreamURL = hlsStreamComponents.url!
|
||||
|
||||
// MARK: VidoPlayerViewModel Creation
|
||||
|
||||
var subtitle: String?
|
||||
|
||||
// MARK: Attach media content to self
|
||||
|
||||
var modifiedSelfItem = self
|
||||
modifiedSelfItem.mediaStreams = currentMediaSource.mediaStreams
|
||||
|
||||
// TODO: other forms of media subtitle
|
||||
if self.itemType == .episode {
|
||||
if let seriesName = self.seriesName, let episodeLocator = self.getEpisodeLocator() {
|
||||
subtitle = "\(seriesName) - \(episodeLocator)"
|
||||
}
|
||||
}
|
||||
|
||||
let subtitlesEnabled = defaultSubtitleStream != nil
|
||||
|
||||
let shouldShowAutoPlay = Defaults[.shouldShowAutoPlay] && itemType == .episode
|
||||
let autoplayEnabled = Defaults[.autoplayEnabled] && shouldShowAutoPlay
|
||||
|
||||
let overlayType = Defaults[.overlayType]
|
||||
|
||||
let shouldShowPlayPreviousItem = Defaults[.shouldShowPlayPreviousItem] && itemType == .episode
|
||||
let shouldShowPlayNextItem = Defaults[.shouldShowPlayNextItem] && itemType == .episode
|
||||
|
||||
var fileName: String?
|
||||
if let lastInPath = currentMediaSource.path?.split(separator: "/").last {
|
||||
fileName = String(lastInPath)
|
||||
}
|
||||
|
||||
let videoPlayerViewModel = VideoPlayerViewModel(item: modifiedSelfItem,
|
||||
title: modifiedSelfItem.name ?? "",
|
||||
subtitle: subtitle,
|
||||
directStreamURL: directStreamURL,
|
||||
transcodedStreamURL: transcodedStreamURL?.url,
|
||||
hlsStreamURL: hlsStreamURL,
|
||||
streamType: streamType,
|
||||
response: response,
|
||||
audioStreams: audioStreams,
|
||||
subtitleStreams: subtitleStreams,
|
||||
chapters: modifiedSelfItem.chapters ?? [],
|
||||
selectedAudioStreamIndex: defaultAudioStream?.index ?? -1,
|
||||
selectedSubtitleStreamIndex: defaultSubtitleStream?.index ?? -1,
|
||||
subtitlesEnabled: subtitlesEnabled,
|
||||
autoplayEnabled: autoplayEnabled,
|
||||
overlayType: overlayType,
|
||||
shouldShowPlayPreviousItem: shouldShowPlayPreviousItem,
|
||||
shouldShowPlayNextItem: shouldShowPlayNextItem,
|
||||
shouldShowAutoPlay: shouldShowAutoPlay,
|
||||
container: currentMediaSource.container ?? "",
|
||||
filename: fileName,
|
||||
versionName: currentMediaSource.name)
|
||||
|
||||
viewModels.append(videoPlayerViewModel)
|
||||
}
|
||||
|
||||
return viewModels
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,8 @@ struct tvOSLiveTVOverlay_Previews: PreviewProvider {
|
||||
title: "Glorious Purpose",
|
||||
subtitle: "Loki - S1E1",
|
||||
directStreamURL: URL(string: "www.apple.com")!,
|
||||
transcodedStreamURL: nil,
|
||||
transcodedStreamURL: nil,
|
||||
hlsStreamURL: URL(string: "www.apple.com")!,
|
||||
streamType: .direct,
|
||||
response: PlaybackInfoResponse(),
|
||||
audioStreams: [MediaStream(displayTitle: "English", index: -1)],
|
||||
|
Loading…
x
Reference in New Issue
Block a user