Skip to content

Commit

Permalink
Merge branch 'devine-dl:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Sp5rky authored Apr 25, 2024
2 parents 5ed8d0b + af95ba0 commit 909dce4
Show file tree
Hide file tree
Showing 15 changed files with 130 additions and 80 deletions.
29 changes: 18 additions & 11 deletions devine/commands/dl.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from rich.text import Text
from rich.tree import Tree

from devine.core import binaries
from devine.core.config import config
from devine.core.console import console
from devine.core.constants import DOWNLOAD_LICENCE_ONLY, AnyTrack, context_settings
Expand All @@ -51,7 +52,7 @@
from devine.core.titles.episode import Episode
from devine.core.tracks import Audio, Subtitle, Tracks, Video
from devine.core.tracks.attachment import Attachment
from devine.core.utilities import get_binary_path, get_system_fonts, is_close_match, time_elapsed_since
from devine.core.utilities import get_system_fonts, is_close_match, time_elapsed_since
from devine.core.utils.click_types import LANGUAGE_RANGE, QUALITY_LIST, SEASON_RANGE, ContextData, MultipleChoice
from devine.core.utils.collections import merge_dict
from devine.core.utils.subprocess import ffprobe
Expand Down Expand Up @@ -198,7 +199,7 @@ def __init__(
self.proxy_providers.append(Basic(**config.proxy_providers["basic"]))
if config.proxy_providers.get("nordvpn"):
self.proxy_providers.append(NordVPN(**config.proxy_providers["nordvpn"]))
if get_binary_path("hola-proxy"):
if binaries.HolaProxy:
self.proxy_providers.append(Hola())
for proxy_provider in self.proxy_providers:
self.log.info(f"Loaded {proxy_provider.__class__.__name__}: {proxy_provider}")
Expand Down Expand Up @@ -558,14 +559,17 @@ def result(
except Exception as e: # noqa
error_messages = [
":x: Download Failed...",
" One of the track downloads had an error!",
" See the error trace above for more information."
]
if isinstance(e, subprocess.CalledProcessError):
# ignore process exceptions as proper error logs are already shown
error_messages.append(f" Process exit code: {e.returncode}")
if isinstance(e, EnvironmentError):
error_messages.append(f" {e}")
else:
console.print_exception()
error_messages.append(" An unexpected error occurred in one of the download workers.",)
if hasattr(e, "returncode"):
error_messages.append(f" Binary call failed, Process exit code: {e.returncode}")
error_messages.append(" See the error trace above for more information.")
if isinstance(e, subprocess.CalledProcessError):
# CalledProcessError already lists the exception trace
console.print_exception()
console.print(Padding(
Group(*error_messages),
(1, 5)
Expand Down Expand Up @@ -622,11 +626,14 @@ def result(
break
video_track_n += 1

if sub_format:
with console.status(f"Converting Subtitles to {sub_format.name}..."):
for subtitle in title.tracks.subtitles:
with console.status("Converting Subtitles..."):
for subtitle in title.tracks.subtitles:
if sub_format:
if subtitle.codec != sub_format:
subtitle.convert(sub_format)
elif subtitle.codec == Subtitle.Codec.TimedTextMarkupLang:
# MKV does not support TTML, VTT is the next best option
subtitle.convert(Subtitle.Codec.WebVTT)

with console.status("Checking Subtitles for Fonts..."):
font_names = []
Expand Down
13 changes: 13 additions & 0 deletions devine/commands/env.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import logging
import os
import shutil
import sys
from pathlib import Path
from typing import Optional

import click
Expand Down Expand Up @@ -38,10 +41,20 @@ def info() -> None:
table.add_column("Name", no_wrap=True)
table.add_column("Path")

path_vars = {
x: Path(os.getenv(x))
for x in ("TEMP", "APPDATA", "LOCALAPPDATA", "USERPROFILE")
if sys.platform == "win32" and os.getenv(x)
}

for name in sorted(dir(config.directories)):
if name.startswith("__") or name == "app_dirs":
continue
path = getattr(config.directories, name).resolve()
for var, var_path in path_vars.items():
if path.is_relative_to(var_path):
path = rf"%{var}%\{path.relative_to(var_path)}"
break
table.add_row(name.title(), str(path))

console.print(Padding(
Expand Down
4 changes: 2 additions & 2 deletions devine/commands/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
from rich.tree import Tree

from devine.commands.dl import dl
from devine.core import binaries
from devine.core.config import config
from devine.core.console import console
from devine.core.constants import context_settings
from devine.core.proxies import Basic, Hola, NordVPN
from devine.core.service import Service
from devine.core.services import Services
from devine.core.utilities import get_binary_path
from devine.core.utils.click_types import ContextData
from devine.core.utils.collections import merge_dict

Expand Down Expand Up @@ -72,7 +72,7 @@ def search(
proxy_providers.append(Basic(**config.proxy_providers["basic"]))
if config.proxy_providers.get("nordvpn"):
proxy_providers.append(NordVPN(**config.proxy_providers["nordvpn"]))
if get_binary_path("hola-proxy"):
if binaries.HolaProxy:
proxy_providers.append(Hola())
for proxy_provider in proxy_providers:
log.info(f"Loaded {proxy_provider.__class__.__name__}: {proxy_provider}")
Expand Down
7 changes: 3 additions & 4 deletions devine/commands/serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import click

from devine.core import binaries
from devine.core.config import config
from devine.core.constants import context_settings
from devine.core.utilities import get_binary_path


@click.command(
Expand All @@ -29,11 +29,10 @@ def serve(host: str, port: int, caddy: bool) -> None:
from pywidevine import serve

if caddy:
executable = get_binary_path("caddy")
if not executable:
if not binaries.Caddy:
raise click.ClickException("Caddy executable \"caddy\" not found but is required for --caddy.")
caddy_p = subprocess.Popen([
executable,
binaries.Caddy,
"run",
"--config", str(config.directories.user_configs / "Caddyfile")
])
Expand Down
21 changes: 9 additions & 12 deletions devine/commands/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import click
from pymediainfo import MediaInfo

from devine.core import binaries
from devine.core.constants import context_settings
from devine.core.utilities import get_binary_path


@click.group(short_help="Various helper scripts and programs.", context_settings=context_settings)
Expand Down Expand Up @@ -38,8 +38,7 @@ def crop(path: Path, aspect: str, letter: bool, offset: int, preview: bool) -> N
as it may go from being 2px away from a perfect crop, to 20px over-cropping
again due to sub-sampled chroma.
"""
executable = get_binary_path("ffmpeg")
if not executable:
if not binaries.FFMPEG:
raise click.ClickException("FFmpeg executable \"ffmpeg\" not found but is required.")

if path.is_dir():
Expand Down Expand Up @@ -87,15 +86,15 @@ def crop(path: Path, aspect: str, letter: bool, offset: int, preview: bool) -> N
]))))]

ffmpeg_call = subprocess.Popen([
executable, "-y",
binaries.FFMPEG, "-y",
"-i", str(video_path),
"-map", "0:v:0",
"-c", "copy",
"-bsf:v", crop_filter
] + out_path, stdout=subprocess.PIPE)
try:
if preview:
previewer = get_binary_path("mpv", "ffplay")
previewer = binaries.MPV or binaries.FFPlay
if not previewer:
raise click.ClickException("MPV/FFplay executables weren't found but are required for previewing.")
subprocess.Popen((previewer, "-"), stdin=ffmpeg_call.stdout)
Expand All @@ -120,8 +119,7 @@ def range_(path: Path, full: bool, preview: bool) -> None:
then you're video may have the range set to the wrong value. Flip its range to the
opposite value and see if that fixes it.
"""
executable = get_binary_path("ffmpeg")
if not executable:
if not binaries.FFMPEG:
raise click.ClickException("FFmpeg executable \"ffmpeg\" not found but is required.")

if path.is_dir():
Expand Down Expand Up @@ -157,15 +155,15 @@ def range_(path: Path, full: bool, preview: bool) -> None:
]))))]

ffmpeg_call = subprocess.Popen([
executable, "-y",
binaries.FFMPEG, "-y",
"-i", str(video_path),
"-map", "0:v:0",
"-c", "copy",
"-bsf:v", f"{metadata_key}=video_full_range_flag={int(full)}"
] + out_path, stdout=subprocess.PIPE)
try:
if preview:
previewer = get_binary_path("mpv", "ffplay")
previewer = binaries.MPV or binaries.FFPlay
if not previewer:
raise click.ClickException("MPV/FFplay executables weren't found but are required for previewing.")
subprocess.Popen((previewer, "-"), stdin=ffmpeg_call.stdout)
Expand All @@ -188,8 +186,7 @@ def test(path: Path, map_: str) -> None:
You may choose specific streams using the -m/--map parameter. E.g.,
'0:v:0' to test the first video stream, or '0:a' to test all audio streams.
"""
executable = get_binary_path("ffmpeg")
if not executable:
if not binaries.FFMPEG:
raise click.ClickException("FFmpeg executable \"ffmpeg\" not found but is required.")

if path.is_dir():
Expand All @@ -199,7 +196,7 @@ def test(path: Path, map_: str) -> None:
for video_path in paths:
print("Starting...")
p = subprocess.Popen([
executable, "-hide_banner",
binaries.FFMPEG, "-hide_banner",
"-benchmark",
"-i", str(video_path),
"-map", map_,
Expand Down
45 changes: 45 additions & 0 deletions devine/core/binaries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import shutil
import sys
from pathlib import Path
from typing import Optional

__shaka_platform = {
"win32": "win",
"darwin": "osx"
}.get(sys.platform, sys.platform)


def find(*names: str) -> Optional[Path]:
"""Find the path of the first found binary name."""
for name in names:
path = shutil.which(name)
if path:
return Path(path)
return None


FFMPEG = find("ffmpeg")
FFProbe = find("ffprobe")
FFPlay = find("ffplay")
SubtitleEdit = find("SubtitleEdit")
ShakaPackager = find(
"shaka-packager",
"packager",
f"packager-{__shaka_platform}",
f"packager-{__shaka_platform}-x64"
)
Aria2 = find("aria2c", "aria2")
CCExtractor = find(
"ccextractor",
"ccextractorwin",
"ccextractorwinfull"
)
HolaProxy = find("hola-proxy")
MPV = find("mpv")
Caddy = find("caddy")


__all__ = (
"FFMPEG", "FFProbe", "FFPlay", "SubtitleEdit", "ShakaPackager",
"Aria2", "CCExtractor", "HolaProxy", "MPV", "Caddy", "find"
)
8 changes: 4 additions & 4 deletions devine/core/downloaders/aria2c.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
from rich import filesize
from rich.text import Text

from devine.core import binaries
from devine.core.config import config
from devine.core.console import console
from devine.core.constants import DOWNLOAD_CANCELLED
from devine.core.utilities import get_binary_path, get_extension, get_free_port
from devine.core.utilities import get_extension, get_free_port


def rpc(caller: Callable, secret: str, method: str, params: Optional[list[Any]] = None) -> Any:
Expand Down Expand Up @@ -87,8 +88,7 @@ def download(
if not isinstance(urls, list):
urls = [urls]

executable = get_binary_path("aria2c", "aria2")
if not executable:
if not binaries.Aria2:
raise EnvironmentError("Aria2c executable not found...")

if proxy and not proxy.lower().startswith("http://"):
Expand Down Expand Up @@ -186,7 +186,7 @@ def download(
try:
p = subprocess.Popen(
[
executable,
binaries.Aria2,
*arguments
],
stdin=subprocess.PIPE,
Expand Down
10 changes: 4 additions & 6 deletions devine/core/drm/widevine.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import base64
import shutil
import subprocess
import sys
import textwrap
from pathlib import Path
from typing import Any, Callable, Optional, Union
Expand All @@ -17,10 +16,11 @@
from requests import Session
from rich.text import Text

from devine.core import binaries
from devine.core.config import config
from devine.core.console import console
from devine.core.constants import AnyTrack
from devine.core.utilities import get_binary_path, get_boxes
from devine.core.utilities import get_boxes
from devine.core.utils.subprocess import ffprobe


Expand Down Expand Up @@ -223,9 +223,7 @@ def decrypt(self, path: Path) -> None:
if not self.content_keys:
raise ValueError("Cannot decrypt a Track without any Content Keys...")

platform = {"win32": "win", "darwin": "osx"}.get(sys.platform, sys.platform)
executable = get_binary_path("shaka-packager", "packager", f"packager-{platform}", f"packager-{platform}-x64")
if not executable:
if not binaries.ShakaPackager:
raise EnvironmentError("Shaka Packager executable not found but is required.")
if not path or not path.exists():
raise ValueError("Tried to decrypt a file that does not exist.")
Expand All @@ -252,7 +250,7 @@ def decrypt(self, path: Path) -> None:
]

p = subprocess.Popen(
[executable, *arguments],
[binaries.ShakaPackager, *arguments],
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
universal_newlines=True
Expand Down
8 changes: 4 additions & 4 deletions devine/core/manifests/hls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
from pywidevine.pssh import PSSH
from requests import Session

from devine.core import binaries
from devine.core.constants import DOWNLOAD_CANCELLED, DOWNLOAD_LICENCE_ONLY, AnyTrack
from devine.core.downloaders import requests as requests_downloader
from devine.core.drm import DRM_T, ClearKey, Widevine
from devine.core.events import events
from devine.core.tracks import Audio, Subtitle, Tracks, Video
from devine.core.utilities import get_binary_path, get_extension, is_close_match, try_ensure_utf8
from devine.core.utilities import get_extension, is_close_match, try_ensure_utf8


class HLS:
Expand Down Expand Up @@ -556,8 +557,7 @@ def merge_segments(segments: list[Path], save_path: Path) -> int:
Returns the file size of the merged file.
"""
ffmpeg = get_binary_path("ffmpeg")
if not ffmpeg:
if not binaries.FFMPEG:
raise EnvironmentError("FFmpeg executable was not found but is required to merge HLS segments.")

demuxer_file = segments[0].parent / "ffmpeg_concat_demuxer.txt"
Expand All @@ -567,7 +567,7 @@ def merge_segments(segments: list[Path], save_path: Path) -> int:
]))

subprocess.check_call([
ffmpeg, "-hide_banner",
binaries.FFMPEG, "-hide_banner",
"-loglevel", "panic",
"-f", "concat",
"-safe", "0",
Expand Down
Loading

0 comments on commit 909dce4

Please sign in to comment.