Post

Mastering JMTE Patterns for Exporting & Renaming in tinyMediaManager

Mastering JMTE Patterns for Exporting & Renaming in tinyMediaManager

When it comes to organizing media libraries with precision, tinyMediaManager (tMM) is one of the most powerful tools available. Whether you’re exporting data for Kodi, Plex, Jellyfin, or creating a custom file/folder naming scheme, tMM gives you complete control through its JMTE (Java Minimal Template Engine) integration.

In this post, we’ll dive into mastering JMTE patterns, especially focusing on:

  • Export templates
  • File and folder renaming
  • Conditional patterns with if
  • Testing templates with the JMTE Helper

If you’re new to JMTE or want to take your templates to the next level, this post will help you go from beginner to advanced user.


📂 What is JMTE and Why Should You Care?

JMTE is a lightweight templating engine for Java, used by tMM to allow customizable text output. This is especially useful for:

  • Exporting media metadata into HTML, NFO, JSON, etc.
  • Creating custom folder and filename structures when renaming

JMTE syntax is simple and flexible. You write placeholders like ${title}, ${year}, or ${mediaSource}, and tMM fills them in based on your media entries. But that’s just the start - JMTE also supports logic, loops, and filters.

👉 You can read the full syntax reference here: JMTE in tinyMediaManager Docs


🧪 Explore and Test with the JMTE Helper

Before jumping into real usage, get familiar with the JMTE helper built into tinyMediaManager. You can find it either in the renamer settings under:

1
2
Settings → Movies → Renamer
Settings → TV shows → Renamer

or in the tools menu:

1
Tools → JMTE helper

This tool allows you to:

  • Preview how your templates would render with real media data
  • Explore the full object tree available in export and rename contexts
  • Test conditional logic, filters, and structure

You can read the official announcement for the JMTE helper on the tinyMediaManager website to get a feeling what it can be used for.

🧭 Pro tip: Use the helper to “walk the object” - e.g. check what’s available under ${movie}, ${episode}, or ${tvShow}.


🧳 Using JMTE for Renaming Files and Folders

Renaming templates are powered entirely by JMTE. You can set templates for folder names and file names (and season folder in the TV show section):

1
2
Settings → Movies → Renamer
Settings → TV shows → Renamer

Let’s use the default pattern for a movie folder as our first example: ${title}${ - ,edition,} (${year}). Splitting this pattern apart will give us three different tokens:

  • ${title}: the movie title
  • ${ - ,edition,} : the edition of the movie (if available), separated by ` - `
  • (${year}): the year of the movie in brackets.

This would create folder name like Inception (2010).mkv without an edition set, and Inception - Collectors Edition (2010).mkv with the edition set.

💼 Be cautious: Not all variables are guaranteed to exist (e.g., edition). Use ${if ...} to avoid errors!


🛠️ Using JMTE in Export Templates

You can export movie and TV show data from tinyMediaManager using JMTE to generate custom output files for your media library. You can create or modify templates to export data as:

  • Text files (.txt)
  • CSV spreadsheets (.csv)
  • HTML pages (.html)
  • JSON files (.json)
  • XML files (.xml)

Each export template is a folder containing .jmte files (JMTE templates), a template.conf for metadata, and optional assets (like CSS or images). These templates define how your exported files will look and what data they include.

Example: CSV Export:

1
2
3
sep=,${-- first line defines fixed separator char; US defaults to "," non-US to ";" }
${foreach movies movie}${movie.title},${movie.year},${movie.dateAdded;date(yyyy-MM-dd)},${movie.path}
${end}

Example: HTML Export:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head></head>

  <body>
    <h1>Movie List</h1><br />
    <table>
${foreach movies movie}
      <tr>
        <td>${movie.title}</td>
        <td>${movie.year}</td>
        <td>${movie.rating}</td>
        <td>${movie.runtime}</td>
      </tr>
${end}
    </table>
  </body>
</html>

You can use all JMTE features - placeholders, filters, and logic - to customize the output. For example, to only show a tagline if it exists:

1
${if movie.tagline}<p class="tagline">${movie.tagline}</p>${end}

To get started, copy an existing template (like ListExampleCsv or ListExampleHtml), then edit the template.conf and .jmte files to fit your needs.

📝 More info: Export Templates Docs


❓ Conditional Patterns with IF

Now we get to the real power tool: conditional logic.

JMTE allows conditional rendering using IF expressions. This is critical when some media items don’t have certain properties.

Basic example:

1
${if edition}${edition} Edition${end}

Only shows the edition if it’s defined.

