Transcoding up
This commit is contained in:
parent
e148090c3c
commit
125daea6ef
5 changed files with 82 additions and 94 deletions
|
@ -2065,9 +2065,9 @@ class API():
|
||||||
action 'DirectPlay', 'DirectStream' or 'Transcode'
|
action 'DirectPlay', 'DirectStream' or 'Transcode'
|
||||||
|
|
||||||
quality: {
|
quality: {
|
||||||
'videoResolution': 'resolution',
|
'videoResolution': e.g. '1024x768',
|
||||||
'videoQuality': 'quality',
|
'videoQuality': e.g. '60',
|
||||||
'maxVideoBitrate': 'bitrate'
|
'maxVideoBitrate': e.g. '2000' (in kbits)
|
||||||
}
|
}
|
||||||
(one or several of these options)
|
(one or several of these options)
|
||||||
subtitle {'selected', 'dontBurnIn', 'size'}
|
subtitle {'selected', 'dontBurnIn', 'size'}
|
||||||
|
@ -2081,47 +2081,26 @@ class API():
|
||||||
# Set Client capabilities
|
# Set Client capabilities
|
||||||
clientArgs = {
|
clientArgs = {
|
||||||
'X-Plex-Client-Capabilities':
|
'X-Plex-Client-Capabilities':
|
||||||
"protocols=shoutcast,"
|
'protocols='
|
||||||
"http-live-streaming,"
|
'shoutcast,'
|
||||||
"http-streaming-video,"
|
'http-video;'
|
||||||
"http-streaming-video-720p,"
|
'videoDecoders='
|
||||||
"http-streaming-video-1080p,"
|
'h264{profile:high&resolution:1080&level:51};'
|
||||||
"http-mp4-streaming,"
|
'audioDecoders='
|
||||||
"http-mp4-video,"
|
'mp3,aac,dts{bitrate:800000&channels:8},'
|
||||||
"http-mp4-video-720p,"
|
'ac3{bitrate:800000&channels:8}',
|
||||||
"http-mp4-video-1080p;"
|
'X-Plex-Client-Profile-Extra':
|
||||||
"videoDecoders="
|
'add-transcode-target-audio-codec'
|
||||||
"h264{profile:high&resolution:1080&level:51},"
|
'(type=videoProfile&'
|
||||||
"h265{profile:high&resolution:1080&level:51},"
|
'context=streaming&'
|
||||||
"mpeg1video,"
|
'protocol=*&'
|
||||||
"mpeg2video,"
|
'audioCodec=dca,ac3)'
|
||||||
"mpeg4,"
|
|
||||||
"msmpeg4,"
|
|
||||||
"mjpeg,"
|
|
||||||
"wmv2,"
|
|
||||||
"wmv3,"
|
|
||||||
"vc1,"
|
|
||||||
"cinepak,"
|
|
||||||
"h263;"
|
|
||||||
"audioDecoders="
|
|
||||||
"mp3,"
|
|
||||||
"aac,"
|
|
||||||
"ac3{bitrate:800000&channels:8},"
|
|
||||||
"dts{bitrate:800000&channels:8},"
|
|
||||||
"truehd,"
|
|
||||||
"eac3,"
|
|
||||||
"dca,"
|
|
||||||
"mp2,"
|
|
||||||
"pcm,"
|
|
||||||
"wmapro,"
|
|
||||||
"wmav2,"
|
|
||||||
"wmavoice,"
|
|
||||||
"wmalossless;"
|
|
||||||
}
|
}
|
||||||
path = self.item[0][self.part].attrib['key']
|
|
||||||
xargs = PlexAPI().getXArgsDeviceInfo()
|
xargs = PlexAPI().getXArgsDeviceInfo()
|
||||||
|
|
||||||
|
# For DirectPlay, path/key of PART is needed
|
||||||
if action == "DirectPlay":
|
if action == "DirectPlay":
|
||||||
|
path = self.item[0][self.part].attrib['key']
|
||||||
url = self.server + path
|
url = self.server + path
|
||||||
if '?' in url:
|
if '?' in url:
|
||||||
url += '&' + urlencode(xargs)
|
url += '&' + urlencode(xargs)
|
||||||
|
@ -2130,13 +2109,27 @@ class API():
|
||||||
return url
|
return url
|
||||||
|
|
||||||
# For Direct Streaming or Transcoding
|
# For Direct Streaming or Transcoding
|
||||||
|
# Path/key to VIDEO item of xml PMS response is needed, not part
|
||||||
|
path = self.item.attrib['key']
|
||||||
|
# transcodePath = self.server + \
|
||||||
|
# '/video/:/transcode/universal/start.m3u8?'
|
||||||
transcodePath = self.server + \
|
transcodePath = self.server + \
|
||||||
'/video/:/transcode/universal/start.m3u8?'
|
'/video/:/transcode/universal/start.mkv?'
|
||||||
|
# args = {
|
||||||
|
# 'path': path,
|
||||||
|
# 'mediaIndex': 0, # Probably refering to XML reply sheme
|
||||||
|
# 'partIndex': self.part,
|
||||||
|
# 'protocol': 'hls', # seen in the wild: 'dash', 'http', 'hls'
|
||||||
|
# 'offset': 0, # Resume point
|
||||||
|
# 'fastSeek': 1
|
||||||
|
# }
|
||||||
args = {
|
args = {
|
||||||
|
'copyts': 1,
|
||||||
'path': path,
|
'path': path,
|
||||||
'mediaIndex': 0, # Probably refering to XML reply sheme
|
'mediaIndex': 0, # Probably refering to XML reply sheme
|
||||||
'partIndex': self.part,
|
'partIndex': self.part,
|
||||||
'protocol': 'hls', # seen in the wild: 'dash', 'http', 'hls'
|
'protocol': 'http', # seen in the wild: 'dash', 'http', 'hls'
|
||||||
|
'session': self.clientId,
|
||||||
'offset': 0, # Resume point
|
'offset': 0, # Resume point
|
||||||
'fastSeek': 1
|
'fastSeek': 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,7 +232,6 @@ class Items(object):
|
||||||
Updates the Kodi watched state of the item from PMS. Also retrieves
|
Updates the Kodi watched state of the item from PMS. Also retrieves
|
||||||
Plex resume points for movies in progress.
|
Plex resume points for movies in progress.
|
||||||
"""
|
"""
|
||||||
self.logMsg("Entering updateUserdata", 1)
|
|
||||||
for mediaitem in xml:
|
for mediaitem in xml:
|
||||||
API = PlexAPI.API(mediaitem)
|
API = PlexAPI.API(mediaitem)
|
||||||
itemid = API.getRatingKey()
|
itemid = API.getRatingKey()
|
||||||
|
@ -300,8 +299,7 @@ class Movies(Items):
|
||||||
movieid = emby_dbitem[0]
|
movieid = emby_dbitem[0]
|
||||||
fileid = emby_dbitem[1]
|
fileid = emby_dbitem[1]
|
||||||
pathid = emby_dbitem[2]
|
pathid = emby_dbitem[2]
|
||||||
self.logMsg("movieid: %s fileid: %s pathid: %s" % (movieid, fileid, pathid), 1)
|
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
update_item = False
|
update_item = False
|
||||||
self.logMsg("movieid: %s not found." % itemid, 2)
|
self.logMsg("movieid: %s not found." % itemid, 2)
|
||||||
|
@ -911,10 +909,8 @@ class TVShows(Items):
|
||||||
try:
|
try:
|
||||||
showid = emby_dbitem[0]
|
showid = emby_dbitem[0]
|
||||||
pathid = emby_dbitem[2]
|
pathid = emby_dbitem[2]
|
||||||
self.logMsg("showid: %s pathid: %s" % (showid, pathid), 1)
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
update_item = False
|
update_item = False
|
||||||
self.logMsg("showid: %s not found." % itemid, 2)
|
|
||||||
|
|
||||||
self.logMsg("View tag found: %s" % viewtag, 2)
|
self.logMsg("View tag found: %s" % viewtag, 2)
|
||||||
|
|
||||||
|
|
|
@ -189,9 +189,8 @@ class ThreadedShowSyncInfo(threading.Thread):
|
||||||
try:
|
try:
|
||||||
dialog.update(
|
dialog.update(
|
||||||
percentage,
|
percentage,
|
||||||
message="Downloaded: %s, Processed: %s: %s"
|
message="Downloaded: %s, Processed: %s"
|
||||||
% (getMetadataProgress, processMetadataProgress,
|
% (getMetadataProgress, processMetadataProgress))
|
||||||
viewName))
|
|
||||||
except:
|
except:
|
||||||
# Wierd formating of the string viewName?!?
|
# Wierd formating of the string viewName?!?
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -102,11 +102,10 @@ class PlaybackUtils():
|
||||||
|
|
||||||
# Get playurls per part and process them
|
# Get playurls per part and process them
|
||||||
listitems = []
|
listitems = []
|
||||||
for playurl in playutils.getPlayUrl():
|
for counter, playurl in enumerate(playutils.getPlayUrl()):
|
||||||
# Add item via Kodi db, if found. Preserves metadata
|
# Add item via Kodi db, if found. Preserves metadata
|
||||||
emby_dbitem = emby_db.getItem_byId(self.API.getRatingKey())
|
emby_dbitem = emby_db.getItem_byId(self.API.getRatingKey())
|
||||||
if emby_dbitem:
|
if emby_dbitem:
|
||||||
self.logMsg('emby_dbitem found', 1)
|
|
||||||
kodi_id = emby_dbitem[0]
|
kodi_id = emby_dbitem[0]
|
||||||
media_type = emby_dbitem[4]
|
media_type = emby_dbitem[4]
|
||||||
pl.insertintoPlaylist(
|
pl.insertintoPlaylist(
|
||||||
|
@ -121,32 +120,33 @@ class PlaybackUtils():
|
||||||
self.logMsg('emby_dbitem not found. Plex ratingKey was %s'
|
self.logMsg('emby_dbitem not found. Plex ratingKey was %s'
|
||||||
% self.API.getRatingKey(), 1)
|
% self.API.getRatingKey(), 1)
|
||||||
listitem = xbmcgui.ListItem()
|
listitem = xbmcgui.ListItem()
|
||||||
# Set artwork
|
self.setArtwork(listitem)
|
||||||
self.setProperties(playurl, listitem)
|
|
||||||
# Set metadata
|
|
||||||
self.setListItem(listitem)
|
self.setListItem(listitem)
|
||||||
self.playlist.add(
|
self.playlist.add(
|
||||||
playurl, listitem, index=self.currentPosition)
|
playurl, listitem, index=self.currentPosition)
|
||||||
|
|
||||||
|
playmethod = utils.window('emby_%s.playmethod' % playurl)
|
||||||
|
|
||||||
# For transcoding only, ask for audio/subs pref
|
# For transcoding only, ask for audio/subs pref
|
||||||
if utils.window('emby_%s.playmethod' % playurl) == "Transcode":
|
if playmethod == "Transcode":
|
||||||
playurl = playutils.audioSubsPref(playurl, listitem)
|
utils.window('emby_%s.playmethod' % playurl, clear=True)
|
||||||
|
playurl = playutils.audioSubsPref(
|
||||||
|
playurl, listitem, part=counter)
|
||||||
utils.window('emby_%s.playmethod' % playurl, value="Transcode")
|
utils.window('emby_%s.playmethod' % playurl, value="Transcode")
|
||||||
|
|
||||||
|
self.setProperties(playurl, listitem)
|
||||||
# Update the playurl to the PMS xml response (hence no loop)
|
# Update the playurl to the PMS xml response (hence no loop)
|
||||||
listitem.setPath(playurl)
|
listitem.setPath(playurl)
|
||||||
|
|
||||||
|
# Append external subtitles to stream
|
||||||
|
# Only for direct play and direct stream
|
||||||
|
if playmethod != "Transcode":
|
||||||
|
# Direct play automatically appends external
|
||||||
|
listitem.setSubtitles(self.API.externalSubs(playurl))
|
||||||
|
|
||||||
listitems.append(listitem)
|
listitems.append(listitem)
|
||||||
self.currentPosition += 1
|
self.currentPosition += 1
|
||||||
|
|
||||||
# We need to keep track of playQueueItemIDs for Plex Companion
|
|
||||||
playQueueItemID = self.API.GetPlayQueueItemID()
|
|
||||||
utils.window(
|
|
||||||
'plex_%s.playQueueItemID' % playurl, playQueueItemID)
|
|
||||||
utils.window(
|
|
||||||
'plex_%s.playlistPosition'
|
|
||||||
% playurl, str(self.currentPosition))
|
|
||||||
|
|
||||||
return listitems
|
return listitems
|
||||||
|
|
||||||
def setProperties(self, playurl, listitem):
|
def setProperties(self, playurl, listitem):
|
||||||
|
@ -160,23 +160,20 @@ class PlaybackUtils():
|
||||||
utils.window('%s.type' % embyitem, value=itemtype)
|
utils.window('%s.type' % embyitem, value=itemtype)
|
||||||
utils.window('%s.itemid' % embyitem, value=itemid)
|
utils.window('%s.itemid' % embyitem, value=itemid)
|
||||||
|
|
||||||
|
# We need to keep track of playQueueItemIDs for Plex Companion
|
||||||
|
playQueueItemID = self.API.GetPlayQueueItemID()
|
||||||
|
utils.window(
|
||||||
|
'plex_%s.playQueueItemID' % playurl, playQueueItemID)
|
||||||
|
utils.window(
|
||||||
|
'plex_%s.playlistPosition'
|
||||||
|
% playurl, str(self.currentPosition))
|
||||||
|
|
||||||
if itemtype == "episode":
|
if itemtype == "episode":
|
||||||
utils.window('%s.refreshid' % embyitem,
|
utils.window('%s.refreshid' % embyitem,
|
||||||
value=self.API.getParentRatingKey())
|
value=self.API.getParentRatingKey())
|
||||||
else:
|
else:
|
||||||
utils.window('%s.refreshid' % embyitem, value=itemid)
|
utils.window('%s.refreshid' % embyitem, value=itemid)
|
||||||
|
|
||||||
# Append external subtitles to stream
|
|
||||||
playmethod = utils.window('%s.playmethod' % embyitem)
|
|
||||||
# Only for direct play and direct stream
|
|
||||||
# subtitles = self.externalSubs(playurl)
|
|
||||||
subtitles = self.API.externalSubs(playurl)
|
|
||||||
if playmethod != "Transcode":
|
|
||||||
# Direct play automatically appends external
|
|
||||||
listitem.setSubtitles(subtitles)
|
|
||||||
|
|
||||||
self.setArtwork(listitem)
|
|
||||||
|
|
||||||
def externalSubs(self, playurl):
|
def externalSubs(self, playurl):
|
||||||
|
|
||||||
externalsubs = []
|
externalsubs = []
|
||||||
|
@ -290,8 +287,7 @@ class PlaybackUtils():
|
||||||
'dateadded': API.getDateCreated(),
|
'dateadded': API.getDateCreated(),
|
||||||
'lastplayed': userdata['LastPlayedDate'],
|
'lastplayed': userdata['LastPlayedDate'],
|
||||||
'mpaa': API.getMpaa(),
|
'mpaa': API.getMpaa(),
|
||||||
'aired': API.getPremiereDate(),
|
'aired': API.getPremiereDate()
|
||||||
'votes': None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if "Episode" in mediaType:
|
if "Episode" in mediaType:
|
||||||
|
|
|
@ -276,7 +276,7 @@ class PlayUtils():
|
||||||
# max bit rate supported by server (max signed 32bit integer)
|
# max bit rate supported by server (max signed 32bit integer)
|
||||||
return bitrate.get(videoQuality, 2147483)
|
return bitrate.get(videoQuality, 2147483)
|
||||||
|
|
||||||
def audioSubsPref(self, url, listitem, child=0):
|
def audioSubsPref(self, url, listitem, part=None):
|
||||||
# For transcoding only
|
# For transcoding only
|
||||||
# Present the list of audio to select from
|
# Present the list of audio to select from
|
||||||
audioStreamsList = {}
|
audioStreamsList = {}
|
||||||
|
@ -289,42 +289,46 @@ class PlayUtils():
|
||||||
selectSubsIndex = ""
|
selectSubsIndex = ""
|
||||||
playurlprefs = "%s" % url
|
playurlprefs = "%s" % url
|
||||||
|
|
||||||
|
# Set part where we're at
|
||||||
|
self.API.setPartNumber(part)
|
||||||
item = self.item
|
item = self.item
|
||||||
try:
|
try:
|
||||||
mediasources = item['MediaSources'][0]
|
mediasources = item[0]
|
||||||
mediastreams = mediasources['MediaStreams']
|
mediastreams = mediasources[part]
|
||||||
except (TypeError, KeyError, IndexError):
|
except (TypeError, KeyError, IndexError):
|
||||||
return
|
return
|
||||||
|
|
||||||
for stream in mediastreams:
|
for stream in mediastreams:
|
||||||
# Since Emby returns all possible tracks together, have to sort them.
|
# Since Emby returns all possible tracks together, have to sort them.
|
||||||
index = stream['Index']
|
index = stream['index']
|
||||||
type = stream['Type']
|
type = stream['streamType']
|
||||||
|
|
||||||
if 'Audio' in type:
|
# Audio
|
||||||
codec = stream['Codec']
|
if type == "2":
|
||||||
channelLayout = stream.get('ChannelLayout', "")
|
codec = stream['codec']
|
||||||
|
channelLayout = stream.get('audioChannelLayout', "")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
track = "%s - %s - %s %s" % (index, stream['Language'], codec, channelLayout)
|
track = "%s - %s - %s %s" % (index, stream['language'], codec, channelLayout)
|
||||||
except:
|
except:
|
||||||
track = "%s - %s %s" % (index, codec, channelLayout)
|
track = "%s - %s %s" % (index, codec, channelLayout)
|
||||||
|
|
||||||
audioStreamsChannelsList[index] = stream['Channels']
|
audioStreamsChannelsList[index] = stream['channels']
|
||||||
audioStreamsList[track] = index
|
audioStreamsList[track] = index
|
||||||
audioStreams.append(track)
|
audioStreams.append(track)
|
||||||
|
|
||||||
elif 'Subtitle' in type:
|
# Subtitles
|
||||||
|
elif type == "3":
|
||||||
'''if stream['IsExternal']:
|
'''if stream['IsExternal']:
|
||||||
continue'''
|
continue'''
|
||||||
try:
|
try:
|
||||||
track = "%s - %s" % (index, stream['Language'])
|
track = "%s - %s" % (index, stream['language'])
|
||||||
except:
|
except:
|
||||||
track = "%s - %s" % (index, stream['Codec'])
|
track = "%s - %s" % (index, stream['codec'])
|
||||||
|
|
||||||
default = stream['IsDefault']
|
default = stream.get('default', None)
|
||||||
forced = stream['IsForced']
|
forced = stream.get('forced', None)
|
||||||
downloadable = stream['IsTextSubtitleStream']
|
downloadable = True if stream.get('format', None) else False
|
||||||
|
|
||||||
if default:
|
if default:
|
||||||
track = "%s - Default" % track
|
track = "%s - Default" % track
|
||||||
|
|
Loading…
Reference in a new issue