style: apply ruff format across backend + scripts (line-length 100)
Mechanical, whole-tree `ruff format` pass — no behaviour change. Recorded in .git-blame-ignore-revs (next commit) so git blame skips it.
This commit is contained in:
+82
-23
@@ -14,6 +14,7 @@ Sessions live in this (single) API process; a periodic reaper kills idle ones an
|
||||
segments. The remux is CPU-light (video copy + a tiny audio transcode), so it runs fine on the
|
||||
CPU-only prod host; only P3's full transcode is CPU-heavy.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
import shutil
|
||||
@@ -31,7 +32,11 @@ from app.plex import paths
|
||||
|
||||
log = logging.getLogger("siftlode.plex")
|
||||
|
||||
_HLS_ROOT = Path(settings.plex_hls_dir) if settings.plex_hls_dir else Path(settings.download_root) / ".plex-hls"
|
||||
_HLS_ROOT = (
|
||||
Path(settings.plex_hls_dir)
|
||||
if settings.plex_hls_dir
|
||||
else Path(settings.download_root) / ".plex-hls"
|
||||
)
|
||||
_SEG_SECONDS = 6
|
||||
_SESSION_IDLE_S = 600 # reap a session with no access for this long
|
||||
# A session directory is named `{rating_key}_{int(start_s)}_{tag}_{aoff:+.2f}` (see start_session);
|
||||
@@ -66,7 +71,9 @@ _sessions: dict[str, "HlsSession"] = {}
|
||||
|
||||
|
||||
class HlsSession:
|
||||
def __init__(self, key: str, directory: Path, proc: subprocess.Popen, start_s: float, entry: str):
|
||||
def __init__(
|
||||
self, key: str, directory: Path, proc: subprocess.Popen, start_s: float, entry: str
|
||||
):
|
||||
self.key = key
|
||||
self.dir = directory
|
||||
self.proc = proc
|
||||
@@ -91,15 +98,21 @@ def _seek_opts(start_s: float) -> list[str]:
|
||||
|
||||
|
||||
_HLS_TAIL = [
|
||||
"-f", "hls",
|
||||
"-hls_time", str(_SEG_SECONDS),
|
||||
"-hls_list_size", "0",
|
||||
"-f",
|
||||
"hls",
|
||||
"-hls_time",
|
||||
str(_SEG_SECONDS),
|
||||
"-hls_list_size",
|
||||
"0",
|
||||
# EVENT (not VOD): ffmpeg writes/appends the playlist AS segments complete, so playback can
|
||||
# start immediately from this session's offset. VOD only writes the playlist at the end. The
|
||||
# full seekbar comes from our known duration + the seek-restart model, not from the playlist.
|
||||
"-hls_playlist_type", "event",
|
||||
"-hls_segment_type", "mpegts",
|
||||
"-hls_flags", "independent_segments+temp_file",
|
||||
"-hls_playlist_type",
|
||||
"event",
|
||||
"-hls_segment_type",
|
||||
"mpegts",
|
||||
"-hls_flags",
|
||||
"independent_segments+temp_file",
|
||||
]
|
||||
|
||||
|
||||
@@ -108,9 +121,21 @@ def _probe_audio_langs(src: Path) -> list[str]:
|
||||
Used to build the multi-rendition var_stream_map. Empty on probe failure → single-audio path."""
|
||||
try:
|
||||
out = subprocess.run(
|
||||
["ffprobe", "-v", "error", "-select_streams", "a", "-show_entries", "stream_tags=language",
|
||||
"-of", "csv=p=0", str(src)],
|
||||
capture_output=True, text=True, timeout=10,
|
||||
[
|
||||
"ffprobe",
|
||||
"-v",
|
||||
"error",
|
||||
"-select_streams",
|
||||
"a",
|
||||
"-show_entries",
|
||||
"stream_tags=language",
|
||||
"-of",
|
||||
"csv=p=0",
|
||||
str(src),
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
)
|
||||
return [ln.strip() for ln in out.stdout.splitlines()]
|
||||
except (subprocess.SubprocessError, OSError):
|
||||
@@ -118,8 +143,12 @@ def _probe_audio_langs(src: Path) -> list[str]:
|
||||
|
||||
|
||||
def _ffmpeg_cmd(
|
||||
src: Path, start_s: float, out_dir: Path, audio_ord: int | None,
|
||||
aoff: float = 0.0, audio_langs: list[str] | None = None,
|
||||
src: Path,
|
||||
start_s: float,
|
||||
out_dir: Path,
|
||||
audio_ord: int | None,
|
||||
aoff: float = 0.0,
|
||||
audio_langs: list[str] | None = None,
|
||||
) -> list[str]:
|
||||
args = ["ffmpeg", "-nostdin", "-loglevel", "error"]
|
||||
# Keep ORIGINAL timestamps on the output so the first segment carries the true absolute PTS of the
|
||||
@@ -152,15 +181,23 @@ def _ffmpeg_cmd(
|
||||
entry += ",default:yes"
|
||||
var.append(entry)
|
||||
args += _HLS_TAIL + [
|
||||
"-master_pl_name", "master.m3u8",
|
||||
"-var_stream_map", " ".join(var),
|
||||
"-hls_segment_filename", str(out_dir / "seg_%v_%d.ts"), str(out_dir / "stream_%v.m3u8"),
|
||||
"-master_pl_name",
|
||||
"master.m3u8",
|
||||
"-var_stream_map",
|
||||
" ".join(var),
|
||||
"-hls_segment_filename",
|
||||
str(out_dir / "seg_%v_%d.ts"),
|
||||
str(out_dir / "stream_%v.m3u8"),
|
||||
]
|
||||
else:
|
||||
ao = audio_ord if audio_ord is not None else 0
|
||||
args += ["-map", "0:v:0", "-map", f"{ai}:a:{ao}?", "-sn"]
|
||||
args += ["-c:v", "copy", "-c:a", "aac", "-ac", "2", "-b:a", "192k"]
|
||||
args += _HLS_TAIL + ["-hls_segment_filename", str(out_dir / "seg_%d.ts"), str(out_dir / "index.m3u8")]
|
||||
args += _HLS_TAIL + [
|
||||
"-hls_segment_filename",
|
||||
str(out_dir / "seg_%d.ts"),
|
||||
str(out_dir / "index.m3u8"),
|
||||
]
|
||||
return args
|
||||
|
||||
|
||||
@@ -170,9 +207,23 @@ def _probe_first_pts(seg: Path) -> float | None:
|
||||
zero-bases the timeline to. Returns None on any failure (caller falls back to the requested offset)."""
|
||||
try:
|
||||
out = subprocess.run(
|
||||
["ffprobe", "-v", "error", "-select_streams", "v:0", "-read_intervals", "%+#1",
|
||||
"-show_entries", "packet=pts_time", "-of", "csv=p=0", str(seg)],
|
||||
capture_output=True, text=True, timeout=10,
|
||||
[
|
||||
"ffprobe",
|
||||
"-v",
|
||||
"error",
|
||||
"-select_streams",
|
||||
"v:0",
|
||||
"-read_intervals",
|
||||
"%+#1",
|
||||
"-show_entries",
|
||||
"packet=pts_time",
|
||||
"-of",
|
||||
"csv=p=0",
|
||||
str(seg),
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
)
|
||||
for line in out.stdout.splitlines():
|
||||
tok = line.strip().strip(",")
|
||||
@@ -199,7 +250,9 @@ def _enforce_cap(cap: int) -> None:
|
||||
# Caller holds _lock. Drop the least-recently-accessed sessions over the cap.
|
||||
if len(_sessions) <= cap:
|
||||
return
|
||||
for key, s in sorted(_sessions.items(), key=lambda kv: kv[1].last_access)[: len(_sessions) - cap]:
|
||||
for key, s in sorted(_sessions.items(), key=lambda kv: kv[1].last_access)[
|
||||
: len(_sessions) - cap
|
||||
]:
|
||||
_kill(s)
|
||||
_sessions.pop(key, None)
|
||||
|
||||
@@ -232,7 +285,9 @@ def start_session(
|
||||
shutil.rmtree(directory, ignore_errors=True)
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
proc = subprocess.Popen(
|
||||
_ffmpeg_cmd(src, start_s, directory, audio_ord, aoff, audio_langs if is_multi else None),
|
||||
_ffmpeg_cmd(
|
||||
src, start_s, directory, audio_ord, aoff, audio_langs if is_multi else None
|
||||
),
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
@@ -253,7 +308,11 @@ def start_session(
|
||||
s.media_start_s = k
|
||||
log.info(
|
||||
"plex hls session start key=%s req=%.1f real=%.3f multi=%s audio=%s",
|
||||
key, start_s, s.media_start_s, is_multi, audio_ord,
|
||||
key,
|
||||
start_s,
|
||||
s.media_start_s,
|
||||
is_multi,
|
||||
audio_ord,
|
||||
)
|
||||
return s
|
||||
|
||||
|
||||
Reference in New Issue
Block a user