#!/usr/bin/env python3
"""
Simple HLS slicing script in Python.

Goals:
- Take a single input video (filename in BASE_DIR or absolute path)
- Produce an HLS ABR ladder with aligned keyframes
- Keep code straightforward and readable (no deep decomposition)

Usage:
  python3 src/hls_slice.py "Your Video.mp4" [--segment-duration 4] [--base-dir /override/path]

Outputs:
  ./out/<basename>/hls/master.m3u8
  ./out/<basename>/hls/v{height}/index.m3u8 + segments
"""

import argparse
import os
import subprocess
import sys


def main():
    # Defaults
    base_dir_default = "/home/arezvov/projects/midshore/res/"
    out_root_dir = "./out"
    segment_duration = 4

    # ABR ladder: (height, video_kbps, audio_kbps)
    abr_ladder = [
        (1080, 8000, 192),
        (720, 4000, 160),
        (480, 1500, 128),
        (360, 800, 96),
    ]

    parser = argparse.ArgumentParser(description="HLS slicing script")
    parser.add_argument("input", help="Filename in BASE_DIR or absolute path")
    parser.add_argument("--segment-duration", type=int, default=segment_duration, dest="seg")
    parser.add_argument("--base-dir", type=str, default=base_dir_default, dest="base")
    args = parser.parse_args()

    # Resolve input path
    base_dir = args.base.rstrip("/")
    if os.path.isabs(args.input):
        input_path = args.input
    else:
        input_path = os.path.join(base_dir, args.input)

    if not os.path.isfile(input_path):
        print(f"[hls_slice] ERROR: Input file not found: {input_path}")
        if os.path.isdir(base_dir):
            print(f"[hls_slice] Available files in base dir ({base_dir}):")
            try:
                for name in sorted(os.listdir(base_dir)):
                    print(name)
            except Exception:
                pass
        sys.exit(2)

    basename_with_ext = os.path.basename(input_path)
    basename_no_ext = os.path.splitext(basename_with_ext)[0]
    out_dir = os.path.join(out_root_dir, basename_no_ext, "hls")
    os.makedirs(out_dir, exist_ok=True)

    print(f"[hls_slice] Input: {input_path}")
    print(f"[hls_slice] Output directory: {out_dir}")
    print(f"[hls_slice] Segment duration: {args.seg}s")

    # Check ffmpeg availability
    try:
        subprocess.run(["ffmpeg", "-version"], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    except Exception:
        print("[hls_slice] ERROR: ffmpeg not found in PATH. Please install ffmpeg.")
        sys.exit(3)

    master_variants = []  # (height, bandwidth_bps, relative_playlist)

    for height, vbk, abk in abr_ladder:
        variant_dir = os.path.join(out_dir, f"v{height}")
        os.makedirs(variant_dir, exist_ok=True)
        playlist_path = os.path.join(variant_dir, "index.m3u8")
        segment_pattern = os.path.join(variant_dir, "seg_%05d.ts")

        # Estimated BANDWIDTH for master playlist (bps), include audio and small headroom
        bandwidth_bps = int((vbk + abk) * 1000 * 1.05)

        print(f"[hls_slice] Generating {height}p @ {vbk}k/{abk}k -> {playlist_path}")

        # Keep flags similar to bash version: aligned keyframes, independent segments
        cmd = [
            "ffmpeg", "-y", "-hide_banner", "-loglevel", "error",
            "-i", input_path,
            "-vf", f"scale=-2:{height}",
            "-c:v", "libx264", "-profile:v", "high", "-preset", "veryfast",
            "-b:v", f"{vbk}k", "-maxrate", f"{vbk}k", "-bufsize", f"{vbk*2}k",
            "-x264-params", "scenecut=0:open_gop=0", "-sc_threshold", "0",
            "-force_key_frames", f"expr:gte(t,n_forced*{args.seg})",
            "-c:a", "aac", "-ac", "2", "-b:a", f"{abk}k",
            "-hls_time", str(args.seg), "-hls_playlist_type", "vod", "-hls_flags", "independent_segments",
            "-hls_segment_filename", segment_pattern,
            playlist_path,
        ]

        # Run ffmpeg for this rendition
        try:
            subprocess.run(cmd, check=True)
        except subprocess.CalledProcessError as e:
            print(f"[hls_slice] ERROR: ffmpeg failed for {height}p: {e}")
            sys.exit(4)

        rel_playlist = os.path.relpath(playlist_path, out_dir)
        master_variants.append((height, bandwidth_bps, rel_playlist))

    # Write master.m3u8
    master_path = os.path.join(out_dir, "master.m3u8")
    with open(master_path, "w", encoding="utf-8") as f:
        f.write("#EXTM3U\n")
        f.write("#EXT-X-VERSION:3\n")
        for height, bw, rel in master_variants:
            # Width is set to 1920 placeholder; players will read real resolution from streams
            f.write(f"#EXT-X-STREAM-INF:BANDWIDTH={bw},RESOLUTION=1920x{height}\n")
            f.write(f"{rel}\n")

    print(f"[hls_slice] Master playlist created: {master_path}")
    print("[hls_slice] Done.")


if __name__ == "__main__":
    main()


