Improved synced and optimized version info

This commit is contained in:
JonnyWong16 2017-12-23 11:52:28 -08:00
parent 0a42cb4135
commit 33acf9402d
9 changed files with 156 additions and 42 deletions

View file

@ -162,7 +162,15 @@ DOCUMENTATION :: END
<li class="dashboard-activity-info-item">
<div class="sub-heading">Optimized</div>
<div class="sub-value" id="optimized_version-${sk}">
${data['optimized_version_profile']}
${data['optimized_version_profile']} (${data['optimized_version_title']})
</div>
</li>
% endif
% if data['synced_version'] == 1:
<li class="dashboard-activity-info-item">
<div class="sub-heading">Synced</div>
<div class="sub-value" id="synced_version-${sk}">
${data['synced_version_profile']}
</div>
</li>
% endif
@ -185,7 +193,7 @@ DOCUMENTATION :: END
% elif data['transcode_decision'] == 'copy':
Direct Stream
% else:
Direct Play ${'(Synced)' if data['synced_version'] == 1 else ''}
Direct Play
% endif
</div>
</li>
@ -250,7 +258,7 @@ DOCUMENTATION :: END
% elif data['stream_subtitle_decision'] == 'burn':
Burn (${data['subtitle_codec'].upper()})
% else:
Direct Play (${data['subtitle_codec'].upper()})
Direct Play (${data['stream_subtitle_codec'].upper() if data['synced_version'] else data['subtitle_codec'].upper()})
% endif
% else:
None

View file

@ -257,7 +257,7 @@
if (!(current_activity)) {
% if _session['user_group'] == 'admin':
var msg_settings = ' Verify your server in the <a href="settings#tab_tabs-plex_media_server">settings</a>.';
var msg_settings = ' Verify your server connection in the <a href="settings#tab_tabs-plex_media_server">settings</a>.';
% else:
var msg_settings = ''
% endif
@ -357,7 +357,7 @@
} else if (s.transcode_decision === 'copy') {
transcode_decision = 'Direct Stream';
} else {
transcode_decision = 'Direct Play' + ((s.synced_version == 1) ? ' (Synced)' : '');
transcode_decision = 'Direct Play';
}
$('#transcode_decision-' + key).html(transcode_decision);
@ -434,7 +434,7 @@
} else if (s.stream_subtitle_decision === 'burn') {
subtitle_decision = 'Burn (' + s.subtitle_codec.toUpperCase() + ')';
} else {
subtitle_decision = 'Direct Play (' + s.subtitle_codec.toUpperCase() + ')';
subtitle_decision = 'Direct Play (' + ((s.synced_version == '1') ? s.stream_subtitle_codec.toUpperCase() : s.subtitle_codec.toUpperCase()) + ')';
}
}
$('#subtitle_decision-' + key).html(subtitle_decision);
@ -453,7 +453,8 @@
} else {
$('#stream_quality-' + key).html(s.quality_profile);
}
$('#optimized_version-' + key).html(s.optimized_version_profile);
$('#optimized_version-' + key).html(s.optimized_version_profile + ' (' + s.optimized_version_title + ')');
$('#synced_quality_profile-' + key).html(s.synced_quality_profile);
if (s.media_type != 'photo' && parseInt(s.bandwidth)) {
var bw = parseInt(s.bandwidth);

View file

@ -98,14 +98,14 @@ DOCUMENTATION :: END
<tr>
<td>Optimized Version</td>
<td>-</td>
<td>${data['optimized_version_profile']}</td>
<td>${data['optimized_version_profile']}<br>(${data['optimized_version_title']})</td>
</tr>
% endif
% if data['synced_version'] == 1:
<tr>
<td>Synced Version</td>
<td>-</td>
<td>yes</td>
<td>${data['synced_version_profile']}</td>
</tr>
% endif
</tbody>

View file

@ -450,7 +450,8 @@ def dbcheck():
'transcode_protocol TEXT, transcode_container TEXT, '
'transcode_video_codec TEXT, transcode_audio_codec TEXT, transcode_audio_channels INTEGER,'
'transcode_width INTEGER, transcode_height INTEGER, '
'optimized_version INTEGER, optimized_version_profile TEXT, synced_version INTEGER, '
'optimized_version INTEGER, optimized_version_profile TEXT, optimized_version_title TEXT, '
'synced_version INTEGER, synced_version_profile TEXT, '
'buffer_count INTEGER DEFAULT 0, buffer_last_triggered INTEGER, last_paused INTEGER, write_attempts INTEGER DEFAULT 0, '
'raw_stream_info TEXT)'
)
@ -482,7 +483,8 @@ def dbcheck():
'stream_video_framerate TEXT, '
'stream_audio_decision TEXT, stream_audio_codec TEXT, stream_audio_bitrate INTEGER, stream_audio_channels INTEGER, '
'stream_subtitle_decision TEXT, stream_subtitle_codec TEXT, stream_subtitle_container TEXT, stream_subtitle_forced INTEGER, '
'subtitles INTEGER, subtitle_codec TEXT, synced_version INTEGER, optimized_version INTEGER, optimized_version_profile TEXT)'
'subtitles INTEGER, subtitle_codec TEXT, synced_version INTEGER, synced_version_profile TEXT, '
'optimized_version INTEGER, optimized_version_profile TEXT, optimized_version_title TEXT)'
)
# session_history_metadata table :: This is a table which logs each session's media metadata
@ -892,6 +894,15 @@ def dbcheck():
'ALTER TABLE sessions ADD COLUMN raw_stream_info TEXT'
)
# Upgrade sessions table from earlier versions
try:
c_db.execute('SELECT video_height FROM sessions')
except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.")
c_db.execute(
'ALTER TABLE sessions ADD COLUMN video_height INTEGER'
)
# Upgrade sessions table from earlier versions
try:
c_db.execute('SELECT subtitles FROM sessions')
@ -900,13 +911,17 @@ def dbcheck():
c_db.execute(
'ALTER TABLE sessions ADD COLUMN subtitles INTEGER'
)
# Upgrade sessions table from earlier versions
try:
c_db.execute('SELECT video_height FROM sessions')
c_db.execute('SELECT synced_version_profile FROM sessions')
except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.")
c_db.execute(
'ALTER TABLE sessions ADD COLUMN video_height INTEGER'
'ALTER TABLE sessions ADD COLUMN synced_version_profile TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN optimized_version_title TEXT'
)
# Upgrade session_history table from earlier versions
@ -1139,6 +1154,18 @@ def dbcheck():
'ALTER TABLE session_history_media_info ADD COLUMN subtitle_codec TEXT '
)
# Upgrade session_history_media_info table from earlier versions
try:
c_db.execute('SELECT synced_version_profile FROM session_history_media_info')
except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_media_info.")
c_db.execute(
'ALTER TABLE session_history_media_info ADD COLUMN synced_version_profile TEXT '
)
c_db.execute(
'ALTER TABLE session_history_media_info ADD COLUMN optimized_version_title TEXT '
)
# Upgrade users table from earlier versions
try:
c_db.execute('SELECT do_notify FROM users')

