External subtitles

Add external subtitles as tracks for direct play and direct stream.
Important to note, when direct streaming, the tracks are defined as
Unknown(external). There's no way to correct this.
This commit is contained in:
angelblue05 2015-08-24 05:55:37 -05:00
parent 475a671d08
commit 1691fd5e8b
4 changed files with 103 additions and 12 deletions

View file

@ -166,12 +166,6 @@ class PlayUtils():
elif "Video" in type: elif "Video" in type:
playurl = "%s/mediabrowser/Videos/%s/stream?static=true" % (server, id) playurl = "%s/mediabrowser/Videos/%s/stream?static=true" % (server, id)
# Verify audio and subtitles
mediaSources = result[u'MediaSources']
if mediaSources[0].get('DefaultAudioStreamIndex') != None:
playurl = "%s&AudioStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultAudioStreamIndex'))
if mediaSources[0].get('DefaultSubtitleStreamIndex') != None:
playurl = "%s&SubtitleStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultSubtitleStreamIndex'))
elif "Audio" in type: elif "Audio" in type:
playurl = "%s/mediabrowser/Audio/%s/stream.mp3" % (server, id) playurl = "%s/mediabrowser/Audio/%s/stream.mp3" % (server, id)

View file

@ -91,18 +91,21 @@ class PlaybackUtils():
return self.AddToPlaylist(itemsToPlay) return self.AddToPlaylist(itemsToPlay)
playurl = PlayUtils().getPlayUrl(server, id, result) playurl = PlayUtils().getPlayUrl(server, id, result)
if playurl == False or WINDOW.getProperty('playurlFalse') == "true": if playurl == False or WINDOW.getProperty('playurlFalse') == "true":
WINDOW.clearProperty('playurlFalse') WINDOW.clearProperty('playurlFalse')
xbmc.log("Failed to retrieve the playback path/url.") xbmc.log("Failed to retrieve the playback path/url.")
return return
if WINDOW.getProperty("%splaymethod" % playurl) == "Transcode": if WINDOW.getProperty("%splaymethod" % playurl) == "Transcode":
# Transcoding, we pull every track to set before playback starts
playurlprefs = self.audioSubsPref(playurl, result.get("MediaSources")) playurlprefs = self.audioSubsPref(playurl, result.get("MediaSources"))
if playurlprefs: if playurlprefs:
playurl = playurlprefs playurl = playurlprefs
else: # User cancelled dialog else: # User cancelled dialog
return return
thumbPath = API().getArtwork(result, "Primary") thumbPath = API().getArtwork(result, "Primary")
#if the file is a virtual strm file, we need to override the path by reading it's contents #if the file is a virtual strm file, we need to override the path by reading it's contents
@ -114,6 +117,13 @@ class PlaybackUtils():
listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath) listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath)
if WINDOW.getProperty("%splaymethod" % playurl) != "Transcode":
# Only for direct play and direct stream
# Append external subtitles to stream
subtitleList = self.externalSubs(id, playurl, server, result.get('MediaSources'))
listItem.setSubtitles(subtitleList)
#pass
# Can not play virtual items # Can not play virtual items
if (result.get("LocationType") == "Virtual"): if (result.get("LocationType") == "Virtual"):
xbmcgui.Dialog().ok(self.language(30128), self.language(30129)) xbmcgui.Dialog().ok(self.language(30128), self.language(30129))
@ -164,6 +174,38 @@ class PlaybackUtils():
else: else:
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem)
def externalSubs(self, id, playurl, server, mediaSources):
externalsubs = []
mapping = {}
mediaStream = mediaSources[0].get('MediaStreams')
kodiindex = 0
for stream in mediaStream:
index = stream['Index']
# Since Emby returns all possible tracks together, have to pull only external subtitles.
# IsTextSubtitleStream if true, is available to download from emby.
if "Subtitle" in stream['Type'] and stream['IsExternal'] and stream['IsTextSubtitleStream']:
playmethod = utils.window("%splaymethod" % playurl)
if "DirectPlay" in playmethod:
# Direct play, get direct path
url = PlayUtils().directPlay(stream)
elif "DirectStream" in playmethod: # Direct stream
url = "%s/Videos/%s/%s/Subtitles/%s/Stream.srt" % (server, id, id, index)
# map external subtitles for mapping
mapping[kodiindex] = index
externalsubs.append(url)
kodiindex += 1
mapping = json.dumps(mapping)
utils.window('%sIndexMapping' % playurl, mapping)
return externalsubs
def audioSubsPref(self, url, mediaSources): def audioSubsPref(self, url, mediaSources):
WINDOW = xbmcgui.Window(10000) WINDOW = xbmcgui.Window(10000)

