Skip to content

vsmuxtools.extension.audio

export_audionode

export_audionode(node: AudioNode, outfile: PathLike | None = None, w64: bool | None = None) -> Path

Exports an audionode to a wav/w64 file.

Parameters:

Name Type Description Default
node AudioNode

Your audionode

required
outfile PathLike | None

Custom output path if any

None
w64 bool | None

Force Wave64 output or auto-detect based on file size/extension

None

Returns:

Type Description
Path

Returns path

Source code in vsmuxtools/extension/audio.py
@keep.running
def export_audionode(node: vs.AudioNode, outfile: PathLike | None = None, w64: bool | None = None) -> Path:
    """
    Exports an audionode to a wav/w64 file.

    :param node:            Your audionode
    :param outfile:         Custom output path if any
    :param w64:             Force Wave64 output or auto-detect based on file size/extension

    :return:                Returns path
    """
    from vstools.functions.render.progress import get_render_progress

    if outfile is not None:
        outfile = ensure_path(outfile, export_audionode)

    if w64 is None:
        if outfile is not None and outfile.suffix.lower() == ".w64":
            w64 = True
        else:
            # Check if the resulting file size is > to 4GiB
            # https://github.com/vapoursynth/vapoursynth/blob/5b2d5562726a91d9a75441cc4728a90e6c9f4f27/src/common/wave.cpp#L142-L150
            bytes_per_sample = (node.bits_per_sample + 7) // 8
            data_size = node.num_samples * node.num_channels * bytes_per_sample
            # https://github.com/vapoursynth/vapoursynth/blob/5b2d5562726a91d9a75441cc4728a90e6c9f4f27/src/common/wave.cpp#L87
            w64 = (data_size + 68) > 0xFFFFFFFE

    ext = ".w64" if w64 else ".wav"

    if outfile is None:
        outfile = ensure_path(uniquify_path(Path(get_workdir(), f"exported{ext}")), export_audionode)
    elif w64 and outfile.suffix.lower() == ".wav":
        outfile = outfile.with_suffix(".w64")
    elif not outfile.suffix:
        outfile = outfile.with_suffix(ext)

    with outfile.open("wb") as bf, get_render_progress() as progress:
        task = progress.add_task("Rendering audio...", total=node.num_frames)
        node.output(bf, wav=not w64, w64=w64, progress_update=lambda curr, total: progress.update(task, total=total, completed=curr))
    return outfile

do_audio

do_audio(fileIn: PathLike | list[PathLike] | list[Path] | src_file | AudioNode, track: int = 0, trims: Trim | list[Trim] | None = None, timesource: TimeSourceT = None, timescale: TimeScaleT = TimeScale.MKV, num_frames: int = 0, extractor: Extractor | None = AutoExtractor(), trimmer: Trimmer | None = AutoTrimmer(), encoder: Encoder | None = AutoEncoder(), quiet: bool = True, output: PathLike | None = None) -> AudioFile

One-liner to handle the whole audio processing

Parameters:

Name Type Description Default
fileIn PathLike | list[PathLike] | list[Path] | src_file | AudioNode

Input file or src_file/FileInfo or AudioNode

required
track int

Audio track number

0
trims Trim | list[Trim] | None

Frame ranges to trim and/or combine, e.g. (24, -24) or [(24, 500), (700, 900)]

None inherits the src_file's trims; [] disables trimming. Explicit trims override the source's trims.

None
timesource TimeSourceT

The source of timestamps/timecodes. For details check the docstring on the type.

Will be taken from input if it's a src_file and assume the usual 24 if not.

None
timescale TimeScaleT

Unit of time (in seconds) in terms of which frame timestamps are represented.

For details check the docstring on the type.

MKV
num_frames int

Total number of frames, used for negative numbers in trims

Will be taken from input if it's a src_file

0
extractor Extractor | None

Tool used to extract the audio (Will default to None if an AudioNode gets passed, otherwise FFMpeg)

AutoExtractor()
trimmer Trimmer | None

Tool used to trim the audio

AutoTrimmer means it will choose ffmpeg for lossy and Sox for lossless

AutoTrimmer()
encoder Encoder | None

Tool used to encode the audio

AutoEncoder means it won't reencode lossy and choose opus otherwise

AutoEncoder()
quiet bool

Whether the tool output should be visible

True
output PathLike | None

Custom output file or directory, extensions will be automatically added

None

Returns:

Type Description
AudioFile

AudioFile Object containing file path, delays and source

Source code in vsmuxtools/extension/audio.py
@keep.running
def do_audio(
    fileIn: PathLike | list[PathLike] | list[Path] | src_file | vs.AudioNode,
    track: int = 0,
    trims: Trim | list[Trim] | None = None,
    timesource: TimeSourceT = None,
    timescale: TimeScaleT = TimeScale.MKV,
    num_frames: int = 0,
    extractor: Extractor | None = AutoExtractor(),
    trimmer: Trimmer | None = AutoTrimmer(),
    encoder: Encoder | None = AutoEncoder(),
    quiet: bool = True,
    output: PathLike | None = None,
) -> AudioFile:
    """
    One-liner to handle the whole audio processing

    :param fileIn:          Input file or src_file/FileInfo or AudioNode
    :param track:           Audio track number
    :param trims:           Frame ranges to trim and/or combine, e.g. (24, -24) or [(24, 500), (700, 900)]\n
                            None inherits the src_file's trims; [] disables trimming. Explicit trims override the source's trims.
    :param timesource:      The source of timestamps/timecodes. For details check the docstring on the type.\n
                            Will be taken from input if it's a src_file and assume the usual 24 if not.

    :param timescale:       Unit of time (in seconds) in terms of which frame timestamps are represented.\n
                            For details check the docstring on the type.

    :param num_frames:      Total number of frames, used for negative numbers in trims\n
                            Will be taken from input if it's a src_file

    :param extractor:       Tool used to extract the audio (Will default to None if an AudioNode gets passed, otherwise FFMpeg)
    :param trimmer:         Tool used to trim the audio\n
                            AutoTrimmer means it will choose ffmpeg for lossy and Sox for lossless

    :param encoder:         Tool used to encode the audio\n
                            AutoEncoder means it won't reencode lossy and choose opus otherwise

    :param quiet:           Whether the tool output should be visible
    :param output:          Custom output file or directory, extensions will be automatically added
    :return:                AudioFile Object containing file path, delays and source
    """
    if trims is not None:
        if isinstance(fileIn, src_file):
            danger("Other trims passed will overwrite whatever your src_file has!", do_audio, 1)
        if isinstance(fileIn, vs.AudioNode):
            danger("Trims won't be applied if you pass an Audionode. Just do them yourself before this lol.", do_audio, 1)
            trims = None
            trimmer = None

    if isinstance(fileIn, vs.AudioNode):
        extractor = None
        fileIn = export_audionode(fileIn)
    elif isinstance(fileIn, src_file):
        if trims is None:
            trims = fileIn.trim

        clip = fileIn.src
        fileIn = fileIn.file
        if not num_frames:
            num_frames = clip.num_frames
        if timesource is None:
            timesource = Fraction(clip.fps_num, clip.fps_den)

    if timesource is None:
        timesource = Fraction(24000, 1001)

    if isinstance(trims, list):
        trims = trims.copy()

    # TODO: Check why this typecheck fails lol
    return mt_audio(fileIn, track, trims, timesource, timescale, num_frames, extractor, trimmer, encoder, quiet, output)  # type: ignore