Skip to content

Advanced

We'll go over some advanced use cases.

User Tokens

In NfoForge, open Settings → User Tokens to manage user tokens.

Adding a User Token

To add a new token, select Add.

  • Double click the cell in the Token column that you just created to modify the token name.
  • Double click the cell in the Type column that you just created to select the desired token type.

What is the difference between FileTokens and NfoTokens?

FileTokens are used for file paths and are accessible everywhere file paths are needed.
NfoTokens are only available within NFO templates and cannot be used for file paths. NFOs, however, can use all FileTokens.

Below are two newly created tokens.

User NfoToken

User Tokens NfoToken

User FileToken

User Tokens FileToken

Example Usage

Below is an NFO template using our two example tokens.

User Tokens Example

Output

User Tokens Example

Example of file path token.

User Tokens Example

Global Tokens

These tokens are meant to be used in NFO templates. Each global token is prefixed with nf_.

Token Objects

All token objects resets to empty on Start Over or wizard reset. These tokens are updated dynamically throughout the flow of the program. Having this data available can be very powerful for advanced users.

{{ nf_shared_data }}

This token gives the user access to the SharedPayload dataclass. The field dynamic_data is specifically designed for plugins and numerous other functions that get filled throughout the workflow.

@dataclass(slots=True)
class SharedPayload:
    url_data: list[ImageUploadData] = field(default_factory=list)
    selected_trackers: Sequence[TrackerSelection] | None = None
    loaded_images: Sequence[Path] | None = None
    generated_images: bool = False
    is_comparison_images: bool = False
    dynamic_data: dict[str, Any] = field(default_factory=dict)
    release_notes: str | None = None
    encode_logs: str | None = None

    def reset(self) -> None:
        self.url_data.clear()
        self.selected_trackers = None
        self.loaded_images = None
        self.generated_images = False
        self.is_comparison_images = False
        self.dynamic_data.clear()
        self.release_notes = None
        self.encode_logs = None
{{ nf_media_search_payload }}

This token gives the user access to the MediaSearchPayload dataclass.

@dataclass(slots=True)
class MediaSearchPayload:
    media_type: MediaType | None = None
    imdb_id: str | None = None
    tmdb_id: str | None = None
    tmdb_data: dict | None = None
    tvdb_id: str | None = None
    tvdb_data: dict | None = None
    anilist_id: str | None = None
    anilist_data: dict | None = None
    mal_id: str | None = None
    title: str | None = None
    year: int | None = None
    original_title: str | None = None
    title_override: str | None = None
    genres: list[TMDBGenreIDsMovies | TMDBGenreIDsSeries] = field(default_factory=list)
    plot: str | None = None
    poster_url: str | None = None
    genre_names: tuple[str, ...] = ()
    media_kind: MetadataMediaKind | None = None
    plugin_data: dict[str, Any] = field(default_factory=dict)

    def reset(self) -> None:
        self.media_type = None
        self.imdb_id = None
        self.tmdb_id = None
        self.tmdb_data = None
        self.tvdb_id = None
        self.tvdb_data = None
        self.anilist_id = None
        self.anilist_data = None
        self.mal_id = None
        self.title = None
        self.year = None
        self.original_title = None
        self.title_override = None
        self.genres.clear()
        self.plot = None
        self.poster_url = None
        self.genre_names = ()
        self.media_kind = None
        self.plugin_data.clear()
{{ nf_media_input_payload }}

This token gives the user access to the MediaInputPayload dataclass.

@dataclass(slots=True)
class MediaInputPayload:
    input_path: Path | None = None
    media_type: MediaType | None = None
    working_dir: Path | None = None
    file_list: list[Path] = field(default_factory=list)
    file_list_mediainfo: dict[Path, MediaInfo] = field(default_factory=dict)
    comparison_pair: ComparisonPair | None = None
    series_episode_map: dict[Path, dict] | None = None
    series_episode_format: EpisodeFormat = EpisodeFormat.STANDARD

    def has_basic_data(self) -> bool:
        ...

    def require_input_path(self) -> Path:
        ...

    def require_media_type(self) -> MediaType:
        ...

    def require_working_dir(self) -> Path:
        ...

    def require_existing_media_paths(self, *, include_comparison: bool) -> None:
        ...

    def get_first_file(self, raise_error: bool = False) -> Path | None:
        ...

    def require_first_file(self) -> Path:
        ...

    def get_mediainfo(self, fp: Path) -> MediaInfo | None:
        ...

    def require_mediainfo(self, fp: Path) -> MediaInfo:
        ...

    def reset(self, input_path: Path | None = None) -> None:
        ...
