Advanced example script¶
This is an advanced example of how to use Yukine to encode and mux a video.
We will create a Source object, and then use Setting Track Properties You can set properties for the tracks.
Here we set the Strict matching We use the Match conditions We can setup conditions to match tracks based on their properties.
Here we use the Keys and where to find them. The keys that the match conditions use are the ones that
One of these things just doesn’t belong here. When a track is not matched, it is not added to the muxed video.
This can be used for dealing with occasional tracks that are
not in every file, like commentary tracks. Globby Processors We can use Encode and mux to encode and mux the video.
In this example, we will use one Source object for multiple encodes. We will use MatchCondition and MatchSettings to select specific audio and subtitle tracks from the source file based off the track properties and we will also use pre-defined Vapoursynth filters.Advanced script
import signal
import argparse
from pathlib import Path
from muxtools import Chapters
from yukine import (
Encode,
Globby,
Source,
Processors,
ImportMethod,
mux,
Encoder,
AudioEncoder,
has_chapters,
EncodingMethod,
SetAudioTrack,
SetSubtitleTrack,
MatchCondition,
MatchSettings,
SetFilter,
)
def main():
# Setup argparse to not have to edit the script to change the input folder.
args = argparse.ArgumentParser()
args.add_argument("--input", type=Path, default=Path("input"))
args.add_argument("--temp", type=Path, default=Path("temp"))
args.add_argument("--debug", action="store_true")
args = args.parse_args()
iter = 0
for f in sorted(args.input.iterdir(), key=lambda x: x.name):
if f.suffix == ".mkv":
# Increment the episode number, and format it as a two digit number.
iter += 1
ep_num: str = f"{iter:02d}"
# type hinting
input_file: Path = f
vid1 = Source(
video_input=input_file,
importer=ImportMethod.FFMS2,
av1an_settings="--workers 4 -x 240",
encoder_settings="--preset 2 --crf 30",
video_encoder=Encoder.svt_av1,
encoding_method=EncodingMethod.av1an,
audio=[
SetAudioTrack(
file=input_file,
encoder=AudioEncoder.OPUS,
default=True, # (1)!
title="Japanese OPUS 2.0",
# (2)!
match_settings=MatchSettings(strict=True),
# (3)!
match=[
MatchCondition(key="language", value="jpn"), # (4)!
MatchCondition(key="title", value="FLAC 2.0"),
],
),
SetAudioTrack(
file=input_file,
encoder=AudioEncoder.OPUS,
default=True,
title="English OPUS 5.1",
match_settings=MatchSettings(strict=True),
match=[
MatchCondition(key="language", value="eng"),
MatchCondition(key="title", value="TrueHD 5.1"),
],
),
# (5)!
SetAudioTrack(
file=input_file,
encoder=AudioEncoder.OPUS,
default=False,
forced=False,
match_settings=MatchSettings(strict=True),
match=[
MatchCondition(key="language", value="jpn"),
MatchCondition(key="title", value="Commentary", regex=True),
],
),
],
subs=[
SetSubtitleTrack(
file=input_file,
),
SetSubtitleTrack(
file=Globby("*.fre.ass", dir=Path(f"wise_wolf_eraisubs/{ep_num}")), # (6)!
default=True,
forced=False,
lang="fr",
title="Français (France)",
),
],
# (7)!
process_methods=[
SetFilter(Processors.denoise(strength=0.3)),
SetFilter(Processors.deband(threshold=16)),
],
)
# Even though only one `Source` object is defined,
# we can keep this here for later use if we want
# to define more `Source` objects.
# This is useful if we want to compare encode settings.
vids: list[Source] = [vid1]
for vid in vids:
encoder = Encode(vid)
# Tell ChunkedEncoder to stop if we're using it and not av1an.
def force_exit(sig, frame):
print("Exiting on user script.")
if encoder.chunked_encoder is not None:
encoder.chunked_encoder.stop()
exit(0)
signal.signal(signal.SIGINT, force_exit)
encoder.run()
mux(vid)
if __name__ == "__main__":
main()
default and title properties for the tracks.
We can also set the forced property for the tracks
along with the lang and delay properties.match and match_settings options to match tracks based on their properties.
strict=True means that the track must match all the conditions in the match list.
Without it, only one condition must match.other_language and title properties to match the tracks.
We can also use the regex=True option to treat the value as a regex pattern.ffprobe and mkvmerge uses.
You’ll likely need to make a small script that
uses muxtools.ParsedFile
to get the correct properties of the tracks.Globby
is a helper function that returns the first Path that match a glob pattern.
It is used here to get a subtitle file from a folder matching a glob pattern.Processors
to apply select filters to the video.
Here we use Processors.denoise
and Processors.deband
to denoise and deband the video. There are only a select few filters
available, but they can make life easier if they are the ones you need.
Providing a custom Vapoursynth script is also possible via
vpy_script arg in Source