mirror of
https://github.com/Benexl/FastAnime.git
synced 2025-12-12 15:50:01 -08:00
feat: init python mpv intergration for next and prev episode
This commit is contained in:
@@ -14,7 +14,7 @@ if TYPE_CHECKING:
|
||||
def downloads(config: "Config", path: bool):
|
||||
import os
|
||||
|
||||
from ...cli.utils.mpv import mpv
|
||||
from ...cli.utils.mpv import run_mpv
|
||||
from ...libs.fzf import fzf
|
||||
from ...libs.rofi import Rofi
|
||||
from ..utils.tools import exit_app
|
||||
@@ -41,7 +41,7 @@ def downloads(config: "Config", path: bool):
|
||||
exit_app()
|
||||
return
|
||||
playlist = os.path.join(USER_VIDEOS_DIR, playlist_name)
|
||||
mpv(playlist)
|
||||
run_mpv(playlist)
|
||||
stream()
|
||||
|
||||
stream()
|
||||
|
||||
@@ -23,7 +23,7 @@ def search(config: Config, anime_title: str, episode_range: str):
|
||||
from ...libs.anime_provider.types import Anime
|
||||
from ...libs.fzf import fzf
|
||||
from ...libs.rofi import Rofi
|
||||
from ..utils.mpv import mpv
|
||||
from ..utils.mpv import run_mpv
|
||||
from ..utils.tools import exit_app
|
||||
from ..utils.utils import clear, fuzzy_inquirer
|
||||
|
||||
@@ -138,7 +138,7 @@ def search(config: Config, anime_title: str, episode_range: str):
|
||||
|
||||
print(f"[purple]Now Playing:[/] {search_result} Episode {episode}")
|
||||
|
||||
mpv(link, search_result)
|
||||
run_mpv(link, search_result)
|
||||
stream_anime()
|
||||
|
||||
stream_anime()
|
||||
|
||||
@@ -47,6 +47,7 @@ class Config(object):
|
||||
"rofi_theme": "",
|
||||
"rofi_theme_input": "",
|
||||
"rofi_theme_confirm": "",
|
||||
"use_mpv_mod": "true",
|
||||
}
|
||||
)
|
||||
self.configparser.add_section("stream")
|
||||
@@ -71,6 +72,7 @@ class Config(object):
|
||||
self.continue_from_history = self.get_continue_from_history()
|
||||
self.auto_next = self.get_auto_next()
|
||||
self.auto_select = self.get_auto_select()
|
||||
self.use_mpv_mod = self.get_use_mpv_mod()
|
||||
self.quality = self.get_quality()
|
||||
self.notification_duration = self.get_notification_duration()
|
||||
self.error = self.get_error()
|
||||
@@ -170,6 +172,9 @@ class Config(object):
|
||||
def get_quality(self):
|
||||
return self.configparser.getint("stream", "quality")
|
||||
|
||||
def get_use_mpv_mod(self):
|
||||
return self.configparser.getboolean("stream", "use_mpv_mod")
|
||||
|
||||
def get_notification_duration(self):
|
||||
return self.configparser.getint("general", "notification_duration")
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@ from ...libs.fzf import fzf
|
||||
from ...libs.rofi import Rofi
|
||||
from ...Utility.data import anime_normalizer
|
||||
from ...Utility.utils import anime_title_percentage_match, sanitize_filename
|
||||
from ..utils.mpv import mpv
|
||||
from ..utils.mpv import run_mpv
|
||||
from ..utils.player import player
|
||||
from ..utils.tools import QueryDict, exit_app
|
||||
from ..utils.utils import clear, fuzzy_inquirer
|
||||
from .utils import aniskip
|
||||
@@ -75,7 +76,7 @@ def player_controls(config: "Config", anilist_config: QueryDict):
|
||||
anilist_config.selected_anime_anilist["idMal"], current_episode
|
||||
):
|
||||
custom_args = args
|
||||
stop_time, total_time = mpv(
|
||||
stop_time, total_time = run_mpv(
|
||||
current_link,
|
||||
selected_server["episode_title"],
|
||||
start_time=start_time,
|
||||
@@ -341,18 +342,28 @@ def fetch_streams(config: "Config", anilist_config: QueryDict):
|
||||
if start_time != "0":
|
||||
print("[green]Continuing from:[/] ", start_time)
|
||||
custom_args = []
|
||||
if config.skip:
|
||||
if args := aniskip(
|
||||
anilist_config.selected_anime_anilist["idMal"], episode_number
|
||||
):
|
||||
custom_args = args
|
||||
if config.use_mpv_mod:
|
||||
mpv = player.create_player(
|
||||
anime_provider, anilist_config, config, selected_server["episode_title"]
|
||||
)
|
||||
mpv.play(stream_link)
|
||||
mpv.wait_for_shutdown()
|
||||
mpv.terminate()
|
||||
stop_time = player.last_stop_time
|
||||
total_time = player.last_total_time
|
||||
|
||||
stop_time, total_time = mpv(
|
||||
stream_link,
|
||||
selected_server["episode_title"],
|
||||
start_time=start_time,
|
||||
custom_args=custom_args,
|
||||
)
|
||||
else:
|
||||
if config.skip:
|
||||
if args := aniskip(
|
||||
anilist_config.selected_anime_anilist["idMal"], episode_number
|
||||
):
|
||||
custom_args.extend(args)
|
||||
stop_time, total_time = run_mpv(
|
||||
stream_link,
|
||||
selected_server["episode_title"],
|
||||
start_time=start_time,
|
||||
custom_args=custom_args,
|
||||
)
|
||||
print("Finished at: ", stop_time)
|
||||
|
||||
# update_watch_history
|
||||
@@ -541,7 +552,7 @@ def anilist_options(config, anilist_config: QueryDict):
|
||||
if trailer := selected_anime.get("trailer"):
|
||||
trailer_url = "https://youtube.com/watch?v=" + trailer["id"]
|
||||
print("[bold magenta]Watching Trailer of:[/]", selected_anime_title)
|
||||
mpv(
|
||||
run_mpv(
|
||||
trailer_url,
|
||||
ytdl_format=config.format,
|
||||
)
|
||||
|
||||
@@ -1,29 +1,6 @@
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
from typing import Optional
|
||||
|
||||
# legacy
|
||||
# def mpv(link, title: None | str = "anime", *custom_args):
|
||||
# MPV = shutil.which("mpv")
|
||||
# if not MPV:
|
||||
# args = [
|
||||
# "nohup",
|
||||
# "am",
|
||||
# "start",
|
||||
# "--user",
|
||||
# "0",
|
||||
# "-a",
|
||||
# "android.intent.action.VIEW",
|
||||
# "-d",
|
||||
# link,
|
||||
# "-n",
|
||||
# "is.xyz.mpv/.MPVActivity",
|
||||
# ]
|
||||
# subprocess.run(args)
|
||||
# else:
|
||||
# subprocess.run([MPV, *custom_args, f"--title={title}", link])
|
||||
#
|
||||
|
||||
|
||||
def stream_video(MPV, url, mpv_args, custom_args):
|
||||
@@ -69,9 +46,9 @@ def stream_video(MPV, url, mpv_args, custom_args):
|
||||
return last_time, total_time
|
||||
|
||||
|
||||
def mpv(
|
||||
def run_mpv(
|
||||
link: str,
|
||||
title: Optional[str] = "",
|
||||
title: str | None = "",
|
||||
start_time: str = "0",
|
||||
ytdl_format="",
|
||||
custom_args=[],
|
||||
@@ -135,7 +112,7 @@ def mpv(
|
||||
|
||||
# Example usage
|
||||
if __name__ == "__main__":
|
||||
mpv(
|
||||
run_mpv(
|
||||
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
||||
"Example Video",
|
||||
"--fullscreen",
|
||||
|
||||
133
fastanime/cli/utils/player.py
Normal file
133
fastanime/cli/utils/player.py
Normal file
@@ -0,0 +1,133 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import mpv
|
||||
|
||||
from ...anilist import AniList
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Literal
|
||||
|
||||
from ...AnimeProvider import AnimeProvider
|
||||
from ..config import Config
|
||||
|
||||
|
||||
def format_time(duration_in_secs: float):
|
||||
h = duration_in_secs // 3600
|
||||
m = duration_in_secs // 60
|
||||
s = duration_in_secs - ((h * 3600) + (m * 60))
|
||||
return f"{int(h):2d}:{int(m):2d}:{int(s):2d}".replace(" ", "0")
|
||||
|
||||
|
||||
class MpvPlayer(object):
|
||||
anime_provider: "AnimeProvider"
|
||||
config: "Config"
|
||||
mpv_player: "mpv.MPV"
|
||||
last_stop_time: str = "0"
|
||||
last_total_time: str = "0"
|
||||
last_stop_time_secs = 0
|
||||
last_total_time_secs = 0
|
||||
current_media_title = ""
|
||||
|
||||
def get_episode(self, type: "Literal['next','previous']"):
|
||||
anilist_config = self.anilist_config
|
||||
config = self.config
|
||||
episode_number: str = anilist_config.episode_number
|
||||
quality = config.quality
|
||||
episodes: list = sorted(anilist_config.episodes, key=float)
|
||||
anime_id: int = anilist_config.anime_id
|
||||
anime = anilist_config.anime
|
||||
translation_type = config.translation_type
|
||||
anime_provider = config.anime_provider
|
||||
|
||||
if type == "next":
|
||||
next_episode = episodes.index(episode_number) + 1
|
||||
if next_episode >= len(episodes):
|
||||
next_episode = len(episodes) - 1
|
||||
anilist_config.episode_number = episodes[next_episode]
|
||||
episode_number = anilist_config.episode_number
|
||||
config.update_watch_history(anime_id, episodes[next_episode])
|
||||
else:
|
||||
prev_episode = episodes.index(episode_number) - 1
|
||||
if prev_episode <= 0:
|
||||
prev_episode = 0
|
||||
anilist_config.episode_number = episodes[prev_episode]
|
||||
episode_number = anilist_config.episode_number
|
||||
config.update_watch_history(anime_id, episodes[prev_episode])
|
||||
if config.user and episode_number:
|
||||
AniList.update_anime_list(
|
||||
{
|
||||
"mediaId": anime_id,
|
||||
"progress": episode_number,
|
||||
}
|
||||
)
|
||||
episode_streams = anime_provider.get_episode_streams(
|
||||
anime,
|
||||
episode_number,
|
||||
translation_type,
|
||||
anilist_config.selected_anime_anilist,
|
||||
)
|
||||
if not episode_streams:
|
||||
self.mpv_player.print_text("No streams were found")
|
||||
return None
|
||||
|
||||
selected_server = next(episode_streams)
|
||||
self.current_media_title = selected_server["episode_title"]
|
||||
self.mpv_player.script_message(f"{self.current_media_title}")
|
||||
links = selected_server["links"]
|
||||
if quality > len(links) - 1:
|
||||
quality = config.quality = len(links) - 1
|
||||
elif quality < 0:
|
||||
quality = config.quality = 0
|
||||
stream_link = links[quality]["link"]
|
||||
return stream_link
|
||||
|
||||
def create_player(
|
||||
self, anime_provider: "AnimeProvider", anilist_config, config: "Config", title
|
||||
):
|
||||
self.anime_provider = anime_provider
|
||||
self.anilist_config = anilist_config
|
||||
self.config = config
|
||||
mpv_player = mpv.MPV(
|
||||
config=True,
|
||||
input_default_bindings=True,
|
||||
input_vo_keyboard=True,
|
||||
osc=True,
|
||||
ytdl=True,
|
||||
)
|
||||
mpv_player.title = title
|
||||
|
||||
@mpv_player.on_key_press("shift+n")
|
||||
def _next_episode():
|
||||
url = self.get_episode("next")
|
||||
if url:
|
||||
mpv_player.loadfile(url, options=f"title={self.current_media_title}")
|
||||
mpv_player.title = self.current_media_title
|
||||
|
||||
@mpv_player.on_key_press("shift+p")
|
||||
def _previous_episode():
|
||||
url = self.get_episode("previous")
|
||||
if url:
|
||||
mpv_player.loadfile(url, options=f"title={self.current_media_title}")
|
||||
mpv_player.title = self.current_media_title
|
||||
|
||||
@mpv_player.property_observer("time-pos")
|
||||
def handle_time_start_update(*args):
|
||||
if len(args) > 1:
|
||||
value = args[1]
|
||||
if value is not None:
|
||||
self.last_stop_time = format_time(value)
|
||||
|
||||
@mpv_player.property_observer("time-remaining")
|
||||
def handle_time_remaining_update(*args):
|
||||
if len(args) > 1:
|
||||
value = args[1]
|
||||
if value is not None:
|
||||
self.last_total_time = format_time(value)
|
||||
|
||||
mpv_player.observe_property("time-pos", handle_time_start_update)
|
||||
mpv_player.observe_property("time-remaining", handle_time_remaining_update)
|
||||
self.mpv_player = mpv_player
|
||||
return mpv_player
|
||||
|
||||
|
||||
player = MpvPlayer()
|
||||
Reference in New Issue
Block a user