Example Usage

The payload now exposes the selected input path, the discovered file list, and cached MediaInfo objects keyed by file path.

You can pull the first discovered file and its MediaInfo from the payload in a template.

{% set first_file = nf_media_input_payload.require_first_file() %}
{% set media_info = nf_media_input_payload.get_mediainfo(first_file) %}
{% if media_info %}
{{ media_info.to_data() }}
{% endif %}
{
    "tracks": [
        {
            "track_type": "General",
            "count": "350",
            "count_of_stream_of_this_kind": "1",
            "kind_of_stream": "General",
            "other_kind_of_stream": ["General"],
            "stream_identifier": "0",
            "count_of_video_streams": "1",
            "count_of_audio_streams": "2",
            "video_format_list": "AVC",
            "video_format_withhint_list": "AVC",
            "codecs_video": "AVC",
            "audio_format_list": "MPEG Audio / AC-3",
            "audio_format_withhint_list": "MPEG Audio / AC-3",
            "audio_codecs": "MPEG Audio / AC-3",
            "audio_channels_total": "8",
            "complete_name": "C:\\Users\\user\\Desktop\\sample\\example\\Big.Buck.Bunny.2008.BluRay.1080p.MP2.2.0.x264.mp4",
            "folder_name": "C:\\Users\\user\\Desktop\\sample\\example",
            "file_name_extension": "Big.Buck.Bunny.2008.BluRay.1080p.MP2.2.0.x264.mp4",
            "file_name": "Big.Buck.Bunny.2008.BluRay.1080p.MP2.2.0.x264",
            "file_extension": "mp4",
            "format": "MPEG-4",
            "other_format": ["MPEG-4"],
            "format_extensions_usually_used": "braw mov mp4 m4v m4a m4b m4p m4r 3ga 3gpa 3gpp 3gp 3gpp2 3g2 k3g jpm jpx mqv ismv isma ismt f4a f4b f4v",
            "commercial_name": "MPEG-4",
            "format_profile": "Base Media",
            "internet_media_type": "video/mp4",
            "codec_id": "isom",
            "other_codec_id": ["isom (isom/avc1)"],
            "codec_id_url": "http://www.apple.com/quicktime/download/standalone.html",
            "codecid_compatible": "isom/avc1",
            "file_size": 355040641,
            "other_file_size": [
                "339 MiB",
                "339 MiB",
                "339 MiB",
                "339 MiB",
                "338.6 MiB",
            ],
            "duration": 634500,
            "other_duration": [
                "10 min 34 s",
                "10 min 34 s 500 ms",
                "10 min 34 s",
                "00:10:34.500",
                "00:10:34:15",
                "00:10:34.500 (00:10:34:15)",
            ],
            "overall_bit_rate": 4476478,
            "other_overall_bit_rate": ["4 476 kb/s"],
            "frame_rate": "30.000",
            "other_frame_rate": ["30.000 FPS"],
            "frame_count": "19035",
            "stream_size": 236023,
            "other_stream_size": [
                "230 KiB (0%)",
                "230 KiB",
                "230 KiB",
                "230 KiB",
                "230.5 KiB",
                "230 KiB (0%)",
            ],
            "proportion_of_this_stream": "0.00066",
            "headersize": "235477",
            "datasize": "354805106",
            "footersize": "58",
            "isstreamable": "Yes",
            "title": "Big Buck Bunny, Sunflower version",
            "movie_name": "Big Buck Bunny, Sunflower version",
            "performer": "Blender Foundation 2008, Janus Bager Kristensen 2013",
            "composer": "Sacha Goedegebure",
            "genre": "Animation",
            "encoded_date": "2013-12-16 17:49:00 UTC",
            "tagged_date": "2013-12-16 17:49:00 UTC",
            "file_creation_date": "2025-07-30 22:09:03.199 UTC",
            "file_creation_date__local": "2025-07-30 18:09:03.199",
            "file_last_modification_date": "2013-12-17 17:49:05.000 UTC",
            "file_last_modification_date__local": "2013-12-17 13:49:05.000",
            "comment": "Creative Commons Attribution 3.0 - http://bbb3d.renderfarming.net",
            "com": "Jan Morgenstern",
        },
        {
            "track_type": "Video",
            "count": "391",
            "count_of_stream_of_this_kind": "1",
            "kind_of_stream": "Video",
            "other_kind_of_stream": ["Video"],
            "stream_identifier": "0",
            "streamorder": "0",
            "track_id": 1,
            "other_track_id": ["1"],
            "format": "AVC",
            "other_format": ["AVC"],
            "format_info": "Advanced Video Codec",
            "format_url": "http://developers.videolan.org/x264.html",
            "commercial_name": "AVC",
            "format_profile": "High@L4.2",
            "format_settings": "CABAC / 4 Ref Frames",
            "format_settings__cabac": "Yes",
            "other_format_settings__cabac": ["Yes"],
            "format_settings__reference_frames": 4,
            "other_format_settings__reference_frames": ["4 frames"],
            "internet_media_type": "video/H264",
            "codec_id": "avc1",
            "codec_id_info": "Advanced Video Coding",
            "duration": 634500,
            "other_duration": [
                "10 min 34 s",
                "10 min 34 s 500 ms",
                "10 min 34 s",
                "00:10:34.500",
                "00:10:34:15",
                "00:10:34.500 (00:10:34:15)",
            ],
            "bit_rate": 4000000,
            "other_bit_rate": ["4 000 kb/s"],
            "maximum_bit_rate": 25957272,
            "other_maximum_bit_rate": ["26.0 Mb/s"],
            "width": 1920,
            "other_width": ["1 920 pixels"],
            "height": 1080,
            "other_height": ["1 080 pixels"],
            "stored_height": "1088",
            "sampled_width": "1920",
            "sampled_height": "1080",
            "pixel_aspect_ratio": "1.000",
            "display_aspect_ratio": "1.778",
            "other_display_aspect_ratio": ["16:9"],
            "rotation": "0.000",
            "frame_rate_mode": "CFR",
            "other_frame_rate_mode": ["Constant"],
            "frame_rate": "30.000",
            "other_frame_rate": ["30.000 FPS"],
            "framerate_num": "30",
            "framerate_den": "1",
            "frame_count": "19035",
            "color_space": "YUV",
            "chroma_subsampling": "4:2:0",
            "other_chroma_subsampling": ["4:2:0"],
            "bit_depth": 8,
            "other_bit_depth": ["8 bits"],
            "scan_type": "Progressive",
            "other_scan_type": ["Progressive"],
            "bits__pixel_frame": "0.064",
            "stream_size": 316755338,
            "other_stream_size": [
                "302 MiB (89%)",
                "302 MiB",
                "302 MiB",
                "302 MiB",
                "302.1 MiB",
                "302 MiB (89%)",
            ],
            "proportion_of_this_stream": "0.89217",
            "writing_library": "x264 - core 115",
            "other_writing_library": ["x264 core 115"],
            "encoded_library_name": "x264",
            "encoded_library_version": "core 115",
            "encoding_settings": "cabac=1 / ref=4 / deblock=1:1:1 / analyse=0x3:0x133 / me=tesa / subme=10 / psy=1 / psy_rd=0.40:0.00 / mixed_ref=1 / me_range=24 / chroma_me=1 / trellis=2 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=0 / chroma_qp_offset=-2 / threads=12 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=16 / b_pyramid=2 / b_adapt=2 / b_bias=0 / direct=3 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=60 / rc=2pass / mbtree=1 / bitrate=4000 / ratetol=1.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / cplxblur=20.0 / qblur=0.5 / ip_ratio=1.40 / aq=1:0.60",
            "encoded_date": "2013-12-16 17:49:00 UTC",
            "tagged_date": "2013-12-16 17:49:05 UTC",
            "codec_configuration_box": "avcC",
        },
        {
            "track_type": "Audio",
            "count": "285",
            "count_of_stream_of_this_kind": "2",
            "kind_of_stream": "Audio",
            "other_kind_of_stream": ["Audio"],
            "stream_identifier": 0,
            "other_stream_identifier": ["1"],
            "streamorder": "1",
            "track_id": 2,
            "other_track_id": ["2"],
            "format": "MPEG Audio",
            "other_format": ["MPEG Audio"],
            "commercial_name": "MPEG Audio",
            "format_version": "Version 1",
            "format_profile": "Layer 3",
            "format_settings": "Joint stereo / MS Stereo",
            "mode": "Joint stereo",
            "mode_extension": "MS Stereo",
            "internet_media_type": "audio/mpeg",
            "codec_id": "mp4a-6B",
            "duration": 634200,
            "other_duration": [
                "10 min 34 s",
                "10 min 34 s 200 ms",
                "10 min 34 s",
                "00:10:34.200",
                "00:10:34.200",
            ],
            "bit_rate_mode": "CBR",
            "other_bit_rate_mode": ["Constant"],
            "bit_rate": 160000,
            "other_bit_rate": ["160 kb/s"],
            "maximum_bit_rate": 165120,
            "other_maximum_bit_rate": ["165 kb/s"],
            "channel_s": 2,
            "other_channel_s": ["2 channels"],
            "samples_per_frame": "1152",
            "sampling_rate": 48000,
            "other_sampling_rate": ["48.0 kHz"],
            "samples_count": "30440448",
            "frame_rate": "41.667",
            "other_frame_rate": ["41.667 FPS (1152 SPF)"],
            "frame_count": "26424",
            "compression_mode": "Lossy",
            "other_compression_mode": ["Lossy"],
            "stream_size": 12683520,
            "other_stream_size": [
                "12.1 MiB (4%)",
                "12 MiB",
                "12 MiB",
                "12.1 MiB",
                "12.10 MiB",
                "12.1 MiB (4%)",
            ],
            "proportion_of_this_stream": "0.03572",
            "writing_library": "LAME3.99r",
            "other_writing_library": ["LAME3.99r"],
            "encoding_settings": "-m j -V 4 -q 3 -lowpass 17.5 -b 160",
            "encoded_date": "2013-12-16 17:49:04 UTC",
            "tagged_date": "2013-12-16 17:49:05 UTC",
        },
        {
            "track_type": "Audio",
            "count": "301",
            "count_of_stream_of_this_kind": "2",
            "kind_of_stream": "Audio",
            "other_kind_of_stream": ["Audio"],
            "stream_identifier": 1,
            "other_stream_identifier": ["2"],
            "streamorder": "2",
            "track_id": 3,
            "other_track_id": ["3"],
            "format": "AC-3",
            "other_format": ["AC-3"],
            "format_info": "Audio Coding 3",
            "format_url": "https://en.wikipedia.org/wiki/AC3",
            "commercial_name": "Dolby Digital",
            "other_commercial_name": ["Dolby Digital"],
            "format_settings__endianness": "Big",
            "codec_id": "ac-3",
            "duration": 634143,
            "other_duration": [
                "10 min 34 s",
                "10 min 34 s 143 ms",
                "10 min 34 s",
                "00:10:34.143",
                "00:10:34.143",
            ],
            "bit_rate_mode": "CBR",
            "other_bit_rate_mode": ["Constant"],
            "bit_rate": 320000,
            "other_bit_rate": ["320 kb/s"],
            "channel_s": 6,
            "other_channel_s": ["6 channels"],
            "channel_positions": "Front: L C R, Side: L R, LFE",
            "other_channel_positions": ["3/2/0.1"],
            "channel_layout": "L R C LFE Ls Rs",
            "samples_per_frame": "1536",
            "sampling_rate": 48000,
            "other_sampling_rate": ["48.0 kHz"],
            "samples_count": "30438864",
            "frame_rate": "31.250",
            "other_frame_rate": ["31.250 FPS (1536 SPF)"],
            "frame_count": "19817",
            "compression_mode": "Lossy",
            "other_compression_mode": ["Lossy"],
            "stream_size": 25365760,
            "other_stream_size": [
                "24.2 MiB (7%)",
                "24 MiB",
                "24 MiB",
                "24.2 MiB",
                "24.19 MiB",
                "24.2 MiB (7%)",
            ],
            "proportion_of_this_stream": "0.07144",
            "service_kind": "CM",
            "other_service_kind": ["Complete Main"],
            "encoded_date": "2013-12-16 17:49:05 UTC",
            "tagged_date": "2013-12-16 17:49:05 UTC",
            "bsid": "8",
            "dialog_normalization": -31,
            "other_dialog_normalization": ["-31 dB"],
            "acmod": "7",
            "lfeon": "1",
            "cmixlev": "-4.5",
            "other_cmixlev": ["-4.5 dB"],
            "surmixlev": "-6 dB",
            "other_surmixlev": ["-6 dB"],
            "dialnorm_average": -31,
            "other_dialnorm_average": ["-31 dB"],
            "dialnorm_minimum": -31,
            "other_dialnorm_minimum": ["-31 dB"],
            "dialnorm_maximum": -31,
            "other_dialnorm_maximum": ["-31 dB"],
            "dialnorm_count": "32",
        },
    ]
}

To display the duration of the loaded object, first check that the object exists. Then, set a variable named general_track to the first general track, and access the first value in its other_duration list:

{% set first_file = nf_media_input_payload.require_first_file() %}
{% set media_info = nf_media_input_payload.get_mediainfo(first_file) %}
{% if media_info %}
{% set general_track = media_info.general_tracks[0] %}
{{ general_track.other_duration[0] }}
{% endif %}
10 min 34 s