feat(logging): add debug_requests flag and aggregate subtitle-conversion logs

This commit is contained in:
imSp4rky
2026-06-09 22:26:35 -06:00
parent 394ed67e28
commit 5337639035
6 changed files with 39 additions and 32 deletions

View File

@@ -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

View File

@@ -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])

View File

@@ -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."""

View File

@@ -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,30 +624,7 @@ 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
return run_conversion(self, codec, pin=pin, forced=forced)
dl = get_debug_logger()
if not dl:
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]:

View File

@@ -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

View File

@@ -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)