Merge pull request #781 from jimdogx/jf-video-stats

Jf video stats
This commit is contained in:
1hitsong 2022-09-23 08:20:02 -04:00 committed by GitHub
commit 1832dfd0d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 238 additions and 17 deletions

View File

@ -134,6 +134,9 @@ function onKeyEvent(key as string, press as boolean) as boolean
if m.top.Subtitles.count() and key = "down"
m.top.selectSubtitlePressed = true
return true
else if key = "up"
m.top.selectPlaybackInfoPressed = true
return true
end if
return false

View File

@ -3,6 +3,7 @@
<interface>
<field id="backPressed" type="boolean" alwaysNotify="true" />
<field id="selectSubtitlePressed" type="boolean" alwaysNotify="true" />
<field id="selectPlaybackInfoPressed" type="boolean" alwaysNotify="true" />
<field id="PlaySessionId" type="string" />
<field id="Subtitles" type="array" />
<field id="SelectedSubtitle" type="integer" />

View File

@ -738,5 +738,83 @@
<translation>Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.</translation>
<extracomment>Settings Menu - Description for option</extracomment>
</message>
<message>
<source>Playback Information</source>
<translation>Playback Information</translation>
</message>
<message>
<source>Transcoding Information</source>
<translation>Transcoding Information</translation>
</message>
<message>
<source>Reason</source>
<translation>Reason</translation>
</message>
<message>
<source>Video Codec</source>
<translation>Video Codec</translation>
</message>
<message>
<source>Audio Codec</source>
<translation>Audio Codec</translation>
</message>
<message>
<source>direct</source>
<translation>direct</translation>
</message>
<message>
<source>Total Bitrate</source>
<translation>Total Bitrate</translation>
</message>
<message>
<source>Audio Channels</source>
<translation>Audio Channels</translation>
</message>
<message>
<source>Stream Information</source>
<translation>Stream Information</translation>
</message>
<message>
<source>Codec</source>
<translation>Codec</translation>
</message>
<message>
<source>Codec Tag</source>
<translation>Codec Tag</translation>
</message>
<message>
<source>Level</source>
<translation>Level</translation>
<extracomment>Video profile level</extracomment>
</message>
<message>
<source>Bit Rate</source>
<translation>Bit Rate</translation>
<extracomment>Video streaming bit rate</extracomment>
</message>
<message>
<source>Container</source>
<translation>Container</translation>
<extracomment>Video streaming container</extracomment>
</message>
<message>
<source>Size</source>
<translation>Size</translation>
<extracomment>Video size</extracomment>
</message>
<message>
<source>Video range type</source>
<translation>Video range type</translation>
</message>
<message>
<source>Pixel format</source>
<translation>Pixel format</translation>
<extracomment>Video pixel format</extracomment>
</message>
<message>
<source>WxH</source>
<translation>WxH</translation>
<extracomment>Video width x height</extracomment>
</message>
</context>
</TS>

View File

@ -385,6 +385,12 @@ sub Main (args as dynamic) as void
changeSubtitleDuringPlayback(trackSelected)
end if
end if
else if isNodeEvent(msg, "selectPlaybackInfoPressed")
node = m.scene.focusedChild
if node.focusedChild <> invalid and node.focusedChild.isSubType("JFVideo")
info = GetPlaybackInfo()
show_dialog(tr("Playback Information"), info)
end if
else if isNodeEvent(msg, "state")
node = msg.getRoSGNode()
if selectedItem.Type = "TvChannel" and node.state = "finished"

View File