View file

@ -211,8 +211,24 @@ class Player( xbmc.Player ):
# Convert back into an Emby index # Convert back into an Emby index
audioTracks = len(xbmc.Player().getAvailableAudioStreams()) audioTracks = len(xbmc.Player().getAvailableAudioStreams())
indexAudio = indexAudio + 1 indexAudio = indexAudio + 1
if subsEnabled and len(xbmc.Player().getAvailableSubtitleStreams()) > 0: if subsEnabled and len(xbmc.Player().getAvailableSubtitleStreams()) > 0:
indexSubs = indexSubs + audioTracks + 1 WINDOW = xbmcgui.Window(10000)
mapping = WINDOW.getProperty("%sIndexMapping" % currentFile)
externalIndex = json.loads(mapping)
if externalIndex:
# If there's external subtitles added via PlaybackUtils
if externalIndex.get(str(indexSubs)):
# If the current subtitle is in the mapping
indexSubs = externalIndex[str(indexSubs)]
else:
# Internal subtitle currently selected
external = len(externalIndex)
indexSubs = indexSubs - external + audioTracks + 1
else:
# No external subtitles added via PlayUtils
audioTracks = len(xbmc.Player().getAvailableAudioStreams())
indexSubs = indexSubs + audioTracks + 1
else: else:
indexSubs = "" indexSubs = ""
@ -292,6 +308,9 @@ class Player( xbmc.Player ):
refresh_id = WINDOW.getProperty(currentFile + "refresh_id") refresh_id = WINDOW.getProperty(currentFile + "refresh_id")
playMethod = WINDOW.getProperty(currentFile + "playmethod") playMethod = WINDOW.getProperty(currentFile + "playmethod")
itemType = WINDOW.getProperty(currentFile + "type") itemType = WINDOW.getProperty(currentFile + "type")
mapping = WINDOW.getProperty("%sIndexMapping" % currentFile)
self.logMsg("Mapping for index: %s" % mapping)
# Get playback volume # Get playback volume
volume_query = '{"jsonrpc": "2.0", "method": "Application.GetProperties", "params": {"properties": ["volume","muted"]}, "id": 1}' volume_query = '{"jsonrpc": "2.0", "method": "Application.GetProperties", "params": {"properties": ["volume","muted"]}, "id": 1}'
@ -304,6 +323,7 @@ class Player( xbmc.Player ):
url = "{server}/mediabrowser/Sessions/Playing" url = "{server}/mediabrowser/Sessions/Playing"
postdata = { postdata = {
'QueueableMediaTypes': "Video", 'QueueableMediaTypes': "Video",
'CanSeek': True, 'CanSeek': True,
'ItemId': item_id, 'ItemId': item_id,
@ -325,6 +345,7 @@ class Player( xbmc.Player ):
track_query = '{"jsonrpc": "2.0", "method": "Player.GetProperties", "params": {"playerid": 1,"properties": ["currentsubtitle","currentaudiostream","subtitleenabled"]} , "id": 1}' track_query = '{"jsonrpc": "2.0", "method": "Player.GetProperties", "params": {"playerid": 1,"properties": ["currentsubtitle","currentaudiostream","subtitleenabled"]} , "id": 1}'
result = xbmc.executeJSONRPC(track_query) result = xbmc.executeJSONRPC(track_query)
result = json.loads(result) result = json.loads(result)
# Audio tracks # Audio tracks
indexAudio = result.get('result', 0) indexAudio = result.get('result', 0)
if indexAudio: if indexAudio:
@ -337,11 +358,25 @@ class Player( xbmc.Player ):
subsEnabled = result.get('result', "") subsEnabled = result.get('result', "")
if subsEnabled: if subsEnabled:
subsEnabled = subsEnabled.get('subtitleenabled', "") subsEnabled = subsEnabled.get('subtitleenabled', "")
# Postdata for the audio and subs tracks # Postdata for the audio and subs tracks
audioTracks = len(xbmc.Player().getAvailableAudioStreams())
postdata['AudioStreamIndex'] = indexAudio + 1 postdata['AudioStreamIndex'] = indexAudio + 1
if subsEnabled and len(xbmc.Player().getAvailableSubtitleStreams()) > 0: if subsEnabled and len(xbmc.Player().getAvailableSubtitleStreams()) > 0:
audioTracks = len(xbmc.Player().getAvailableAudioStreams()) externalIndex = json.loads(mapping)
postdata['SubtitleStreamIndex'] = indexSubs + audioTracks + 1 if externalIndex:
# If there's external subtitles added via PlaybackUtils
if externalIndex.get(str(indexSubs)):
# If the current subtitle is in the mapping
postdata['SubtitleStreamIndex'] = externalIndex[str(indexSubs)]
else:
# Internal subtitle currently selected
external = len(externalIndex)
postdata['SubtitleStreamIndex'] = indexSubs - external + audioTracks + 1
else:
# No external subtitles added via PlayUtils
postdata['SubtitleStreamIndex'] = indexSubs + audioTracks + 1
else: else:
postdata['SubtitleStreamIndex'] = "" postdata['SubtitleStreamIndex'] = ""
@ -349,6 +384,7 @@ class Player( xbmc.Player ):
self.logMsg("Sending POST play started.", 1) self.logMsg("Sending POST play started.", 1)
self.doUtils.downloadUrl(url, postBody=postdata, type="POST") self.doUtils.downloadUrl(url, postBody=postdata, type="POST")
# save data map for updates and position calls # save data map for updates and position calls
data = { data = {
'runtime': runtime, 'runtime': runtime,

View file

@ -165,9 +165,28 @@ class WebSocketThread(threading.Thread):
xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % volume) xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % volume)
elif command == "SetSubtitleStreamIndex": elif command == "SetSubtitleStreamIndex":
# Emby merges audio and subtitle index together # Emby merges audio and subtitle index together
audioTracks = len(xbmc.Player().getAvailableAudioStreams()) xbmcplayer = xbmc.Player()
index = int(arguments['Index']) - audioTracks currentFile = xbmcplayer.getPlayingFile()
xbmc.Player().setSubtitleStream(index - 1) embyIndex = int(arguments['Index'])
mapping = WINDOW.getProperty("%sIndexMapping" % currentFile)
externalIndex = json.loads(mapping)
if externalIndex:
# If there's external subtitles added via PlaybackUtils
for index in externalIndex:
if externalIndex[index] == embyIndex:
xbmcplayer.setSubtitleStream(int(index))
else:
# User selected internal subtitles
external = len(externalIndex)
audioTracks = len(xbmcplayer.getAvailableAudioStreams())
xbmcplayer.setSubtitleStream(external + embyIndex - audioTracks - 1)
else:
# Emby merges audio and subtitle index together
audioTracks = len(xbmcplayer.getAvailableAudioStreams())
xbmcplayer.setSubtitleStream(index - audioTracks - 1)
elif command == "SetAudioStreamIndex": elif command == "SetAudioStreamIndex":
index = int(arguments['Index']) index = int(arguments['Index'])
xbmc.Player().setAudioStream(index - 1) xbmc.Player().setAudioStream(index - 1)