Files
FastAnime/fastanime/libs/player/mpv/player.py

171 lines
5.5 KiB
Python

import logging
import re
import shutil
import subprocess
from ....core.config import MpvConfig
from ....core.exceptions import FastAnimeError
from ....core.patterns import TORRENT_REGEX, YOUTUBE_REGEX
from ....core.utils import detect
from ..base import BasePlayer
from ..params import PlayerParams
from ..types import PlayerResult
logger = logging.getLogger(__name__)
MPV_AV_TIME_PATTERN = re.compile(r"AV: ([0-9:]*) / ([0-9:]*) \(([0-9]*)%\)")
class MpvPlayer(BasePlayer):
def __init__(self, config: MpvConfig):
self.config = config
self.executable = shutil.which("mpv")
def play(self, params):
if TORRENT_REGEX.match(params.url) and detect.is_running_in_termux():
raise FastAnimeError("Unable to play torrents on termux")
elif params.syncplay and detect.is_running_in_termux():
raise FastAnimeError("Unable to play torrents on termux")
elif detect.is_running_in_termux():
return self._play_on_mobile(params)
else:
return self._play_on_desktop(params)
def _play_on_mobile(self, params) -> PlayerResult:
if YOUTUBE_REGEX.match(params.url):
args = [
"nohup",
"am",
"start",
"--user",
"0",
"-a",
"android.intent.action.VIEW",
"-d",
params.url,
"-n",
"com.google.android.youtube/.UrlActivity",
]
else:
args = [
"nohup",
"am",
"start",
"--user",
"0",
"-a",
"android.intent.action.VIEW",
"-d",
params.url,
"-n",
"is.xyz.mpv/.MPVActivity",
]
subprocess.run(args)
return PlayerResult()
def _play_on_desktop(self, params) -> PlayerResult:
if not self.executable:
raise FastAnimeError("MPV executable not found in PATH.")
if TORRENT_REGEX.search(params.url):
return self._stream_on_desktop_with_webtorrent_cli(params)
elif params.syncplay:
return self._stream_on_desktop_with_syncplay(params)
elif self.config.use_python_mpv:
return self._stream_on_desktop_with_python_mpv(params)
else:
return self._stream_on_desktop_with_subprocess(params)
def _stream_on_desktop_with_subprocess(self, params: PlayerParams) -> PlayerResult:
mpv_args = [self.executable, params.url]
mpv_args.extend(self._create_mpv_cli_options(params))
pre_args = self.config.pre_args.split(",") if self.config.pre_args else []
stop_time = None
total_time = None
proc = subprocess.run(
pre_args + mpv_args,
capture_output=True,
text=True,
encoding="utf-8",
check=False,
)
if proc.stdout:
for line in reversed(proc.stdout.split("\n")):
match = MPV_AV_TIME_PATTERN.search(line.strip())
if match:
stop_time = match.group(1)
total_time = match.group(2)
break
return PlayerResult(total_time=total_time, stop_time=stop_time)
def _stream_on_desktop_with_python_mpv(self, params: PlayerParams) -> PlayerResult:
return PlayerResult()
def _stream_on_desktop_with_webtorrent_cli(
self, params: PlayerParams
) -> PlayerResult:
WEBTORRENT_CLI = shutil.which("webtorrent")
if not WEBTORRENT_CLI:
raise FastAnimeError(
"Please Install webtorrent cli inorder to stream torrents"
)
args = [WEBTORRENT_CLI, params.url, "--mpv"]
if mpv_args := self._create_mpv_cli_options(params):
args.append("--player-args")
args.extend(mpv_args)
subprocess.run(args)
return PlayerResult()
# TODO: Get people with real friends to do this lol
def _stream_on_desktop_with_syncplay(self, params: PlayerParams) -> PlayerResult:
SYNCPLAY_EXECUTABLE = shutil.which("syncplay")
if not SYNCPLAY_EXECUTABLE:
raise FastAnimeError(
"Please install syncplay to be able to stream with your friends"
)
args = [SYNCPLAY_EXECUTABLE, params.url]
if mpv_args := self._create_mpv_cli_options(params):
args.append("--")
args.extend(mpv_args)
subprocess.run(args)
return PlayerResult()
def _create_mpv_cli_options(self, params: PlayerParams) -> list[str]:
mpv_args = []
if params.headers:
header_str = ",".join([f"{k}:{v}" for k, v in params.headers.items()])
mpv_args.append(f"--http-header-fields={header_str}")
if params.subtitles:
for sub in params.subtitles:
mpv_args.append(f"--sub-file={sub}")
if params.start_time:
mpv_args.append(f"--start={params.start_time}")
if params.title:
mpv_args.append(f"--title={params.title}")
if self.config.args:
mpv_args.extend(self.config.args.split(","))
return mpv_args
if __name__ == "__main__":
from ....core.constants import APP_ASCII_ART
print(APP_ASCII_ART)
url = input("Enter the url you would like to stream: ")
mpv = MpvPlayer(MpvConfig())
player_result = mpv.play(PlayerParams(url=url, title=""))
print(player_result)