vibe coding is something
Build and Push Docker Images / build-and-push (push) Successful in 27s

This commit is contained in:
2026-02-11 00:11:04 +01:00
parent 062c3e6401
commit 7afa148bb3
+49 -8
View File
@@ -272,12 +272,14 @@ def build_epg_xml() -> str:
return '<?xml version="1.0" encoding="UTF-8"?>\n' + ET.tostring(root, encoding="unicode", default_namespace=None)
def _escape_path(p: Path) -> str:
return str(p.resolve()).replace("\\", "\\\\").replace("'", "'\\''")
def write_concat_list(paths: list[Path], fd) -> None:
"""Write FFmpeg concat demuxer list to file. Escapes paths for safety."""
for p in paths:
# Concat format: file 'path' — escape ' as '\''
path_str = str(p.resolve()).replace("\\", "\\\\").replace("'", "'\\''")
fd.write(f"file '{path_str}'\n")
fd.write(f"file '{_escape_path(p)}'\n")
fd.flush()
@@ -286,18 +288,57 @@ def _schedule_epoch_utc() -> datetime:
return datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
def _current_position_in_cycle(durations: list[float]) -> tuple[int, float]:
"""
Return (file_index, offset_sec_in_file) for 'now' in the schedule cycle.
Schedule epoch = midnight UTC; cycle = one full playlist.
"""
epoch = _schedule_epoch_utc()
now = datetime.now(timezone.utc)
cycle_duration = sum(durations)
if cycle_duration <= 0:
return 0, 0.0
offset_sec = (now - epoch).total_seconds() % cycle_duration
cumul = 0.0
for i, dur in enumerate(durations):
if offset_sec < cumul + dur:
return i, offset_sec - cumul
cumul += dur
return len(durations) - 1, durations[-1]
def write_concat_list_from_current(paths: list[Path], durations: list[float], fd) -> None:
"""
Write a concat list that starts at the current position in the schedule and
loops seamlessly. Uses inpoint/outpoint so we join mid-file, then repeat.
Cycle: current file (offset→end), next files…, start…current-1, current file (0→offset).
"""
n = len(paths)
if n == 0:
return
idx, offset_in_file = _current_position_in_cycle(durations)
for i in range(n):
j = (idx + i) % n
fd.write(f"file '{_escape_path(paths[j])}'\n")
if i == 0 and offset_in_file >= 0.5:
fd.write(f"inpoint {offset_in_file:.2f}\n")
if offset_in_file >= 0.5:
fd.write(f"file '{_escape_path(paths[idx])}'\n")
fd.write(f"outpoint {offset_in_file:.2f}\n")
fd.flush()
def stream_live_channel(paths: list[Path], wfile, durations: list[float]) -> None:
"""
Run FFmpeg to output a continuous MPEG-TS stream from paths, looping forever.
Stops when wfile write fails (client disconnect).
(No -ss seek: seeking into a looping concat input is unreliable, so stream
always starts from playlist start; EPG order and durations still match.)
Run FFmpeg to output a continuous MPEG-TS stream. Concat list starts at
current position in schedule (midnight UTC cycle) so each new client joins
where the 'channel' is now; then the list loops. EPG and stream stay in sync.
"""
if not paths:
return
with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f:
write_concat_list(paths, f)
write_concat_list_from_current(paths, durations, f)
list_path = f.name
try:
proc = subprocess.Popen(