From bb14b269de617c593dcb95297a2cee955523e40c Mon Sep 17 00:00:00 2001 From: Benex254 Date: Wed, 18 Sep 2024 19:39:06 +0300 Subject: [PATCH] feat: add --player option --- fastanime/cli/__init__.py | 9 + fastanime/cli/commands/downloads.py | 10 +- fastanime/cli/commands/search.py | 1 + fastanime/cli/config.py | 14 +- .../cli/interfaces/anilist_interfaces.py | 3 + fastanime/cli/utils/mpv.py | 161 ++++++++++++------ fastanime/cli/utils/scripts.py | 2 +- 7 files changed, 140 insertions(+), 60 deletions(-) diff --git a/fastanime/cli/__init__.py b/fastanime/cli/__init__.py index 416ac29..995e033 100644 --- a/fastanime/cli/__init__.py +++ b/fastanime/cli/__init__.py @@ -148,6 +148,12 @@ signal.signal(signal.SIGINT, handle_exit) "--use-python-mpv/--use-default-player", help="Whether to use python-mpv", type=bool ) @click.option("--sync-play", "-sp", help="Use sync play", is_flag=True) +@click.option( + "--player", + "-P", + help="the player to use when streaming", + type=click.Choice(["mpv", "vlc"]), +) @click.pass_context def run_cli( ctx: click.Context, @@ -181,6 +187,7 @@ def run_cli( rofi_theme_input, use_python_mpv, sync_play, + player, ): from .config import Config @@ -235,6 +242,8 @@ def run_cli( ctx.obj.sub_lang = sub_lang if ctx.get_parameter_source("continue_") == click.core.ParameterSource.COMMANDLINE: ctx.obj.continue_from_history = continue_ + if ctx.get_parameter_source("player") == click.core.ParameterSource.COMMANDLINE: + ctx.obj.player = player if ctx.get_parameter_source("skip") == click.core.ParameterSource.COMMANDLINE: ctx.obj.skip = skip if ( diff --git a/fastanime/cli/commands/downloads.py b/fastanime/cli/commands/downloads.py index b2df44c..53ea6f7 100644 --- a/fastanime/cli/commands/downloads.py +++ b/fastanime/cli/commands/downloads.py @@ -279,7 +279,10 @@ def downloads( SyncPlayer(episode_path) else: - run_mpv(episode_path) + run_mpv( + episode_path, + player=config.player, + ) stream_episode(anime_playlist_path) def stream_anime(title=None): @@ -321,7 +324,10 @@ def downloads( SyncPlayer(playlist) else: - run_mpv(playlist) + run_mpv( + playlist, + player=config.player, + ) stream_anime() stream_anime(title) diff --git a/fastanime/cli/commands/search.py b/fastanime/cli/commands/search.py index c119dba..c8a7271 100644 --- a/fastanime/cli/commands/search.py +++ b/fastanime/cli/commands/search.py @@ -352,6 +352,7 @@ def search(config: "Config", anime_titles: str, episode_range: str): episode_title, headers=stream_headers, subtitles=subtitles, + player=config.player, ) except IndexError as e: print(e) diff --git a/fastanime/cli/config.py b/fastanime/cli/config.py index 0141b5e..265a6c5 100644 --- a/fastanime/cli/config.py +++ b/fastanime/cli/config.py @@ -50,6 +50,7 @@ class Config(object): "ffmpegthumnailer_seek_time": "-1", "sub_lang": "eng", "normalize_titles": "true", + "player": "mpv", } def __init__(self) -> None: @@ -64,7 +65,7 @@ class Config(object): # --- set config values from file or using defaults --- if os.path.exists(USER_CONFIG_PATH): - self.configparser.read(USER_CONFIG_PATH,encoding="utf-8") + self.configparser.read(USER_CONFIG_PATH, encoding="utf-8") self.downloads_dir = self.get_downloads_dir() self.sub_lang = self.get_sub_lang() @@ -86,6 +87,7 @@ class Config(object): self.error = self.get_error() self.server = self.get_server() self.format = self.get_format() + self.player = self.get_player() self.force_window = self.get_force_window() self.preferred_language = self.get_preferred_language() self.preferred_history = self.get_preferred_history() @@ -103,7 +105,7 @@ class Config(object): os.environ["CURRENT_FASTANIME_PROVIDER"] = self.provider if not os.path.exists(USER_CONFIG_PATH): - with open(USER_CONFIG_PATH, "w",encoding="utf-8") as config: + with open(USER_CONFIG_PATH, "w", encoding="utf-8") as config: config.write(self.__repr__()) def update_user(self, user): @@ -223,6 +225,9 @@ class Config(object): def get_format(self): return self.configparser.get("stream", "format") + def get_player(self): + return self.configparser.get("stream", "player") + def get_sort_by(self): return self.configparser.get("anilist", "sort_by") @@ -409,6 +414,11 @@ force_window = immediate # this is because they provider a m3u8 file that contans multiple quality streams format = {self.format} +# set the player to use for streaming [mpv/vlc] +# while this option exists i will still recommend that you use mpv +# since you will miss out on some features if you use the others +player = {self.player} + # NOTE: # if you have any trouble setting up your config # please don't be afraid to ask in our discord diff --git a/fastanime/cli/interfaces/anilist_interfaces.py b/fastanime/cli/interfaces/anilist_interfaces.py index 0d0c739..b75ad98 100644 --- a/fastanime/cli/interfaces/anilist_interfaces.py +++ b/fastanime/cli/interfaces/anilist_interfaces.py @@ -164,6 +164,7 @@ def media_player_controls( custom_args=custom_args, headers=selected_server["headers"], subtitles=subtitles, + player=config.player, ) # either update the watch history to the next episode or current depending on progress @@ -574,6 +575,7 @@ def provider_anime_episode_servers_menu( custom_args=custom_args, headers=selected_server["headers"], subtitles=subtitles, + player=config.player, ) print("Finished at: ", stop_time) @@ -893,6 +895,7 @@ def media_actions_menu( run_mpv( trailer_url, ytdl_format=config.format, + player=config.player, ) media_actions_menu(config, fastanime_runtime_state) else: diff --git a/fastanime/cli/utils/mpv.py b/fastanime/cli/utils/mpv.py index 620675f..5fc5f1b 100644 --- a/fastanime/cli/utils/mpv.py +++ b/fastanime/cli/utils/mpv.py @@ -50,75 +50,126 @@ def stream_video(MPV, url, mpv_args, custom_args): def run_mpv( link: str, - title: str | None = "", + title: str = "", start_time: str = "0", ytdl_format="", custom_args=[], headers={}, subtitles=[], + player="", ): - # Determine if mpv is available - MPV = shutil.which("mpv") - # If title is None, set a default value # Regex to check if the link is a YouTube URL youtube_regex = r"(https?://)?(www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/.+" - if not MPV and not S_PLATFORM == "win32": - # Determine if the link is a YouTube URL - if re.match(youtube_regex, link): - # Android specific commands to launch mpv with a YouTube URL - args = [ - "nohup", - "am", - "start", - "--user", - "0", - "-a", - "android.intent.action.VIEW", - "-d", - link, - "-n", - "com.google.android.youtube/.UrlActivity", - ] + if player == "vlc": + VLC = shutil.which("vlc") + if not VLC and not S_PLATFORM == "win32": + # Determine if the link is a YouTube URL + if re.match(youtube_regex, link): + # Android specific commands to launch mpv with a YouTube URL + args = [ + "nohup", + "am", + "start", + "--user", + "0", + "-a", + "android.intent.action.VIEW", + "-d", + link, + "-n", + "com.google.android.youtube/.UrlActivity", + ] + return "0", "0" + else: + args = [ + "nohup", + "am", + "start", + "--user", + "0", + "-a", + "android.intent.action.VIEW" "-d", + link, + "-n", + "org.videolan.vlc/org.videolan.vlc.gui.video.VideoPlayerActivity", + "-e", + "title", + title, + ] + + subprocess.run(args) return "0", "0" else: - # Android specific commands to launch mpv with a regular URL - args = [ - "nohup", - "am", - "start", - "--user", - "0", - "-a", - "android.intent.action.VIEW", - "-d", - link, - "-n", - "is.xyz.mpv/.MPVActivity", - ] - - subprocess.run(args) - return "0", "0" + args = ["vlc", link] + for subtitle in subtitles: + args.append("--sub-file") + args.append(subtitle["url"]) + break + if title: + args.append("--video-title") + args.append(title) + subprocess.run(args) + return "0", "0" else: - # General mpv command with custom arguments - mpv_args = [] - if headers: - mpv_headers = "--http-header-fields=" - for header_name, header_value in headers.items(): - mpv_headers += f"{header_name}:{header_value}," - mpv_args.append(mpv_headers) - for subtitle in subtitles: - mpv_args.append(f"--sub-file={subtitle['url']}") - if start_time != "0": - mpv_args.append(f"--start={start_time}") - if title: - mpv_args.append(f"--title={title}") - if ytdl_format: - mpv_args.append(f"--ytdl-format={ytdl_format}") - stop_time, total_time = stream_video(MPV, link, mpv_args, custom_args) - return stop_time, total_time + # Determine if mpv is available + MPV = shutil.which("mpv") + if not MPV and not S_PLATFORM == "win32": + # Determine if the link is a YouTube URL + if re.match(youtube_regex, link): + # Android specific commands to launch mpv with a YouTube URL + args = [ + "nohup", + "am", + "start", + "--user", + "0", + "-a", + "android.intent.action.VIEW", + "-d", + link, + "-n", + "com.google.android.youtube/.UrlActivity", + ] + return "0", "0" + else: + # Android specific commands to launch mpv with a regular URL + args = [ + "nohup", + "am", + "start", + "--user", + "0", + "-a", + "android.intent.action.VIEW", + "-d", + link, + "-n", + "is.xyz.mpv/.MPVActivity", + ] + + subprocess.run(args) + return "0", "0" + else: + # General mpv command with custom arguments + mpv_args = [] + if headers: + mpv_headers = "--http-header-fields=" + for header_name, header_value in headers.items(): + mpv_headers += f"{header_name}:{header_value}," + mpv_args.append(mpv_headers) + for subtitle in subtitles: + mpv_args.append(f"--sub-file={subtitle['url']}") + if start_time != "0": + mpv_args.append(f"--start={start_time}") + if title: + mpv_args.append(f"--title={title}") + if ytdl_format: + mpv_args.append(f"--ytdl-format={ytdl_format}") + stop_time, total_time = stream_video(MPV, link, mpv_args, custom_args) + return stop_time, total_time # Example usage diff --git a/fastanime/cli/utils/scripts.py b/fastanime/cli/utils/scripts.py index 91676e1..da6b1be 100644 --- a/fastanime/cli/utils/scripts.py +++ b/fastanime/cli/utils/scripts.py @@ -18,7 +18,7 @@ fzf-preview() { fi # 1. Use kitty icat on kitty terminal - if [[ $KITTY_WINDOW_ID ]] && false; then + if [[ $KITTY_WINDOW_ID ]]; then # 1. 'memory' is the fastest option but if you want the image to be scrollable, # you have to use 'stream'. #