Skip to content

mux

Runs the mux.

Parameters:

Name Type Description Default
*tracks _track

Any amount of track objects and a Chapters object

()
tmdb TmdbConfig | None

A TMDB Config used for additional tagging if you so desire.

None
outfile PathLike | None

If you want to overwrite the output file path

None
quiet bool

Whether or not to print the mkvmerge output

True
print_cli bool

Print the final muxing command before running it if True

False
Source code in muxtools/muxing/muxer.py
def mux(*tracks: _track, tmdb: TmdbConfig | None = None, outfile: PathLike | None = None, quiet: bool = True, print_cli: bool = False) -> Path:
    """
    Runs the mux.

    :param *tracks:     Any amount of track objects and a Chapters object
    :param tmdb:        A TMDB Config used for additional tagging if you so desire.
    :param outfile:     If you want to overwrite the output file path
    :param quiet:       Whether or not to print the mkvmerge output
    :param print_cli:   Print the final muxing command before running it if True
    """
    check_mkvmerge_version()
    tracklist = list(tracks)
    out_dir = ensure_path(get_setup_attr("out_dir", "premux"), "Mux")
    args: list[str] = [get_executable("mkvmerge")]

    filename, mkvtitle = output_names(tmdb, args, tracklist)

    if not outfile:
        outfile = Path(out_dir, f"{filename}.mkv")

    outfile = ensure_path(outfile, "Mux")

    args.extend(["-o", str(outfile)])

    for track in tracklist:
        if isinstance(track, _track):
            args.extend(track.mkvmerge_args())
            continue
        elif isinstance(track, MuxingFile):
            if not isinstance(track, FontFile):
                warn("It's strongly recommended to pass tracks to ensure naming and tagging instead of MuxingFiles directly!", "Mux", 1)
            track = track.to_track()
            args.extend(track.mkvmerge_args())
            continue
        elif isinstance(track, Chapters):
            if not track.chapters:
                warn("Chapters are None or empty!", "Mux")
                continue

            args.extend(["--chapters", str(track.to_file())])
            continue
        elif isinstance(track, Path) or isinstance(track, str) or isinstance(track, GlobSearch):
            # Failsave for if someone passes Chapters().to_file() or a txt/xml file
            track = ensure_path_exists(track, "Mux")
            if track.suffix.lower() in [".txt", ".xml"]:
                args.extend(["--chapters", str(track.resolve())])
                continue
        elif track is None:
            continue

        raise error("Only _track, MuxingFiles or Chapters types are supported as muxing input!", "Mux")

    if mkvtitle:
        args.extend(["--title", mkvtitle])

    if print_cli:
        info(joincommand(args), "Mux")

    debug("Running the mux...", "Mux")
    if run_commandline(args, quiet, mkvmerge=True) > 1:
        raise error("Muxing failed!", "Mux")

    if not get_setup_attr("skip_mux_branding", False):
        try:
            from importlib.metadata import version

            parsed = ParsedFile.from_file(outfile, "Mux")
            tags = parsed.container_info.tags
            if not tags:
                debug("File does not contain writing library tags. Skipping the muxtools branding.", "Mux")

            mkvpropedit = get_executable("mkvpropedit", False, False)
            if not mkvpropedit:
                warn("Mkvpropedit could not be found!", "Mux", 0)
            muxtools_version = version("muxtools")
            version_tag = f" + muxtools v{muxtools_version}"

            muxing_application = tags.get("encoder", None)

            if mkvpropedit and muxing_application and (match := writing_lib_regex.search(muxing_application)):
                muxing_application = f"libebml v{match.group(1)} + libmatroska v{match.group(2)}" + version_tag
                args = [mkvpropedit, "--edit", "info", "--set", f"muxing-application={muxing_application}", str(outfile.resolve())]
                if run_commandline(args, mkvmerge=True) > 1:
                    danger("Failed to add muxtools information via mkvpropedit!", "Mux")
        except Exception as e:
            print(e)
            danger("Failed to add muxtools information via mkvpropedit!", "Mux")

    if "#crc32#" in outfile.stem:
        debug("Generating CRC32 for the muxed file...", "Mux")
        outfile = outfile.rename(outfile.with_stem(re.sub(re.escape("#crc32#"), get_crc32(outfile), outfile.stem)))

    if get_setup_attr("clean_work_dirs", False):
        if os.path.samefile(get_workdir(), os.getcwd()):
            error("Clearing workdir not supported when your workdir is cwd.", "Mux")
        else:
            rmtree(get_workdir())

    clean_temp_files()
    debug("Done", "Mux")
    return outfile