View file

@ -90,9 +90,11 @@ class ActivityProcessor(object):
'transcode_audio_channels': session.get('transcode_audio_channels', ''),
'transcode_width': session.get('stream_video_width', ''),
'transcode_height': session.get('stream_video_height', ''),
'synced_version': session.get('synced_version', ''),
'synced_version_profile': session.get('synced_version_profile', ''),
'optimized_version': session.get('optimized_version', ''),
'optimized_version_profile': session.get('optimized_version_profile', ''),
'synced_version': session.get('synced_version', ''),
'optimized_version_title': session.get('optimized_version_title', ''),
'stream_bitrate': session.get('stream_bitrate', ''),
'stream_video_resolution': session.get('stream_video_resolution', ''),
'quality_profile': session.get('quality_profile', ''),
@ -110,6 +112,7 @@ class ActivityProcessor(object):
'stream_audio_channels': session.get('stream_audio_channels', ''),
'stream_subtitle_decision': session.get('stream_subtitle_decision', ''),
'stream_subtitle_codec': session.get('stream_subtitle_codec', ''),
'subtitles': session.get('subtitles', ''),
'raw_stream_info': json.dumps(session),
'stopped': int(time.time())
}
@ -356,6 +359,8 @@ class ActivityProcessor(object):
'stream_subtitle_forced': session['stream_subtitle_forced'],
'subtitles': session['subtitles'],
'synced_version': session['synced_version'],
'synced_version_profile': session['synced_version_profile'],
'synced_version_title': session['synced_version_title'],
'optimized_version': session['optimized_version'],
'optimized_version_profile': session['optimized_version_profile']
}

View file

