From ecaaa11debc81602fdcd871220a6517870b49171 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Thu, 6 Aug 2015 03:09:45 -0500 Subject: [PATCH] Added audio/sub selection for transcoding Also fixed transcoding not terminating as it should and leaving the ffmpeg running. --- resources/lib/PlayUtils.py | 113 +-------------------------------- resources/lib/PlaybackUtils.py | 93 ++++++++++++++++++++++----- resources/lib/Player.py | 102 +++++++++++++++-------------- 3 files changed, 132 insertions(+), 176 deletions(-) diff --git a/resources/lib/PlayUtils.py b/resources/lib/PlayUtils.py index 7d7e8f90..69bc92a7 100644 --- a/resources/lib/PlayUtils.py +++ b/resources/lib/PlayUtils.py @@ -210,11 +210,6 @@ class PlayUtils(): deviceId = self.clientInfo.getMachineId() playurl = "%s/mediabrowser/Videos/%s/master.m3u8?mediaSourceId=%s" % (server, id, id) playurl = "%s&VideoCodec=h264&AudioCodec=aac,ac3&deviceId=%s&VideoBitrate=%s" % (playurl, deviceId, self.getVideoBitRate()*1000) - - mediaSources = result[u'MediaSources'] - prefs = self.audioSubsPref(mediaSources) - - playurl = "%s%s" % (playurl, prefs) self.logMsg("Playurl: %s" % playurl) return playurl @@ -312,110 +307,4 @@ class PlayUtils(): return True else: self.logMsg("Path is detected as follow: %s. Try direct streaming." % path, 2) - return False - - def audioSubsPref(self, mediaSources): - - addon = xbmcaddon.Addon() - - defaultAudio = mediaSources[0][u'DefaultAudioStreamIndex'] - playurlprefs = "&AudioStreamIndex=%s" % defaultAudio - - codecs = [ - # Possible codecs - u'und', u'ac3', u'dts', u'5.1', u'aac', u'mp3', u'dca' - ] - - try: - mediaStream = mediaSources[0].get('MediaStreams') - audiotracks = {} - substracks = {} - defaultSubs = None - - for stream in mediaStream: - # Since Emby returns all possible tracks together, have to sort them. - if u'Audio' in stream[u'Type']: - if u'Language' in stream: - audiotracks[stream[u'Language']] = stream[u'Index'] - else: - audiotracks[stream[u'Codec']] = stream[u'Index'] - - if u'Subtitle' in stream[u'Type']: - if u'Language' in stream: - substracks[stream[u'Language']] = stream[u'Index'] - if stream[u'IsDefault'] == True: - defaultSubs = stream[u'Language'] - else: - substracks[stream[u'Codec']] = stream[u'Index'] - if stream[u'IsDefault']: - defaultSubs = stream[u'Codec'] - - self.logMsg("%s %s %s" % (defaultSubs, audiotracks, substracks), 1) - - if len(audiotracks) == 1 and len(substracks) == 0: - # There's only one audio track and no subtitles - playurlprefs = "&AudioStreamIndex=%s" % defaultAudio - return playurlprefs - - codec_intrack = False - for codec in codecs: - for track in audiotracks: - if codec in track: - codec_intrack = True - - if self.audioPref in audiotracks: - self.logMsg("Door 1", 2) - # Audio pref is available - playurlprefs = "&AudioStreamIndex=%s" % audiotracks[self.audioPref] - - if addon.getSetting('subsoverride') == "true": - # Subs are forced. - if self.subsPref in substracks: - self.logMsg("Door 1.1", 2) - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[self.subsPref]) - else: - # Use default subs - if defaultSubs != None: - self.logMsg("Door 1.2", 2) - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[defaultSubs]) - - elif (len(audiotracks) == 1) and not codec_intrack: - self.logMsg("Door 2", 2) - # 1. There's one audio track. - # 2. The audio is defined as a language. - # 3. Audio pref is not available, guaranteed. - playurlprefs = "&AudioStreamIndex=%s" % defaultAudio - - if self.subsPref in substracks: - self.logMsg("Door 2.1", 2) - # Subs pref is available. - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[self.subsPref]) - else: - # Use default subs - if defaultSubs != None: - self.logMsg("Door 2.2", 2) - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[defaultSubs]) - - elif len(audiotracks) == 1 and codec_intrack: - self.logMsg("Door 3", 2) - # 1. There one audio track. - # 2. The audio is undefined or a codec. - # 3. Audio track is mislabeled. - playurlprefs = "&AudioStreamIndex=%s" % defaultAudio - - if self.subsPref in substracks: - # If the subtitle is available, only display - # if the setting is enabled. - if addon.getSetting('subsoverride') == "true": - # Subs are forced. - self.logMsg("Door 3.1", 2) - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[self.subsPref]) - else: - # Use default subs - if defaultSubs != None: - self.logMsg("Door 3.2", 2) - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[defaultSubs]) - - except: pass - - return playurlprefs \ No newline at end of file + return False \ No newline at end of file diff --git a/resources/lib/PlaybackUtils.py b/resources/lib/PlaybackUtils.py index 6a3be4e2..b6a85329 100644 --- a/resources/lib/PlaybackUtils.py +++ b/resources/lib/PlaybackUtils.py @@ -97,6 +97,13 @@ class PlaybackUtils(): xbmc.log("Failed to retrieve the playback path/url.") return + if WINDOW.getProperty("%splaymethod" % playurl) == "Transcode": + playurlprefs = self.audioSubsPref(playurl, result.get("MediaSources")) + if playurlprefs: + playurl = playurlprefs + else: # User cancelled dialog + return + thumbPath = API().getArtwork(result, "Primary") #if the file is a virtual strm file, we need to override the path by reading it's contents @@ -146,22 +153,6 @@ class PlaybackUtils(): WINDOW.setProperty(playurl+"runtimeticks", str(result.get("RunTimeTicks"))) WINDOW.setProperty(playurl+"type", result.get("Type")) WINDOW.setProperty(playurl+"item_id", id) - - '''mediaSources = result.get("MediaSources") - if(mediaSources != None): - mediaStream = mediaSources[0].get('MediaStreams') - defaultsubs = "" - for stream in mediaStream: - if u'Subtitle' in stream[u'Type'] and stream[u'IsDefault']: - if u'Language' in stream: - defaultsubs = stream[u'Language'] - else: - defaultsubs = stream[u'Codec'] - WINDOW.setProperty("%ssubs" % playurl, defaultsubs.encode('utf-8')) - if mediaSources[0].get('DefaultAudioStreamIndex') != None: - WINDOW.setProperty(playurl+"AudioStreamIndex", str(mediaSources[0].get('DefaultAudioStreamIndex'))) - if mediaSources[0].get('DefaultSubtitleStreamIndex') != None: - WINDOW.setProperty(playurl+"SubtitleStreamIndex", str(mediaSources[0].get('DefaultSubtitleStreamIndex')))''' #launch the playback - only set the listitem props if we're not using the setresolvedurl approach if setup == "service": @@ -174,6 +165,76 @@ class PlaybackUtils(): else: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem) + def audioSubsPref(self, url, mediaSources): + + WINDOW = xbmcgui.Window(10000) + # Present the list of audio to select from + audioStreamsList = {} + audioStreams = [] + selectAudioIndex = "" + subtitleStreamsList = {} + subtitleStreams = ['No subtitles'] + selectSubsIndex = "" + playurlprefs = "%s" % url + + mediaStream = mediaSources[0].get('MediaStreams') + for stream in mediaStream: + index = stream['Index'] + # Since Emby returns all possible tracks together, have to sort them. + if 'Audio' in stream['Type']: + try: + track = stream['Language'] + audioStreamsList[track] = index + audioStreams.append(track) + except: + track = stream['Codec'] + audioStreamsList[track] = index + audioStreams.append(track) + + elif 'Subtitle' in stream['Type']: + try: + track = stream['Language'] + subtitleStreamsList[track] = index + subtitleStreams.append(track) + except: + track = stream['Codec'] + subtitleStreamsList[track] = index + subtitleStreams.append(track) + + if len(audioStreams) > 1: + resp = xbmcgui.Dialog().select("Choose the audio stream", audioStreams) + if resp > -1: + # User selected audio + selected = audioStreams[resp] + selected_audioIndex = audioStreamsList[selected] + playurlprefs += "&AudioStreamIndex=%s" % selected_audioIndex + selectAudioIndex = str(selected_audioIndex) + else: return False + else: # There's only one audiotrack. + audioIndex = audioStreamsList[audioStreams[0]] + playurlprefs += "&AudioStreamIndex=%s" % audioIndex + selectAudioIndex = str(audioIndex) + + if len(subtitleStreams) > 1: + resp = xbmcgui.Dialog().select("Choose the subtitle stream", subtitleStreams) + if resp == 0: + # User selected no subtitles + pass + elif resp > -1: + # User selected subtitles + selected = subtitleStreams[resp] + selected_subsIndex = subtitleStreamsList[selected] + playurlprefs += "&SubtitleStreamIndex=%s" % selected_subsIndex + selectSubsIndex = str(selected_subsIndex) + else: return False + + # Reset the method with the new playurl + WINDOW.setProperty("%splaymethod" % playurlprefs, "Transcode") + WINDOW.setProperty("%sAudioStreamIndex" % playurlprefs, selectAudioIndex) + WINDOW.setProperty("%sSubtitleStreamIndex" % playurlprefs, selectSubsIndex) + + return playurlprefs + def setArt(self, list,name,path): if name=='thumb' or name=='fanart_image' or name=='small_poster' or name=='tiny_poster' or name == "medium_landscape" or name=='medium_poster' or name=='small_fanartimage' or name=='medium_fanartimage' or name=='fanart_noindicators': list.setProperty(name, path) diff --git a/resources/lib/Player.py b/resources/lib/Player.py index be495ece..81d95a84 100644 --- a/resources/lib/Player.py +++ b/resources/lib/Player.py @@ -68,6 +68,8 @@ class Player( xbmc.Player ): def stopAll(self): + WINDOW = xbmcgui.Window(10000) + if(len(self.played_information) == 0): return @@ -86,6 +88,7 @@ class Player( xbmc.Player ): refresh_id = data.get("refresh_id") currentFile = data.get("currentfile") type = data.get("Type") + playMethod = data.get('playmethod') # Prevent websocket feedback self.WINDOW.setProperty("played_itemId", item_id) @@ -116,12 +119,12 @@ class Player( xbmc.Player ): listItem = [item_id] LibrarySync().removefromDB(listItem, True) - # Stop transcoding - if self.WINDOW.getProperty("transcoding%s" % item_id) == "true": - deviceId = self.clientInfo.getMachineId() - url = "{server}/mediabrowser/Videos/ActiveEncodings?DeviceId=%s" % deviceId - self.doUtils.downloadUrl(url, type="DELETE") - self.WINDOW.clearProperty("transcoding%s" % item_id) + # Stop transcoding + if playMethod == "Transcode": + self.logMsg("Transcoding for %s terminated." % item_id) + deviceId = self.clientInfo.getMachineId() + url = "{server}/mediabrowser/Videos/ActiveEncodings?DeviceId=%s" % deviceId + self.doUtils.downloadUrl(url, type="DELETE") self.played_information.clear() @@ -176,22 +179,6 @@ class Player( xbmc.Player ): volume = result.get(u'result').get(u'volume') muted = result.get(u'result').get(u'muted') - # Get current audio and subtitles track - track_query = '{"jsonrpc": "2.0", "method": "Player.GetProperties", "params": {"playerid":1,"properties": ["currentsubtitle","currentaudiostream","subtitleenabled"]} , "id": 1}' - result = xbmc.executeJSONRPC(track_query) - result = json.loads(result) - indexAudio = result['result']['currentaudiostream']['index'] - indexSubs = result['result']['currentsubtitle']['index'] - subsEnabled = result['result']['subtitleenabled'] - - # Convert back into an Emby index - audioTracks = len(xbmc.Player().getAvailableAudioStreams()) - indexAudio = indexAudio + 1 - if subsEnabled: - indexSubs = indexSubs + audioTracks + 1 - else: - indexSubs = "" - postdata = { 'QueueableMediaTypes': "Video", 'CanSeek': True, @@ -206,17 +193,38 @@ class Player( xbmc.Player ): if playTime: postdata['PositionTicks'] = int(playTime * 10000000) - if audioindex == indexAudio: - postdata['AudioStreamIndex'] = audioindex - else: - postdata['AudioStreamIndex'] = indexAudio - data['AudioStreamIndex'] = indexAudio + if playMethod != "Transcode": + # Get current audio and subtitles track + track_query = '{"jsonrpc": "2.0", "method": "Player.GetProperties", "params": {"playerid":1,"properties": ["currentsubtitle","currentaudiostream","subtitleenabled"]} , "id": 1}' + result = xbmc.executeJSONRPC(track_query) + result = json.loads(result) + indexAudio = result['result']['currentaudiostream']['index'] + indexSubs = result['result']['currentsubtitle']['index'] + subsEnabled = result['result']['subtitleenabled'] + + # Convert back into an Emby index + audioTracks = len(xbmc.Player().getAvailableAudioStreams()) + indexAudio = indexAudio + 1 + if subsEnabled: + indexSubs = indexSubs + audioTracks + 1 + else: + indexSubs = "" + + if audioindex == indexAudio: + postdata['AudioStreamIndex'] = audioindex + else: + postdata['AudioStreamIndex'] = indexAudio + data['AudioStreamIndex'] = indexAudio + + if subtitleindex == indexSubs: + postdata['SubtitleStreamIndex'] = subtitleindex + else: + postdata['SubtitleStreamIndex'] = indexSubs + data['SubtitleStreamIndex'] = indexSubs - if subtitleindex == indexSubs: - postdata['SubtitleStreamIndex'] = subtitleindex else: - postdata['SubtitleStreamIndex'] = indexSubs - data['SubtitleStreamIndex'] = indexSubs + data['AudioStreamIndex'] = audioindex + data['SubtitleStreamIndex'] = subtitleindex postdata = json.dumps(postdata) self.logMsg("Report: %s" % postdata, 2) @@ -249,7 +257,7 @@ class Player( xbmc.Player ): def onPlayBackStarted( self ): # Will be called when xbmc starts playing a file - WINDOW = self.WINDOW + WINDOW = xbmcgui.Window(10000) addon = self.addon xbmcplayer = self.xbmcplayer self.stopAll() @@ -277,8 +285,6 @@ class Player( xbmc.Player ): # only ever use the win props here, use the data map in all other places runtime = WINDOW.getProperty(currentFile + "runtimeticks") refresh_id = WINDOW.getProperty(currentFile + "refresh_id") - audioindex = WINDOW.getProperty(currentFile + "AudioStreamIndex") - subtitleindex = WINDOW.getProperty(currentFile + "SubtitleStreamIndex") playMethod = WINDOW.getProperty(currentFile + "playmethod") itemType = WINDOW.getProperty(currentFile + "type") @@ -289,14 +295,6 @@ class Player( xbmc.Player ): volume = result.get(u'result').get(u'volume') muted = result.get(u'result').get(u'muted') - # Get the current audio track and subtitles - track_query = '{"jsonrpc": "2.0", "method": "Player.GetProperties", "params": {"playerid":1,"properties": ["currentsubtitle","currentaudiostream","subtitleenabled"]} , "id": 1}' - result = xbmc.executeJSONRPC(track_query) - result = json.loads(result) - indexAudio = result['result']['currentaudiostream']['index'] - indexSubs = result['result']['currentsubtitle']['index'] - subsEnabled = result['result']['subtitleenabled'] - seekTime = xbmc.Player().getTime() url = "{server}/mediabrowser/Sessions/Playing" @@ -311,14 +309,22 @@ class Player( xbmc.Player ): 'IsMuted': muted } - if audioindex: + # Get the current audio track and subtitles + if playMethod == "Transcode": + audioindex = WINDOW.getProperty(currentFile + "AudioStreamIndex") + subtitleindex = WINDOW.getProperty(currentFile + "SubtitleStreamIndex") postdata['AudioStreamIndex'] = audioindex - else: - postdata['AudioStreamIndex'] = indexAudio + 1 - - if subtitleindex: postdata['SubtitleStreamIndex'] = subtitleindex + else: + track_query = '{"jsonrpc": "2.0", "method": "Player.GetProperties", "params": {"playerid": 1,"properties": ["currentsubtitle","currentaudiostream","subtitleenabled"]} , "id": 1}' + result = xbmc.executeJSONRPC(track_query) + result = json.loads(result) + indexAudio = result['result']['currentaudiostream']['index'] + indexSubs = result['result']['currentsubtitle']['index'] + subsEnabled = result['result']['subtitleenabled'] + + postdata['AudioStreamIndex'] = indexAudio + 1 if subsEnabled: audioTracks = len(xbmc.Player().getAvailableAudioStreams()) postdata['SubtitleStreamIndex'] = indexSubs + audioTracks + 1 @@ -387,4 +393,4 @@ class Player( xbmc.Player ): def onPlayBackStopped( self ): # Will be called when user stops xbmc playing a file self.logMsg("onPlayBackStopped", 0) - self.stopAll() + self.stopAll() \ No newline at end of file