More advanced example with ELSE:

1
${if mediaSource}${mediaSource}${else}Unknown Source${end}

The short version of the above pattern:

1
${mediaSource(Unknown Source)}

Equations:

1
${if codec = "h265"}HEVC${else}${codec}${end}

Or negated:

1
${if ! codec = "h265"}${codec}${else}HEVC${end}

There are much more alternatives to try out - just check the official docs. And always test these in the JMTE Helper to be sure!


🔁 Looping Over Multiple Entries with JMTE

JMTE supports looping over collections, allowing you to expand a template block for each item in a list. This is especially useful for displaying all genres, audio tracks, or other multi-value fields in your media entries.

The basic syntax is:

1
2
3
${foreach collection item}
  ... use ${item} or its properties ...
${end}

For example, to list all genres for a movie:

1
${foreach movie.genres genre}${genre}${if !last}, ${end}${end}

Or to show all audio tracks:

1
2
3
${foreach movie.mainVideoFile.audioStreams audio}
  <li>${audio.language} - ${audio.codec}</li>
${end}

You can use special variables like first, last, and index inside the loop for advanced formatting. For more details, see the official docs: JMTE Loops.


🖌️ Using Renderers in JMTE Templates

Renderers in JMTE allow you to transform and format values directly within your templates - making your output cleaner and more flexible without extra post-processing. Renderers are functions you can apply to variables using a semicolon, e.g., ${date;date("yyyy-MM-dd")} to format a date, or ${seasonNr;pad(2)} to pad a number with leading zeros.

Common use cases include:

  • Date formatting:
    1
    
    ${movie.dateAdded;date("yyyy-MM-dd")}
    
  • Padding numbers:
    1
    
    ${seasonNr;pad(2)}
    
  • String manipulation:
    1
    2
    
    ${title;upper}
    ${title;lower}
    
  • Replacing characters:
    1
    
    ${title;replace(" ", "_")}
    

Renderers can be chained for more complex transformations. For a full list of available renderers and their options, see the official docs:


🧬 Deep Navigation in JMTE Entries

JMTE lets you access deeply nested properties by chaining references through the object tree. For example, ${movie.mediaFiles} gives you access to all media files of a movie, and you can further access their attributes like ${mediaFile.fileName} or ${mediaFile.audioStreams}. Each reference leads to another entity with its own set of attributes, allowing you to build complex templates that pull exactly the data you need.

You can navigate as deep as the data structure allows. For instance:

1
2
3
4
5
6
${foreach movie.mediaFiles mediaFile}
  File: ${mediaFile.fileName}
  ${foreach mediaFile.audioStreams audio}
    Audio: ${audio.language} (${audio.codec})
  ${end}
${end}

The full list of available entries and their structure can be found in the JMTE documentation. Use the JMTE Helper in tinyMediaManager to explore the object tree interactively and discover all available properties for your templates.


🧰 Best Practices for Clean JMTE Templates

📌 A few clean-code practices to keep your templates solid:

  • Avoid magic values: Use fallbacks with else blocks.
  • Handle empty values safely: Always use ${if ...} or conditionals for optional properties.
  • Use renderers for formatting:

    1
    
    ${date;date("yyyy-MM-dd")}
    
  • Keep templates readable: Break long lines, add comments:

    1
    2
    3
    
    ${if videoFormat}
      [${videoFormat}]
    ${end}
    

🧭 Real-World Use Cases

  • Export templates shipped by tinyMediaManager
  • Default movie renamer patterns:
    • Folder name - ${title}${ - ,edition,} (${year})
    • Filename - ${title}${ - ,edition,} (${year}) ${videoFormat} ${audioCodec}
  • Default TV show renamer patterns:
    • Folder name - ${showTitle} (${showYear})
    • Season folder name - Season ${seasonNr}
    • Episode filename - ${showTitle} - S${seasonNr2}E${episodeNr2} - ${title}
  • Plex-optimized movie renamer pattern: ${title} (${year}) {imdb-${imdb}} {$\{edition-,edition,\}} (${videoFormat}} (${videoCodec})

🧠 Final Thoughts

Mastering JMTE inside tinyMediaManager opens the door to total control over how your media is exported and renamed. Whether you’re a casual user or a media hoarder with thousands of files, custom templates can save you hours and avoid naming chaos.

🛠️ Use the JMTE Helper early and often. It’s your best friend in this journey.

📚 And don’t forget to bookmark the official docs:

With a bit of logic and clean template design, your media library will look and behave exactly how you want it. Happy templating!

This post is licensed under CC BY 4.0 by the author.