@ -872,8 +872,10 @@ class DataFactory(object):
user_cond = 'AND %s.user_id = %s ' % (table, session.get_session_user_id())
if row_id:
query = 'SELECT bitrate, video_resolution, optimized_version, optimized_version_profile, synced_version, ' \
'container, video_codec, video_Bitrate, video_width, video_height, video_framerate, aspect_ratio, ' \
query = 'SELECT bitrate, video_resolution, ' \
'optimized_version, optimized_version_profile, optimized_version_title, ' \
'synced_version, synced_version_profile, ' \
'container, video_codec, video_bitrate, video_width, video_height, video_framerate, aspect_ratio, ' \
'audio_codec, audio_bitrate, audio_channels, subtitle_codec, ' \
'stream_bitrate, stream_video_resolution, quality_profile, stream_container_decision, stream_container, ' \
'stream_video_decision, stream_video_codec, stream_video_bitrate, stream_video_width, stream_video_height, ' \
@ -887,8 +889,10 @@ class DataFactory(object):
'WHERE session_history_media_info.id = ? %s' % user_cond
result = monitor_db.select(query, args=[row_id])
elif session_key:
query = 'SELECT bitrate, video_resolution, optimized_version, optimized_version_profile, synced_version, ' \
'container, video_codec, video_Bitrate, video_width, video_height, video_framerate, aspect_ratio, ' \
query = 'SELECT bitrate, video_resolution, ' \
'optimized_version, optimized_version_profile, optimized_version_title, ' \
'synced_version, synced_version_profile, ' \
'container, video_codec, video_bitrate, video_width, video_height, video_framerate, aspect_ratio, ' \
'audio_codec, audio_bitrate, audio_channels, subtitle_codec, ' \
'stream_bitrate, stream_video_resolution, quality_profile, stream_container_decision, stream_container, ' \
'stream_video_decision, stream_video_codec, stream_video_bitrate, stream_video_width, stream_video_height, ' \
@ -909,7 +913,9 @@ class DataFactory(object):
'video_resolution': item['video_resolution'],
'optimized_version': item['optimized_version'],
'optimized_version_profile': item['optimized_version_profile'],
'optimized_version_title': item['optimized_version_title'],
'synced_version': item['synced_version'],
'synced_version_profile': item['synced_version_profile'],
'container': item['container'],
'video_codec': item['video_codec'],
'video_bitrate': item['video_bitrate'],

View file