@ -467,6 +467,7 @@ function CreateVideoPlayerGroup(video_id, mediaSourceId = invalid, audio_stream_
if video = invalid then return invalid
if video.errorMsg = "introaborted" then return video
video.observeField("selectSubtitlePressed", m.port)
video.observeField("selectPlaybackInfoPressed", m.port)
video.observeField("state", m.port)
return video

View File

@ -170,18 +170,18 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
end if
if meta.live then mediaSourceId = "" ' Don't send mediaSourceId for Live media
playbackInfo = ItemPostPlaybackInfo(video.id, mediaSourceId, audio_stream_idx, subtitle_idx, playbackPosition)
m.playbackInfo = ItemPostPlaybackInfo(video.id, mediaSourceId, audio_stream_idx, subtitle_idx, playbackPosition)
video.videoId = video.id
video.mediaSourceId = mediaSourceId
video.audioIndex = audio_stream_idx
if playbackInfo = invalid
if m.playbackInfo = invalid
video.content = invalid
return
end if
params = {}
video.PlaySessionId = playbackInfo.PlaySessionId
video.PlaySessionId = m.playbackInfo.PlaySessionId
if meta.live
video.content.live = true
@ -190,17 +190,17 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
video.container = getContainerType(meta)
if playbackInfo.MediaSources[0] = invalid
playbackInfo = meta.json
if m.playbackInfo.MediaSources[0] = invalid
m.playbackInfo = meta.json
end if
subtitles = sortSubtitles(meta.id, playbackInfo.MediaSources[0].MediaStreams)
subtitles = sortSubtitles(meta.id, m.playbackInfo.MediaSources[0].MediaStreams)
video.Subtitles = subtitles["all"]
if meta.live
video.transcodeParams = {
"MediaSourceId": playbackInfo.MediaSources[0].Id,
"LiveStreamId": playbackInfo.MediaSources[0].LiveStreamId,
"MediaSourceId": m.playbackInfo.MediaSources[0].Id,
"LiveStreamId": m.playbackInfo.MediaSources[0].LiveStreamId,
"PlaySessionId": video.PlaySessionId
}
end if
@ -209,7 +209,7 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
' 'TODO: allow user selection of subtitle track before playback initiated, for now set to no subtitles
video.directPlaySupported = playbackInfo.MediaSources[0].SupportsDirectPlay
video.directPlaySupported = m.playbackInfo.MediaSources[0].SupportsDirectPlay
fully_external = false
@ -218,8 +218,8 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
' artifacts. If the user preference is set, and the only reason the server says we need to
' transcode is that the Envoding Level is not supported, then try to direct play but silently
' fall back to the transcode if that fails.
if meta.live = false and get_user_setting("playback.tryDirect.h264ProfileLevel") = "true" and playbackInfo.MediaSources[0].TranscodingUrl <> invalid and forceTranscoding = false and playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
transcodingReasons = getTranscodeReasons(playbackInfo.MediaSources[0].TranscodingUrl)
if meta.live = false and get_user_setting("playback.tryDirect.h264ProfileLevel") = "true" and m.playbackInfo.MediaSources[0].TranscodingUrl <> invalid and forceTranscoding = false and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
transcodingReasons = getTranscodeReasons(m.playbackInfo.MediaSources[0].TranscodingUrl)
if transcodingReasons.Count() = 1 and transcodingReasons[0] = "VideoLevelNotSupported"
video.directPlaySupported = true
video.transcodeAvailable = true
@ -227,10 +227,10 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
end if
if video.directPlaySupported
protocol = LCase(playbackInfo.MediaSources[0].Protocol)
protocol = LCase(m.playbackInfo.MediaSources[0].Protocol)
if protocol <> "file"
uriRegex = CreateObject("roRegex", "^(.*:)//([A-Za-z0-9\-\.]+)(:[0-9]+)?(.*)$", "")
uri = uriRegex.Match(playbackInfo.MediaSources[0].Path)
uri = uriRegex.Match(m.playbackInfo.MediaSources[0].Path)
' proto $1, host $2, port $3, the-rest $4
localhost = CreateObject("roRegex", "^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$", "i")
' https://stackoverflow.com/questions/8426171/what-regex-will-match-all-loopback-addresses
@ -241,7 +241,7 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
video.content.url = buildURL(uri[4])
else
fully_external = true
video.content.url = playbackInfo.MediaSources[0].Path
video.content.url = m.playbackInfo.MediaSources[0].Path
end if
else:
params.append({
@ -258,15 +258,15 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
end if
video.isTranscoded = false
else
if playbackInfo.MediaSources[0].TranscodingUrl = invalid
if m.playbackInfo.MediaSources[0].TranscodingUrl = invalid
' If server does not provide a transcode URL, display a message to the user
m.global.sceneManager.callFunc("userMessage", tr("Error Getting Playback Information"), tr("An error was encountered while playing this item. Server did not provide required transcoding data."))
video.content = invalid
return
end if
' Get transcoding reason
video.transcodeReasons = getTranscodeReasons(playbackInfo.MediaSources[0].TranscodingUrl)
video.content.url = buildURL(playbackInfo.MediaSources[0].TranscodingUrl)
video.transcodeReasons = getTranscodeReasons(m.playbackInfo.MediaSources[0].TranscodingUrl)
video.content.url = buildURL(m.playbackInfo.MediaSources[0].TranscodingUrl)
video.isTranscoded = true
end if
@ -435,3 +435,135 @@ sub autoPlayNextEpisode(videoID as string, showID as string)
m.global.sceneManager.callFunc("popScene")
end if
end sub
' Returns an array of playback info to be displayed during playback.
' In the future, with a custom playback info view, we can return an associated array.
function GetPlaybackInfo()
sessions = api_API().sessions.get()
if sessions <> invalid and sessions.Count() > 0
return GetTranscodingStats(sessions[0])
end if
errMsg = tr("Unable to get playback information")
return [errMsg]
end function
function GetTranscodingStats(session)
sessionStats = []
if isValid(session.TranscodingInfo) and session.TranscodingInfo.Count() > 0
transcodingReasons = session.TranscodingInfo.TranscodeReasons
videoCodec = session.TranscodingInfo.VideoCodec
audioCodec = session.TranscodingInfo.AudioCodec
totalBitrate = session.TranscodingInfo.Bitrate
audioChannels = session.TranscodingInfo.AudioChannels
if isValid(transcodingReasons) and transcodingReasons.Count() > 0
sessionStats.push("** " + tr("Transcoding Information") + " **")
for each item in transcodingReasons
sessionStats.push(tr("Reason") + ": " + item)
end for
end if
if isValid(videoCodec)
data = tr("Video Codec") + ": " + videoCodec
if session.TranscodingInfo.IsVideoDirect
data = data + " (" + tr("direct") + ")"
end if
sessionStats.push(data)
end if
if isValid(audioCodec)
data = tr("Audio Codec") + ": " + audioCodec
if session.TranscodingInfo.IsAudioDirect
data = data + " (" + tr("direct") + ")"
end if
sessionStats.push(data)
end if
if isValid(totalBitrate)
data = tr("Total Bitrate") + ": " + getDisplayBitrate(totalBitrate)
sessionStats.push(data)
end if
if isValid(audioChannels)
data = tr("Audio Channels") + ": " + Str(audioChannels)
sessionStats.push(data)
end if
end if
if havePlaybackInfo()
stream = m.playbackInfo.mediaSources[0].MediaStreams[0]
sessionStats.push("** " + tr("Stream Information") + " **")
if isValid(stream.Container)
data = tr("Container") + ": " + stream.Container
sessionStats.push(data)
end if
if isValid(stream.Size)
data = tr("Size") + ": " + stream.Size
sessionStats.push(data)
end if
if isValid(stream.BitRate)
data = tr("Bit Rate") + ": " + getDisplayBitrate(stream.BitRate)
sessionStats.push(data)
end if
if isValid(stream.Codec)
data = tr("Codec") + ": " + stream.Codec
sessionStats.push(data)
end if
if isValid(stream.CodecTag)
data = tr("Codec Tag") + ": " + stream.CodecTag
sessionStats.push(data)
end if
if isValid(stream.VideoRangeType)
data = tr("Video range type") + ": " + stream.VideoRangeType
sessionStats.push(data)
end if
if isValid(stream.PixelFormat)
data = tr("Pixel format") + ": " + stream.PixelFormat
sessionStats.push(data)
end if
if isValid(stream.Width) and isValid(stream.Height)
data = tr("WxH") + ": " + Str(stream.Width) + " x " + Str(stream.Height)
sessionStats.push(data)
end if
if isValid(stream.Level)
data = tr("Level") + ": " + Str(stream.Level)
sessionStats.push(data)
end if
end if
return sessionStats
end function
function havePlaybackInfo()
if not isValid(m.playbackInfo)
return false
end if
if not isValid(m.playbackInfo.mediaSources)
return false
end if
if m.playbackInfo.mediaSources.Count() <= 0
return false
end if
if not isValid(m.playbackInfo.mediaSources[0].MediaStreams)
return false
end if
if m.playbackInfo.mediaSources[0].MediaStreams.Count() <= 0
return false
end if
return true
end function
function getDisplayBitrate(bitrate)
if bitrate > 1000000
return Str(Fix(bitrate / 1000000)) + " Mbps"
else
return Str(Fix(bitrate / 1000)) + " Kbps"
end if
end function