Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add credits detection functionality #93

Merged
merged 1 commit into from
Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ Currently on Windows the built-in MPV does not work with SVP. You must download
- `stop_idle` - Stop the player when idle. (Requires `idle_when_paused`.) Default: `false`
- `skip_intro_always` - Always skip intros, without asking. Default: `false`
- `skip_intro_prompt` - Prompt to skip intro via seeking. Default: `true`
- `skip_credits_always` - Always skip credits, without asking. Default: `false`
- `skip_credits_prompt` - Prompt to skip credits via seeking. Default: `true`
- `menu_mouse` - Enable mouse support in the menu. Default: `true`
- This requires MPV to be compiled with lua support.

Expand Down
2 changes: 2 additions & 0 deletions plex_mpv_shim/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class Settings(object):
"seek_left": -5,
"skip_intro_always": False,
"skip_intro_prompt": True,
"skip_credits_always": False,
"skip_credits_prompt": True,
"shader_pack_enable": True,
"shader_pack_custom": False,
"shader_pack_remember": True,
Expand Down
12 changes: 12 additions & 0 deletions plex_mpv_shim/media.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ def __init__(self, node, parent, media=0, part=0):
self.trs_ovr = None
self.intro_start = None
self.intro_end = None
self.credits_start = None
self.credits_end = None

if media:
self.select_media(media, part)
Expand All @@ -106,6 +108,16 @@ def __init__(self, node, parent, media=0, part=0):
except:
log.error("Could not detect intro.", exc_info=True)

# TODO de-duplicate this code in some way - it's ugly
try:
marker = self.node.find("./Marker[@type='credits']")
if marker is not None:
self.credits_start = float(marker.get('startTimeOffset')) / 1e3
self.credits_end = float(marker.get('endTimeOffset')) / 1e3
log.info("Credits Detected: {0} - {1}".format(self.credits_start, self.credits_end))
except:
log.error("Could not detect credits.", exc_info=True)

self.map_streams()

def map_streams(self):
Expand Down
54 changes: 49 additions & 5 deletions plex_mpv_shim/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ def __init__(self):
self.url = None
self.evt_queue = Queue()
self.is_in_intro = False
self.is_in_credits = False
self.intro_has_triggered = False
self.credits_has_triggered = False

if is_using_ext_mpv:
mpv_options.update(
Expand Down Expand Up @@ -156,6 +158,8 @@ def handle_media_next():
if settings.media_key_seek:
if self.is_in_intro:
self.skip_intro()
elif self.is_in_credits:
self.skip_credits()
else:
self._player.command("seek", 30)
else:
Expand Down Expand Up @@ -201,6 +205,8 @@ def menu_right():
else:
if self.is_in_intro:
self.skip_intro()
elif self.is_in_credits:
self.skip_credits()
else:
self._player.command("seek", settings.seek_right)

Expand All @@ -211,6 +217,8 @@ def menu_up():
else:
if self.is_in_intro:
self.skip_intro()
elif self.is_in_credits:
self.skip_credits()
else:
self._player.command("seek", settings.seek_up)

Expand Down Expand Up @@ -289,20 +297,30 @@ def timeline_handle(self):
if self.timeline_trigger:
self.timeline_trigger.set()

def skip_intro(self):
def skip_marker(self, end_point):
if self._media_item.media_type == MediaType.VIDEO:
self._player.playback_time = self._media_item.intro_end
self._player.playback_time = end_point
self.timeline_handle()
return True
return False

def skip_intro(self):
end_point = self._media_item.intro_end
if self.skip_marker(end_point):
self.is_in_intro = False

@synchronous('_lock')
def update(self):
def skip_credits(self):
end_point = self._media_item.credits_end
if self.skip_marker(end_point):
self.is_in_credits = False

def check_intro_or_credits(self):
if ((settings.skip_intro_always or settings.skip_intro_prompt)
and self._media_item is not None and self._media_item.media_type == MediaType.VIDEO and self._media_item.intro_start is not None
and self._player.playback_time is not None
and self._player.playback_time > self._media_item.intro_start
and self._player.playback_time < self._media_item.intro_end):

if not self.is_in_intro:
if settings.skip_intro_always and not self.intro_has_triggered:
self.intro_has_triggered = True
Expand All @@ -314,6 +332,28 @@ def update(self):
else:
self.is_in_intro = False

# TODO de-duplicate this code in some way - it's ugly
if ((settings.skip_credits_always or settings.skip_credits_prompt)
and self._media_item is not None and self._media_item.media_type == MediaType.VIDEO and self._media_item.credits_start is not None
and self._player.playback_time is not None
and self._player.playback_time > self._media_item.credits_start
and self._player.playback_time < self._media_item.credits_end):

if not self.is_in_credits:
if settings.skip_credits_always and not self.credits_has_triggered:
self.credits_has_triggered = True
self.skip_credits()
self._player.show_text("Skipped Credits", 3000, 1)
elif settings.skip_credits_prompt:
self._player.show_text("Seek to Skip Credits", 3000, 1)
self.is_in_credits = True
else:
self.is_in_credits = False


@synchronous('_lock')
def update(self):
self.check_intro_or_credits()
while not self.evt_queue.empty():
func, args = self.evt_queue.get()
func(*args)
Expand Down Expand Up @@ -344,7 +384,9 @@ def _play_media(self, media_item, url, offset=0):
self._player.force_media_title = media_item.get_proper_title()
self._media_item = media_item
self.is_in_intro = False
self.is_in_credits = False
self.intro_has_triggered = False
self.credits_has_triggered = False
self.update_subtitle_visuals(False)
self.upd_player_hide()
self.external_subtitles = {}
Expand Down Expand Up @@ -423,6 +465,8 @@ def seek(self, offset):
if not self._player.playback_abort:
if self.is_in_intro and offset > self._player.playback_time:
self.skip_intro()
elif self.is_in_credits and offset > self._player.playback_time:
self.skip_credits()
else:
self._player.playback_time = offset
self.timeline_handle()
Expand Down