Skip to content

Xil Gui

src.xil_pipeline.xil_gui

Gradio web dashboard for xil-pipeline.

A browser-based GUI that supplements the CLI for visual oversight, audio preview, and sharing episode review with collaborators.

Usage:

xil-gui                              # opens http://localhost:7860
xil-gui --port 8080                  # custom port
xil-gui --share                      # generate public URL for partner access (72h tunnel)
xil-gui --output session.log         # append timestamped activity log to file
xil-gui --verbose                    # detailed logs for the Timeline SFX dialog (open/save)

Install the optional [gui] extra first: pip install 'xil-pipeline[gui]'

logger module-attribute

logger = get_logger(__name__)

RUNNABLE_STAGES module-attribute

RUNNABLE_STAGES = ['1) scan', '2) parse', '3) produce', '4) assemble', '5) daw', '6) master']

DRY_RUN_STAGES module-attribute

DRY_RUN_STAGES = {'produce', 'daw', 'master'}

load_cast_config

load_cast_config(path: str) -> str
Source code in src/xil_pipeline/xil_gui.py
def load_cast_config(path: str) -> str:
    return _load_config_file(path, "cast")

load_speakers_config

load_speakers_config(path: str) -> str
Source code in src/xil_pipeline/xil_gui.py
def load_speakers_config(path: str) -> str:
    return _load_config_file(path, "speakers")

load_sfx_config

load_sfx_config(path: str) -> str
Source code in src/xil_pipeline/xil_gui.py
def load_sfx_config(path: str) -> str:
    return _load_config_file(path, "sfx")

get_parser

get_parser() -> argparse.ArgumentParser

Return the argument parser for xil-gui.

Source code in src/xil_pipeline/xil_gui.py
def get_parser() -> argparse.ArgumentParser:
    """Return the argument parser for xil-gui."""
    parser = argparse.ArgumentParser(
        prog="xil-gui",
        description=(
            "Launch the xil-pipeline web dashboard (Gradio). Opens a browser UI "
            "with nine tabs: Setup (initialize a workspace / select the active "
            "show), Project (edit project.json), Episodes (workspace overview "
            "with parse/stems/DAW/master status), Run Stage (launch pipeline "
            "stages with live log streaming; dry-run on by default), Speakers, "
            "Cast Config and SFX Config (edit the respective JSON configs), "
            "Audio Preview (browse and play stems in the browser), and Timeline "
            "(interactive HTML timeline)."
        ),
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=(
            "Requires the [gui] extra:\n"
            "  pip install 'xil-pipeline[gui]'\n\n"
            "Partner sharing (temporary 72h public URL, open access, no auth —\n"
            "share only with trusted collaborators):\n"
            "  xil-gui --share\n"
        ),
    )
    parser.add_argument(
        "--port", type=int, default=7860,
        help="Port to listen on (default: 7860)",
    )
    parser.add_argument(
        "--host", default="127.0.0.1",
        help="Host address to bind (default: 127.0.0.1)",
    )
    parser.add_argument(
        "--share", action="store_true",
        help="Generate a public ngrok URL for partner access (open, no auth)",
    )
    parser.add_argument(
        "--output", "-o",
        default=None,
        metavar="FILE",
        help="Append a timestamped session activity log to FILE",
    )
    parser.add_argument(
        "--verbose", "-v", action="store_true",
        help="Log detailed activity for the Timeline audio-properties dialog "
             "(SFX open/save requests) to stdout and logs/xil_YYYY-MM-DD.log",
    )
    return parser

main

main() -> None

CLI entry point for the Gradio web dashboard.

Source code in src/xil_pipeline/xil_gui.py
def main() -> None:
    """CLI entry point for the Gradio web dashboard."""
    global _activity_log
    args = get_parser().parse_args()
    # Root stays at INFO regardless of --verbose — raising it to DEBUG would
    # also unmask every third-party library's own DEBUG chatter (PIL, httpx,
    # uvicorn, ...) since they inherit the root level. --verbose instead
    # raises only this module's logger, which still reaches root's stdout +
    # logs/xil_YYYY-MM-DD.log handlers via normal propagation.
    configure_logging()
    if args.verbose:
        logger.setLevel(logging.DEBUG)
    if args.output:
        _activity_log = open(args.output, "a", encoding="utf-8", buffering=1)
    try:
        demo = _build_app()
        demo.launch(
            server_name=args.host,
            server_port=args.port,
            share=args.share,
            allowed_paths=[str(get_workspace_root())],
            prevent_thread_lock=True,
        )
        # launch() replaced demo.app with the FastAPI app that actually
        # serves requests — only now can the /xil/* routes be attached.
        _register_sfx_routes(demo.app)
        demo.block_thread()
    finally:
        if _activity_log:
            _activity_log.close()