feat(player): implement continue from timestamp

This commit is contained in:
Benex254
2024-08-05 09:47:04 +03:00
parent 6fc51a164d
commit 571bf7de83
3 changed files with 123 additions and 14 deletions

View File

@@ -70,8 +70,18 @@ class Config(object):
self.user = user
user_data_helper.update_user_info(user)
def update_watch_history(self, anime_id: int, episode: str | None):
self.watch_history.update({str(anime_id): episode})
def update_watch_history(
self, anime_id: int, episode: str | None, start_time="0", total_time="0"
):
self.watch_history.update(
{
str(anime_id): {
"episode": episode,
"start_time": start_time,
"total_time": total_time,
}
}
)
user_data_helper.update_watch_history(self.watch_history)
def update_anime_list(self, anime_id: int, remove=False):

View File

@@ -2,6 +2,7 @@ from __future__ import annotations
import os
import random
from datetime import datetime
from rich import print
from rich.progress import Progress
@@ -20,6 +21,19 @@ from ..utils.tools import QueryDict, exit_app
from ..utils.utils import clear, fuzzy_inquirer
def calculate_time_delta(start_time, end_time):
time_format = "%H:%M:%S"
# Convert string times to datetime objects
start = datetime.strptime(start_time, time_format)
end = datetime.strptime(end_time, time_format)
# Calculate the difference
delta = end - start
return delta
def player_controls(config: Config, anilist_config: QueryDict):
# user config
config.translation_type.lower()
@@ -46,8 +60,25 @@ def player_controls(config: Config, anilist_config: QueryDict):
current_episode,
)
mpv(current_link, selected_server["episode_title"])
start_time = config.watch_history[str(anime_id)]["start_time"]
print("[green]Continuing from:[/] ", start_time)
stop_time, total_time = mpv(
current_link, selected_server["episode_title"], start_time=start_time
)
if stop_time == "0":
episode = str(int(current_episode) + 1)
else:
error = 5 * 60
delta = calculate_time_delta(stop_time, total_time)
if delta.total_seconds() > error:
episode = current_episode
else:
episode = str(int(current_episode) + 1)
stop_time = "0"
total_time = "0"
clear()
config.update_watch_history(anime_id, episode, stop_time, total_time)
player_controls(config, anilist_config)
def _next_episode():
@@ -220,14 +251,34 @@ def fetch_streams(config: Config, anilist_config: QueryDict):
{
"mediaId": anime_id,
"status": "CURRENT",
"progress": episode_number if episode_number else 1,
"progress": episode_number if episode_number else 0,
}
)
mpv(stream_link, selected_server["episode_title"])
start_time = config.watch_history.get(str(anime_id), {}).get("start_time", "0")
if start_time != "0":
print("[green]Continuing from:[/] ", start_time)
stop_time, total_time = mpv(
stream_link, selected_server["episode_title"], start_time=start_time
)
print("Finished at: ", stop_time)
# update_watch_history
config.update_watch_history(anime_id, str(int(episode_number) + 1))
if stop_time == "0":
episode = str(int(episode_number) + 1)
else:
error = 5 * 60
delta = calculate_time_delta(stop_time, total_time)
if delta.total_seconds() > error:
episode = episode_number
else:
episode = str(int(episode_number) + 1)
stop_time = "0"
total_time = "0"
config.update_watch_history(
anime_id, episode, start_time=stop_time, total_time=total_time
)
# switch to controls
clear()
@@ -249,8 +300,11 @@ def fetch_episode(config: Config, anilist_config: QueryDict):
# prompt for episode number
episodes = anime["availableEpisodesDetail"][translation_type]
if continue_from_history and user_watch_history.get(str(anime_id)) in episodes:
episode_number = user_watch_history[str(anime_id)]
if (
continue_from_history
and user_watch_history.get(str(anime_id), {}).get("episode") in episodes
):
episode_number = user_watch_history[str(anime_id)]["episode"]
print(f"[bold cyan]Continuing from Episode:[/] [bold]{episode_number}[/]")
else:
choices = [*episodes, "Back"]
@@ -266,7 +320,8 @@ def fetch_episode(config: Config, anilist_config: QueryDict):
if episode_number == "Back":
anilist_options(config, anilist_config)
return
config.update_watch_history(anime_id, episode_number)
start_time = user_watch_history.get(str(anime_id), {}).get("start_time", "0")
config.update_watch_history(anime_id, episode_number, start_time=start_time)
# update internal config
anilist_config.episodes = episodes

View File

@@ -3,7 +3,6 @@ import shutil
import subprocess
from typing import Optional
# legacy
# def mpv(link, title: None | str = "anime", *custom_args):
# MPV = shutil.which("mpv")
@@ -25,8 +24,50 @@ from typing import Optional
# else:
# subprocess.run([MPV, *custom_args, f"--title={title}", link])
#
#
def mpv(link: str, title: Optional[str] = "anime", *custom_args):
def stream_video(url, mpv_args):
process = subprocess.Popen(
["mpv", url, *mpv_args],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
last_time = None
av_time_pattern = re.compile(r"AV: ([0-9:]*) / ([0-9:]*) \(([0-9]*)%\)")
last_time = "0"
total_time = "0"
try:
while True:
output = process.stderr.readline()
if output:
# Match the timestamp in the output
match = av_time_pattern.search(output.strip())
if match:
current_time = match.group(1)
total_time = match.group(2)
match.group(3)
last_time = current_time
# print(f"Current stream time: {current_time}, Total time: {total_time}, Progress: {percentage}%")
# Check if the process has terminated
retcode = process.poll()
if retcode is not None:
print("Finshed at: ", last_time)
break
except Exception as e:
print(f"An error occurred: {e}")
finally:
process.terminate()
return last_time, total_time
def mpv(link: str, title: Optional[str] = "anime", start_time: str = "0", *custom_args):
# Determine if mpv is available
MPV = shutil.which("mpv")
@@ -54,6 +95,7 @@ def mpv(link: str, title: Optional[str] = "anime", *custom_args):
"-n",
"com.google.android.youtube/.UrlActivity",
]
return "0"
else:
# Android specific commands to launch mpv with a regular URL
args = [
@@ -71,10 +113,12 @@ def mpv(link: str, title: Optional[str] = "anime", *custom_args):
]
subprocess.run(args)
return "0"
else:
# General mpv command with custom arguments
mpv_args = [MPV, *custom_args, f"--title={title}", link]
subprocess.run(mpv_args)
mpv_args = [*custom_args, f"--title={title}", f"--start={start_time}"]
stop_time, total_time = stream_video(link, mpv_args)
return stop_time, total_time
# Example usage