@ -425,7 +425,7 @@ class PlexTV(object):
return users_list
def get_synced_items(self, machine_id=None, user_id=None):
def get_synced_items(self, machine_id=None, client_id_filter=None, user_id_filter=None, rating_key_filter=None):
sync_list = self.get_plextv_sync_lists(machine_id)
user_data = users.Users()
@ -446,9 +446,15 @@ class PlexTV(object):
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_synced_items.")
else:
for a in xml_head:
sync_id = helpers.get_xml_attr(a, 'id')
client_id = helpers.get_xml_attr(a, 'clientIdentifier')
# Filter by client_id
if client_id_filter and client_id_filter != client_id:
continue
sync_id = helpers.get_xml_attr(a, 'id')
sync_device = a.getElementsByTagName('Device')
for device in sync_device:
device_user_id = helpers.get_xml_attr(device, 'userID')
try:
@ -467,12 +473,23 @@ class PlexTV(object):
device_last_seen = helpers.get_xml_attr(device, 'lastSeenAt')
# Filter by user_id
if user_id and user_id != device_user_id:
if user_id_filter and user_id_filter != device_user_id:
continue
for synced in a.getElementsByTagName('SyncItems'):
sync_item = synced.getElementsByTagName('SyncItem')
for item in sync_item:
for location in item.getElementsByTagName('Location'):
clean_uri = helpers.get_xml_attr(location, 'uri').split('%2F')
rating_key = next((clean_uri[(idx + 1) % len(clean_uri)]
for idx, item in enumerate(clean_uri) if item == 'metadata'), None)
# Filter by rating_key
if rating_key_filter and rating_key_filter != rating_key:
continue
sync_id = helpers.get_xml_attr(item, 'id')
sync_version = helpers.get_xml_attr(item, 'version')
sync_root_title = helpers.get_xml_attr(item, 'rootTitle')
@ -501,12 +518,6 @@ class PlexTV(object):
settings_video_quality = helpers.get_xml_attr(settings, 'videoQuality')
settings_video_resolution = helpers.get_xml_attr(settings, 'videoResolution')
for location in item.getElementsByTagName('Location'):
clean_uri = helpers.get_xml_attr(location, 'uri').split('%2F')
rating_key = next((clean_uri[(idx + 1) % len(clean_uri)]
for idx, item in enumerate(clean_uri) if item == 'metadata'), None)
sync_details = {"device_name": helpers.sanitize(device_name),
"platform": helpers.sanitize(device_platform),
"username": helpers.sanitize(device_username),

View file

@ -24,6 +24,7 @@ import helpers
import http_handler
import libraries
import logger
import plextv
import session
import users
@ -590,7 +591,7 @@ class PmsConnect(object):
return output
def get_metadata_details(self, rating_key=''):
def get_metadata_details(self, rating_key='', sync_id=''):
"""
Return processed and validated metadata list for requested item.
@ -598,7 +599,10 @@ class PmsConnect(object):
Output: array
"""
metadata = self.get_metadata(str(rating_key), output_format='xml')
if rating_key:
metadata = self.get_metadata(str(rating_key), output_format='xml')
elif sync_id:
metadata = self.get_sync_item(str(sync_id), output_format='xml')
try:
xml_head = metadata.getElementsByTagName('MediaContainer')
@ -1322,6 +1326,7 @@ class PmsConnect(object):
# Get the source media type
media_type = helpers.get_xml_attr(session, 'type')
rating_key = helpers.get_xml_attr(session, 'ratingKey')
# Get the user details
user_info = session.getElementsByTagName('User')[0]
@ -1348,7 +1353,7 @@ class PmsConnect(object):
'product_version': helpers.get_xml_attr(player_info, 'version'),
'profile': helpers.get_xml_attr(player_info, 'profile'),
'player': helpers.get_xml_attr(player_info, 'title') or helpers.get_xml_attr(player_info, 'product'),
'machine_id': helpers.get_xml_attr(player_info, 'machineIdentifier').rstrip('_Video').rstrip('_Track'),
'machine_id': helpers.get_xml_attr(player_info, 'machineIdentifier'),
'state': helpers.get_xml_attr(player_info, 'state'),
'local': helpers.get_xml_attr(player_info, 'local')
}
@ -1431,14 +1436,29 @@ class PmsConnect(object):
# Determine if a synced version is being played
if media_type not in ('photo', 'clip') and not session.getElementsByTagName('Session') \
and helpers.get_xml_attr(session, 'ratingKey').isdigit() and transcode_decision == 'direct play':
synced_version = 1
plex_tv = plextv.PlexTV()
synced_items = plex_tv.get_synced_items(machine_id=plexpy.CONFIG.PMS_IDENTIFIER,
client_id_filter=player_details['machine_id'],
rating_key_filter=rating_key)
if synced_items:
sync_id = synced_items[0]['sync_id']
synced_xml = self.get_sync_item(sync_id=sync_id, output_format='xml')
synced_xml_head = synced_xml.getElementsByTagName('MediaContainer')
if synced_xml_head[0].getElementsByTagName('Track'):
synced_session_data = synced_xml_head[0].getElementsByTagName('Track')[0]
elif synced_xml_head[0].getElementsByTagName('Video'):
synced_session_data = synced_xml_head[0].getElementsByTagName('Video')[0]
else:
synced_version = 0
sync_id = None
# Figure out which version is being played
media_info_all = session.getElementsByTagName('Media')
if sync_id:
media_info_all = synced_session_data.getElementsByTagName('Media')
else:
media_info_all = session.getElementsByTagName('Media')
stream_media_info = next((m for m in media_info_all if helpers.get_xml_attr(m, 'selected') == '1'), media_info_all[0])
stream_media_parts_info = stream_media_info.getElementsByTagName('Part')[0]
part_info_all = stream_media_info.getElementsByTagName('Part')
stream_media_parts_info = next((p for p in part_info_all if helpers.get_xml_attr(p, 'selected') == '1'), part_info_all[0])
# Get the stream details
video_stream_info = audio_stream_info = subtitle_stream_info = None
@ -1495,6 +1515,7 @@ class PmsConnect(object):
if subtitle_stream_info:
subtitle_id = helpers.get_xml_attr(subtitle_stream_info, 'id')
subtitle_selected = helpers.get_xml_attr(subtitle_stream_info, 'selected')
subtitle_details = {'stream_subtitle_codec': helpers.get_xml_attr(subtitle_stream_info, 'codec'),
'stream_subtitle_container': helpers.get_xml_attr(subtitle_stream_info, 'container'),
'stream_subtitle_format': helpers.get_xml_attr(subtitle_stream_info, 'format'),
@ -1544,14 +1565,14 @@ class PmsConnect(object):
'stream_video_height': helpers.get_xml_attr(stream_media_info, 'height'),
'stream_video_width': helpers.get_xml_attr(stream_media_info, 'width'),
'stream_duration': helpers.get_xml_attr(stream_media_info, 'duration') or helpers.get_xml_attr(session, 'duration'),
'stream_container_decision': helpers.get_xml_attr(stream_media_parts_info, 'decision').replace('directplay', 'direct play'),
'stream_container_decision': 'direct play' if sync_id else helpers.get_xml_attr(stream_media_parts_info, 'decision').replace('directplay', 'direct play'),
'transcode_decision': transcode_decision,
'optimized_version': 1 if helpers.get_xml_attr(stream_media_info, 'proxyType') == '42' else 0,
'optimized_version_profile': helpers.get_xml_attr(stream_media_info, 'title'),
'synced_version': synced_version,
'optimized_version_title': helpers.get_xml_attr(stream_media_info, 'title'),
'synced_version': 1 if sync_id else 0,
'indexes': 1 if indexes == 'sd' else 0,
'bif_thumb': bif_thumb,
'subtitles': 1 if subtitle_id else 0
'subtitles': 1 if subtitle_id and subtitle_selected else 0
}
# Get the source media info
@ -1617,7 +1638,10 @@ class PmsConnect(object):
media_id = helpers.get_xml_attr(stream_media_info, 'id')
part_id = helpers.get_xml_attr(stream_media_parts_info, 'id')
metadata_details = self.get_metadata_details(rating_key=helpers.get_xml_attr(session, 'ratingKey'))
if sync_id:
metadata_details = self.get_metadata_details(sync_id=sync_id)
else:
metadata_details = self.get_metadata_details(rating_key=rating_key)
# Get the media info, fallback to first item if match id is not found
source_medias = metadata_details.pop('media_info', [])
@ -1682,7 +1706,22 @@ class PmsConnect(object):
quality_profile = common.VIDEO_QUALITY_PROFILES[quailtiy_bitrate]
except ValueError:
quality_profile = 'Original'
if sync_id:
try:
synced_bitrate = min(b for b in common.VIDEO_QUALITY_PROFILES if source_bitrate <= b)
synced_version_profile = common.VIDEO_QUALITY_PROFILES[synced_bitrate]
except ValueError:
synced_version_profile = 'Original'
else:
synced_version_profile = ''
if stream_details['optimized_version']:
optimized_version_profile = '{} Mbps {}'.format(round(source_bitrate / 1000.0, 1),
plexpy.common.VIDEO_RESOLUTION_OVERRIDES.get(source_media_details['video_resolution'], source_media_details['video_resolution']))
else:
optimized_version_profile = ''
elif media_type == 'track' and 'stream_bitrate' in stream_details:
stream_bitrate = helpers.cast_to_int(stream_details['stream_bitrate'])
source_bitrate = helpers.cast_to_int(source_media_details.get('bitrate'))
@ -1693,11 +1732,26 @@ class PmsConnect(object):
except ValueError:
quality_profile = 'Original'
if sync_id:
try:
synced_bitrate = min(b for b in common.AUDIO_QUALITY_PROFILES if source_bitrate <= b)
synced_version_profile = common.AUDIO_QUALITY_PROFILES[synced_bitrate]
except ValueError:
synced_version_profile = 'Original'
else:
synced_version_profile = ''
optimized_version_profile = ''
elif media_type == 'photo':
quality_profile = 'Original'
synced_version_profile = ''
optimized_version_profile = ''
else:
quality_profile = 'Unknown'
synced_version_profile = ''
optimized_version_profile = ''
# Entire session output (single dict for backwards compatibility)
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
@ -1705,6 +1759,8 @@ class PmsConnect(object):
'view_offset': view_offset,
'progress_percent': str(helpers.get_percent(view_offset, stream_details['stream_duration'])),
'quality_profile': quality_profile,
'synced_version_profile': synced_version_profile,
'optimized_version_profile': optimized_version_profile,
'user': user_details['username'], # Keep for backwards compatibility
'channel_stream': channel_stream
}

View file

@ -2195,7 +2195,7 @@ class WebInterface(object):
machine_id = plexpy.CONFIG.PMS_IDENTIFIER
plex_tv = plextv.PlexTV()
result = plex_tv.get_synced_items(machine_id=machine_id, user_id=user_id)
result = plex_tv.get_synced_items(machine_id=machine_id, user_id_filter=user_id)
if result:
output = {"data": result}
@ -4560,7 +4560,7 @@ class WebInterface(object):
```
"""
plex_tv = plextv.PlexTV()
result = plex_tv.get_synced_items(machine_id=machine_id, user_id=user_id)
result = plex_tv.get_synced_items(machine_id=machine_id, user_id_filter=user_id)
if result:
return result