Fix some transcoding bugs causing playback to stall & stop
This commit is contained in:
parent
889f085426
commit
352d47f387
|
@ -300,6 +300,7 @@ struct ConnectToServerView: View {
|
||||||
Button() {
|
Button() {
|
||||||
if(pubuser.hasPassword) {
|
if(pubuser.hasPassword) {
|
||||||
_lastPublicUsers.wrappedValue = _publicUsers.wrappedValue
|
_lastPublicUsers.wrappedValue = _publicUsers.wrappedValue
|
||||||
|
_username.wrappedValue = pubuser.username
|
||||||
_publicUsers.wrappedValue = []
|
_publicUsers.wrappedValue = []
|
||||||
} else {
|
} else {
|
||||||
_publicUsers.wrappedValue = []
|
_publicUsers.wrappedValue = []
|
||||||
|
|
|
@ -166,6 +166,7 @@ class DeviceProfileBuilder {
|
||||||
SubtitleProfiles.append(_AVSubtitleProfile(Format: "ssa", Method: "External"))
|
SubtitleProfiles.append(_AVSubtitleProfile(Format: "ssa", Method: "External"))
|
||||||
SubtitleProfiles.append(_AVSubtitleProfile(Format: "pgssub", Method: "Embed"))
|
SubtitleProfiles.append(_AVSubtitleProfile(Format: "pgssub", Method: "Embed"))
|
||||||
SubtitleProfiles.append(_AVSubtitleProfile(Format: "sub", Method: "Embed"))
|
SubtitleProfiles.append(_AVSubtitleProfile(Format: "sub", Method: "Embed"))
|
||||||
|
SubtitleProfiles.append(_AVSubtitleProfile(Format: "srt", Method: "External"))
|
||||||
|
|
||||||
let ResponseProfiles: [_AVResponseProfile] = [_AVResponseProfile(Type: "Video", Container: "m4v", MimeType: "video/mp4")]
|
let ResponseProfiles: [_AVResponseProfile] = [_AVResponseProfile(Type: "Video", Container: "m4v", MimeType: "video/mp4")]
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ class PlayerUIView: UIView, VLCMediaPlayerDelegate {
|
||||||
|
|
||||||
DispatchQueue.global(qos: .utility).async { [weak self] in
|
DispatchQueue.global(qos: .utility).async { [weak self] in
|
||||||
if(self?.url.wrappedValue.videoType ?? .hls == .hls) {
|
if(self?.url.wrappedValue.videoType ?? .hls == .hls) {
|
||||||
usleep(75000000)
|
usleep(50000000)
|
||||||
}
|
}
|
||||||
self?.mediaPlayer.wrappedValue.play()
|
self?.mediaPlayer.wrappedValue.play()
|
||||||
if(self?.startTime != 0) {
|
if(self?.startTime != 0) {
|
||||||
|
|
|
@ -55,6 +55,7 @@ struct VideoPlayerView: View {
|
||||||
@State private var playSessionId: String = "";
|
@State private var playSessionId: String = "";
|
||||||
@State private var lastPosition: Double = 0;
|
@State private var lastPosition: Double = 0;
|
||||||
@State private var iterations: Int = 0;
|
@State private var iterations: Int = 0;
|
||||||
|
@State private var startTime: Int = 0;
|
||||||
@State private var captionConfiguration: Bool = false {
|
@State private var captionConfiguration: Bool = false {
|
||||||
didSet {
|
didSet {
|
||||||
if(captionConfiguration == false) {
|
if(captionConfiguration == false) {
|
||||||
|
@ -85,13 +86,14 @@ struct VideoPlayerView: View {
|
||||||
if(!vlcplayer.isPlaying) {
|
if(!vlcplayer.isPlaying) {
|
||||||
while(!vlcplayer.isPlaying) {}
|
while(!vlcplayer.isPlaying) {}
|
||||||
}
|
}
|
||||||
|
sendProgressReport(eventName: "unpause")
|
||||||
while(vlcplayer.state != VLCMediaPlayerState.stopped) {
|
while(vlcplayer.state != VLCMediaPlayerState.stopped) {
|
||||||
_streamLoading.wrappedValue = false;
|
_streamLoading.wrappedValue = false;
|
||||||
while(vlcplayer.isPlaying) {
|
while(vlcplayer.isPlaying) {
|
||||||
vlcplayer.currentVideoSubTitleIndex = _selectedCaptionTrack.wrappedValue;
|
vlcplayer.currentVideoSubTitleIndex = _selectedCaptionTrack.wrappedValue;
|
||||||
usleep(500000)
|
usleep(500000)
|
||||||
if(CACurrentMediaTime() - lastProgressReportSent > 10) {
|
if(CACurrentMediaTime() - lastProgressReportSent > 10) {
|
||||||
sendProgressReport()
|
sendProgressReport(eventName: "timeupdate")
|
||||||
_lastProgressReportSent.wrappedValue = CACurrentMediaTime()
|
_lastProgressReportSent.wrappedValue = CACurrentMediaTime()
|
||||||
}
|
}
|
||||||
if(vlcplayer.time.intValue != 0) {
|
if(vlcplayer.time.intValue != 0) {
|
||||||
|
@ -129,12 +131,12 @@ struct VideoPlayerView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendProgressReport() {
|
func sendProgressReport(eventName: String) {
|
||||||
var progressBody: String = "";
|
var progressBody: String = "";
|
||||||
if(pbitem.videoType == VideoType.direct) {
|
if(pbitem.videoType == VideoType.direct) {
|
||||||
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":\(vlcplayer.state == VLCMediaPlayerState.paused ? "true" : "false"),\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[{\"start\":0,\"end\":569735888.888889}],\"PlayMethod\":\"DirectStream\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"EventName\":\"timeupdate\"}";
|
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":\(vlcplayer.state == VLCMediaPlayerState.paused ? "true" : "false"),\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":120000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":\(startTime),\"AudioStreamIndex\":\(selectedAudioTrack),\"BufferedRanges\":[{\"start\":0,\"end\":569735888.888889}],\"PlayMethod\":\"DirectStream\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem0\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"EventName\":\"\(eventName)\"}";
|
||||||
} else {
|
} else {
|
||||||
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":\(vlcplayer.state == VLCMediaPlayerState.paused ? "true" : "false"),\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[{\"start\":0,\"end\":569735888.888889}],\"PlayMethod\":\"Transcode\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"EventName\":\"timeupdate\"}";
|
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":\(vlcplayer.state == VLCMediaPlayerState.paused ? "true" : "false"),\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":120000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":\(startTime),\"AudioStreamIndex\":\(selectedAudioTrack),\"BufferedRanges\":[{\"start\":0,\"end\":569735888.888889}],\"PlayMethod\":\"Transcode\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem0\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"EventName\":\"\(eventName)\"}";
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = RestRequest(method: .post, url: (globalData.server?.baseURI ?? "") + "/Sessions/Playing/Progress")
|
let request = RestRequest(method: .post, url: (globalData.server?.baseURI ?? "") + "/Sessions/Playing/Progress")
|
||||||
|
@ -157,9 +159,9 @@ struct VideoPlayerView: View {
|
||||||
func sendStopReport() {
|
func sendStopReport() {
|
||||||
var progressBody: String = "";
|
var progressBody: String = "";
|
||||||
if(pbitem.videoType == VideoType.direct) {
|
if(pbitem.videoType == VideoType.direct) {
|
||||||
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":true,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[],\"PlayMethod\":\"\(pbitem.videoType == VideoType.direct ? "DirectStream" : "Transcode")\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem1\"}]}";
|
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":true,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":120000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":\(startTime),\"AudioStreamIndex\":\(selectedAudioTrack),\"BufferedRanges\":[],\"PlayMethod\":\"DirectStream\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem0\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem0\"}]}";
|
||||||
} else {
|
} else {
|
||||||
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":true,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[{\"start\":0,\"end\":100000}],\"PlayMethod\":\"Transcode\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem1\"}]}";
|
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":true,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":120000000,\"PositionTicks\":\(Int(vlcplayer.position * Float(item.RuntimeTicks))),\"PlaybackStartTimeTicks\":\(startTime),\"AudioStreamIndex\":\(selectedAudioTrack),\"BufferedRanges\":[{\"start\":0,\"end\":100000}],\"PlayMethod\":\"Transcode\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem0\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem0\"}]}";
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = RestRequest(method: .post, url: (globalData.server?.baseURI ?? "") + "/Sessions/Playing/Stopped")
|
let request = RestRequest(method: .post, url: (globalData.server?.baseURI ?? "") + "/Sessions/Playing/Stopped")
|
||||||
|
@ -171,6 +173,7 @@ struct VideoPlayerView: View {
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let resp):
|
case .success(let resp):
|
||||||
print(resp.body)
|
print(resp.body)
|
||||||
|
self.playing.wrappedValue = false;
|
||||||
break
|
break
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
debugPrint(error)
|
debugPrint(error)
|
||||||
|
@ -181,11 +184,13 @@ struct VideoPlayerView: View {
|
||||||
|
|
||||||
func sendPlayReport() {
|
func sendPlayReport() {
|
||||||
var progressBody: String = "";
|
var progressBody: String = "";
|
||||||
|
_startTime.wrappedValue = Int(Date().timeIntervalSince1970) * 10000000
|
||||||
if(pbitem.videoType == VideoType.hls) {
|
if(pbitem.videoType == VideoType.hls) {
|
||||||
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":false,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":0,\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[],\"PlayMethod\":\"Transcode\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem1\"}]}";
|
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":true,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":120000000,\"PositionTicks\":\(Int(item.Progress)),\"PlaybackStartTimeTicks\":\(startTime),\"AudioStreamIndex\":\(selectedAudioTrack),\"BufferedRanges\":[{\"start\":0,\"end\":100000}],\"PlayMethod\":\"Transcode\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem0\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem0\"}]}";
|
||||||
} else {
|
} else {
|
||||||
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":false,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":140000000,\"PositionTicks\":0,\"PlaybackStartTimeTicks\":16209515560670000,\"AudioStreamIndex\":1,\"BufferedRanges\":[],\"PlayMethod\":\"DirectStream\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem1\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem1\"}]}";
|
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":false,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":120000000,\"PositionTicks\":\(Int(item.Progress)),\"PlaybackStartTimeTicks\":\(startTime),\"AudioStreamIndex\":\(selectedAudioTrack),\"BufferedRanges\":[],\"PlayMethod\":\"DirectStream\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem0\",\"MediaSourceId\":\"\(item.Id)\",\"CanSeek\":true,\"ItemId\":\"\(item.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(item.Id)\",\"PlaylistItemId\":\"playlistItem0\"}]}";
|
||||||
}
|
}
|
||||||
|
print(progressBody)
|
||||||
|
|
||||||
let request = RestRequest(method: .post, url: (globalData.server?.baseURI ?? "") + "/Sessions/Playing")
|
let request = RestRequest(method: .post, url: (globalData.server?.baseURI ?? "") + "/Sessions/Playing")
|
||||||
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
||||||
|
@ -232,7 +237,7 @@ struct VideoPlayerView: View {
|
||||||
_playSessionId.wrappedValue = json["PlaySessionId"].string ?? "";
|
_playSessionId.wrappedValue = json["PlaySessionId"].string ?? "";
|
||||||
if(json["MediaSources"][0]["TranscodingUrl"].string != nil) {
|
if(json["MediaSources"][0]["TranscodingUrl"].string != nil) {
|
||||||
print("Transcoding!")
|
print("Transcoding!")
|
||||||
let streamURL: URL = URL(string: "\(globalData.server?.baseURI ?? "")\((json["MediaSources"][0]["TranscodingUrl"].string ?? "").replacingOccurrences(of: "master.m3u8", with: "main.m3u8"))")!
|
let streamURL: URL = URL(string: "\(globalData.server?.baseURI ?? "")\((json["MediaSources"][0]["TranscodingUrl"].string ?? ""))")!
|
||||||
let item = PlaybackItem(videoType: VideoType.hls, videoUrl: streamURL, subtitles: [])
|
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")
|
||||||
_subtitles.wrappedValue.append(disableSubtitleTrack);
|
_subtitles.wrappedValue.append(disableSubtitleTrack);
|
||||||
|
@ -348,7 +353,6 @@ struct VideoPlayerView: View {
|
||||||
HStack() {
|
HStack() {
|
||||||
Button() {
|
Button() {
|
||||||
sendStopReport()
|
sendStopReport()
|
||||||
self.playing.wrappedValue = false;
|
|
||||||
} label: {
|
} label: {
|
||||||
HStack() {
|
HStack() {
|
||||||
Image(systemName: "chevron.left").font(.system(size: 20)).foregroundColor(.white)
|
Image(systemName: "chevron.left").font(.system(size: 20)).foregroundColor(.white)
|
||||||
|
@ -381,11 +385,11 @@ struct VideoPlayerView: View {
|
||||||
if(vlcplayer.state != VLCMediaPlayerState.paused) {
|
if(vlcplayer.state != VLCMediaPlayerState.paused) {
|
||||||
vlcplayer.pause()
|
vlcplayer.pause()
|
||||||
playPauseButtonSystemName = "play"
|
playPauseButtonSystemName = "play"
|
||||||
sendProgressReport()
|
sendProgressReport(eventName: "pause")
|
||||||
} else {
|
} else {
|
||||||
vlcplayer.play()
|
vlcplayer.play()
|
||||||
playPauseButtonSystemName = "pause"
|
playPauseButtonSystemName = "pause"
|
||||||
sendProgressReport()
|
sendProgressReport(eventName: "unpause")
|
||||||
}
|
}
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: playPauseButtonSystemName).font(.system(size: 55)).foregroundColor(.white)
|
Image(systemName: playPauseButtonSystemName).font(.system(size: 55)).foregroundColor(.white)
|
||||||
|
@ -405,6 +409,7 @@ struct VideoPlayerView: View {
|
||||||
let videoDuration = Double(vlcplayer.time.intValue + abs(vlcplayer.remainingTime.intValue))
|
let videoDuration = Double(vlcplayer.time.intValue + abs(vlcplayer.remainingTime.intValue))
|
||||||
if(bool == true) {
|
if(bool == true) {
|
||||||
vlcplayer.pause()
|
vlcplayer.pause()
|
||||||
|
sendProgressReport(eventName: "pause")
|
||||||
DispatchQueue.global(qos: .utility).async { [self] in
|
DispatchQueue.global(qos: .utility).async { [self] in
|
||||||
self.processScrubbingState()
|
self.processScrubbingState()
|
||||||
}
|
}
|
||||||
|
@ -412,7 +417,7 @@ struct VideoPlayerView: View {
|
||||||
//Scrub is value from 0..1 - find position in video and add / or remove.
|
//Scrub is value from 0..1 - find position in video and add / or remove.
|
||||||
let secondsScrubbedTo = round(_scrub.wrappedValue * videoDuration);
|
let secondsScrubbedTo = round(_scrub.wrappedValue * videoDuration);
|
||||||
let offset = secondsScrubbedTo - videoPosition;
|
let offset = secondsScrubbedTo - videoPosition;
|
||||||
sendProgressReport()
|
sendProgressReport(eventName: "unpause")
|
||||||
vlcplayer.play()
|
vlcplayer.play()
|
||||||
if(offset > 0) {
|
if(offset > 0) {
|
||||||
vlcplayer.jumpForward(Int32(offset)/1000);
|
vlcplayer.jumpForward(Int32(offset)/1000);
|
||||||
|
|
Loading…
Reference in New Issue