mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-06-11 11:42:06 +00:00
feat(logging): add debug_requests flag and aggregate subtitle-conversion logs
This commit is contained in:
@@ -1008,9 +1008,7 @@ class dl:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cdm_info:
|
if cdm_info:
|
||||||
log_event(
|
log_event("load_cdm", level="INFO", service=self.service, context={"cdm": cdm_info})
|
||||||
"load_cdm", level="INFO", service=self.service, context={"cdm": cdm_info}
|
|
||||||
)
|
|
||||||
|
|
||||||
self.proxy_providers = []
|
self.proxy_providers = []
|
||||||
if no_proxy:
|
if no_proxy:
|
||||||
@@ -1805,7 +1803,9 @@ class dl:
|
|||||||
for v in non_hybrid_tracks
|
for v in non_hybrid_tracks
|
||||||
if any(v.height == res or int(v.width * (9 / 16)) == res for res in quality)
|
if any(v.height == res or int(v.width * (9 / 16)) == res for res in quality)
|
||||||
]
|
]
|
||||||
title.tracks.videos = Tracks.merge_video_selections(hybrid_selected, non_hybrid_selected)
|
title.tracks.videos = Tracks.merge_video_selections(
|
||||||
|
hybrid_selected, non_hybrid_selected
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
title.tracks.videos = hybrid_selected
|
title.tracks.videos = hybrid_selected
|
||||||
else:
|
else:
|
||||||
@@ -2422,15 +2422,30 @@ class dl:
|
|||||||
sidecar_original_paths[subtitle.id] = original_path
|
sidecar_original_paths[subtitle.id] = original_path
|
||||||
|
|
||||||
with console.status("Converting Subtitles..."):
|
with console.status("Converting Subtitles..."):
|
||||||
|
sub_conversions: dict[tuple[str, str], int] = {}
|
||||||
for subtitle in title.tracks.subtitles:
|
for subtitle in title.tracks.subtitles:
|
||||||
if sub_format == "original":
|
if sub_format == "original":
|
||||||
continue
|
continue
|
||||||
if sub_format:
|
if sub_format:
|
||||||
if subtitle.codec != sub_format:
|
if subtitle.codec != sub_format:
|
||||||
|
src = getattr(subtitle.codec, "name", str(subtitle.codec))
|
||||||
|
dst = getattr(sub_format, "name", str(sub_format))
|
||||||
subtitle.convert(sub_format, forced=True)
|
subtitle.convert(sub_format, forced=True)
|
||||||
|
sub_conversions[(src, dst)] = sub_conversions.get((src, dst), 0) + 1
|
||||||
elif subtitle.codec == Subtitle.Codec.TimedTextMarkupLang:
|
elif subtitle.codec == Subtitle.Codec.TimedTextMarkupLang:
|
||||||
# MKV does not support TTML, VTT is the next best option
|
# MKV does not support TTML, VTT is the next best option
|
||||||
|
src = getattr(subtitle.codec, "name", str(subtitle.codec))
|
||||||
subtitle.convert(Subtitle.Codec.WebVTT)
|
subtitle.convert(Subtitle.Codec.WebVTT)
|
||||||
|
sub_conversions[(src, Subtitle.Codec.WebVTT.name)] = (
|
||||||
|
sub_conversions.get((src, Subtitle.Codec.WebVTT.name), 0) + 1
|
||||||
|
)
|
||||||
|
for (src, dst), count in sub_conversions.items():
|
||||||
|
log_event(
|
||||||
|
"subtitle_convert",
|
||||||
|
level="INFO",
|
||||||
|
message=f"Converted {src}->{dst} x{count}",
|
||||||
|
context={"from": src, "to": dst, "count": count},
|
||||||
|
)
|
||||||
|
|
||||||
with console.status("Checking Subtitles for Fonts..."):
|
with console.status("Checking Subtitles for Fonts..."):
|
||||||
font_names: list[str] = []
|
font_names: list[str] = []
|
||||||
@@ -2518,7 +2533,9 @@ class dl:
|
|||||||
|
|
||||||
# Now repack the decrypted tracks
|
# Now repack the decrypted tracks
|
||||||
if progress_sink and any(getattr(t, "needs_repack", False) for t in title.tracks):
|
if progress_sink and any(getattr(t, "needs_repack", False) for t in title.tracks):
|
||||||
progress_sink({"phase": "repackaging", "progress": 92.0, "status": "downloading", "active_tracks": []})
|
progress_sink(
|
||||||
|
{"phase": "repackaging", "progress": 92.0, "status": "downloading", "active_tracks": []}
|
||||||
|
)
|
||||||
with console.status("Repackaging tracks with FFMPEG..."):
|
with console.status("Repackaging tracks with FFMPEG..."):
|
||||||
has_repacked = False
|
has_repacked = False
|
||||||
for track in title.tracks:
|
for track in title.tracks:
|
||||||
@@ -2686,7 +2703,9 @@ class dl:
|
|||||||
mux_video_standalone(video_track)
|
mux_video_standalone(video_track)
|
||||||
|
|
||||||
if progress_sink:
|
if progress_sink:
|
||||||
progress_sink({"phase": "muxing", "progress": 96.0, "status": "downloading", "active_tracks": []})
|
progress_sink(
|
||||||
|
{"phase": "muxing", "progress": 96.0, "status": "downloading", "active_tracks": []}
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
with Live(Padding(progress, (0, 5, 1, 5)), console=console):
|
with Live(Padding(progress, (0, 5, 1, 5)), console=console):
|
||||||
mux_index = 0
|
mux_index = 0
|
||||||
|
|||||||
@@ -44,6 +44,10 @@ def main(version: bool, debug: bool) -> None:
|
|||||||
if debug_logging_enabled:
|
if debug_logging_enabled:
|
||||||
init_debug_logger(enabled=True)
|
init_debug_logger(enabled=True)
|
||||||
|
|
||||||
|
if debug and not config.debug_requests:
|
||||||
|
for noisy in ("urllib3", "urllib3.connectionpool", "requests", "rnet", "httpx", "httpcore", "hpack", "h2"):
|
||||||
|
logging.getLogger(noisy).setLevel(logging.WARNING)
|
||||||
|
|
||||||
urllib3.disable_warnings(InsecureRequestWarning)
|
urllib3.disable_warnings(InsecureRequestWarning)
|
||||||
|
|
||||||
traceback.install(console=console, width=80, suppress=[click])
|
traceback.install(console=console, width=80, suppress=[click])
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ class Config:
|
|||||||
|
|
||||||
self.debug: bool = kwargs.get("debug", False)
|
self.debug: bool = kwargs.get("debug", False)
|
||||||
self.debug_keys: bool = kwargs.get("debug_keys", False)
|
self.debug_keys: bool = kwargs.get("debug_keys", False)
|
||||||
|
self.debug_requests: bool = kwargs.get("debug_requests", False)
|
||||||
|
|
||||||
def _validate_output_templates(self) -> None:
|
def _validate_output_templates(self) -> None:
|
||||||
"""Validate output template configurations and warn about potential issues."""
|
"""Validate output template configurations and warn about potential issues."""
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from subtitle_filter import Subtitles
|
|||||||
from unshackle.core import binaries
|
from unshackle.core import binaries
|
||||||
from unshackle.core.config import config
|
from unshackle.core.config import config
|
||||||
from unshackle.core.tracks.track import Track
|
from unshackle.core.tracks.track import Track
|
||||||
from unshackle.core.utilities import get_debug_logger, log_event, try_ensure_utf8
|
from unshackle.core.utilities import try_ensure_utf8
|
||||||
from unshackle.core.utils.subprocess import log_tool_run
|
from unshackle.core.utils.subprocess import log_tool_run
|
||||||
from unshackle.core.utils.webvtt import merge_segmented_webvtt
|
from unshackle.core.utils.webvtt import merge_segmented_webvtt
|
||||||
|
|
||||||
@@ -624,31 +624,8 @@ class Subtitle(Track):
|
|||||||
config.subtitle.get("conversion_method") or getattr(self, "preferred_conversion_method", None) or "auto"
|
config.subtitle.get("conversion_method") or getattr(self, "preferred_conversion_method", None) or "auto"
|
||||||
)
|
)
|
||||||
pin = None if method == "auto" else method
|
pin = None if method == "auto" else method
|
||||||
|
|
||||||
dl = get_debug_logger()
|
|
||||||
if not dl:
|
|
||||||
return run_conversion(self, codec, pin=pin, forced=forced)
|
return run_conversion(self, codec, pin=pin, forced=forced)
|
||||||
|
|
||||||
start = time.monotonic()
|
|
||||||
try:
|
|
||||||
result = run_conversion(self, codec, pin=pin, forced=forced)
|
|
||||||
except Exception as e:
|
|
||||||
dl.log_error(
|
|
||||||
"subtitle_convert",
|
|
||||||
e,
|
|
||||||
context={"from": str(self.codec), "to": str(codec), "method": method, "forced": forced},
|
|
||||||
)
|
|
||||||
raise
|
|
||||||
log_event(
|
|
||||||
"subtitle_convert",
|
|
||||||
level="INFO",
|
|
||||||
message=f"Converted subtitle {self.codec} -> {codec}",
|
|
||||||
context={"from": str(self.codec), "to": str(codec), "method": method, "forced": forced},
|
|
||||||
duration_ms=round((time.monotonic() - start) * 1000, 1),
|
|
||||||
success=True,
|
|
||||||
)
|
|
||||||
return result
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def extract_fonts(text: str) -> set[str]:
|
def extract_fonts(text: str) -> set[str]:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -318,7 +318,6 @@ def run_conversion(sub: Subtitle, target: Codec, *, pin: Optional[str] = None, f
|
|||||||
last_exc = e
|
last_exc = e
|
||||||
log.debug(f"Subtitle backend {backend.name} failed ({source.name}->{target.name}): {e}")
|
log.debug(f"Subtitle backend {backend.name} failed ({source.name}->{target.name}): {e}")
|
||||||
continue
|
continue
|
||||||
log.debug(f"Converted subtitle {source.name}->{target.name} via {backend.name}")
|
|
||||||
return finalize(sub, target, out)
|
return finalize(sub, target, out)
|
||||||
|
|
||||||
raise RuntimeError(f"All subtitle backends failed for {source.name}->{target.name}") from last_exc
|
raise RuntimeError(f"All subtitle backends failed for {source.name}->{target.name}") from last_exc
|
||||||
|
|||||||
@@ -136,6 +136,13 @@ debug_keys:
|
|||||||
# Useful for debugging key retrieval and decryption issues
|
# Useful for debugging key retrieval and decryption issues
|
||||||
# SECURITY NOTE: Passwords, tokens, cookies, and session tokens
|
# SECURITY NOTE: Passwords, tokens, cookies, and session tokens
|
||||||
# are ALWAYS redacted regardless of this setting
|
# are ALWAYS redacted regardless of this setting
|
||||||
|
|
||||||
|
debug_requests:
|
||||||
|
false # Show per-request HTTP library logs under --debug (default: false)
|
||||||
|
# When false, --debug mutes the noisy per-segment connection logs from the
|
||||||
|
# HTTP libraries (urllib3/requests/rnet, e.g. 'GET ...m4s 200'), keeping
|
||||||
|
# unshackle's own DEBUG output readable.
|
||||||
|
# Set to true to see every individual request/segment download.
|
||||||
# Only affects: content_key, key fields (the actual CEKs)
|
# Only affects: content_key, key fields (the actual CEKs)
|
||||||
# Never affects: kid, keys_count, key_id (metadata is always logged)
|
# Never affects: kid, keys_count, key_id (metadata is always logged)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user