A few weeks back I was on Reddit and I came across a post about automating several things in Plex using a tool named Plex Meta Manager (PMM). The Reddit thread eventually lead me to seamonkey420’s GitHub page where seamonkey420 laid out a configuration that looked great so I decided to give it a try. Me being lazy and not much of a programmer, I decided I would just use it as is. To say that effort failed miserably would be an understatement. I do want to offer a huge thank you to seamonkey420 though as it got me started on a path to success.
I’ve now spent hours digging through the Plex Meta Manager wiki and just when I thought the Wiki made sense and I tried to apply my newfound knowledge, I broke everything. Rinse and repeat. Via Discord PMM has a support feature and the people that support the tool are amazing. They took a look at my butchered config file and did more than just fix it, they explained line by line what my mistakes were and how to correct them.
Here are a few tips that I learned along the way, and at the end I post my entire config file along with a couple of sample images.
Tip 1: Installing PMM on QNAP Container Station
The QNAP walkthrough on PMM https://metamanager.wiki/en/latest/home/guides/qnap.html is not updated. Conceptually it’s correct, but none of the screenshots match the current version of Container Station. Here’s my updated QNAP walkthrough using QNAP QTS 5.1.1.2491 running on a QNAP TVS-872XT with Container Station version 3.0.5.623:
- Open Container Station; click “Images”
- Select “Pull” from the top-right
- Leave Mode set to “Basic Mode”
For the Registry select “Docker Hub”
Under the Image section you will be typing in the name and version of the Image you wish to pull. PMM offers three images to choose from: latest, develop and nightly. Choose one of the three and type in the one you wish to use as follows:
meisnate12/plex-meta-manager:latest
meisnate12/plex-meta-manager:develop
meisnate12/plex-meta-manager:nightly
Then click Pull.
Note: You can repeat this step for each of the different versions and you’ll end up with this: - After the Pull is complete the Image(s) will now be available for use.
- From the Images menu under the Actions Column click the Play button to bring up the “Create Container” option
- Create Container Step 1 Select Image – you’ve already done this so just click Next
- Create Container Step 2 Configure Container you can edit the name if you wish. From here on you’ll be working in the Advanced Settings sub-menu. Click on Advanced Settings.
- Under Advanced Settings > Commands you’ll find the “Command:” and “Entrypoint:” sections which are set to Default. In general you should not have to edit these.
- From the Advanced Settings Page select Environments.
You don’t have to change anything here, but you may wish to add more Environment Variables. The list of Variables are found on the PMM wiki.
One use case where I found setting Environments to be helpful is to change the default behavior so that as soon as the Container is started PMM begins to run instead of waiting for the default 5AM run time. Here’s an example of how I added the Environment variablePMM_RUN = true
to trigger this behavior: - The last Advanced Settings page you will need to get correct is the Storage Tab which now looks like this by default:
QNAP seems to want you to define volumes within Container Station that I suspect live within the Container, but I wanted to use a folder on the QNAP where I had dumped all my config files. To accomplish this, click the Trash Can icon to remove the default Storage Mapping- Click Add Volume then choose “Bind Mount Host Path”
- Select the Yellow Folder icon
“Select Host Path” will appear as seen below, letting you select the folder you want to use.
After selecting your folder and choosing Apply the Host path will be filled in as seen in the screenshot below. For the Container path you MUST use
/config
as seen belowSelect Apply to finish the Advanced Settings configuration.
- Click Add Volume then choose “Bind Mount Host Path”
- Under Advanced Settings > Commands you’ll find the “Command:” and “Entrypoint:” sections which are set to Default. In general you should not have to edit these.
- Select Next to advance to “Step 3 Summary”
- Select Finish
- Congratulations you’ve successfully configured PMM on QNAP.
Tip 2: Don’t use FlixPatrol
Up until recently, FlixPatrol could be called via PMM to build some dynamic collections in Plex based on things like “which movies on Disney+ are trending this week.” PMM’s Wiki offers details on how this stuff used to work; however within the last week FlixPatrol has moved many of their API’s behind a paywall requiring a “FlixPatrol Premium” license. FlixPatrol explains these changes in more details here. The end result is that now none of the FlixPatrol PMM features work so don’t attempt to add them into your config.yml file.
Tip 3: Understand the pmm YAML schema to avoid silly mistakes
Typing this seems silly in hindsight, but I did not understand the PMM yaml schema so when I was finding sample config.yml files online I was copy-and-pasting things all over the place in the config.yml file, not grasping that while the - pmm: Name
shows up under multiple parts of the config.yml file there is a specific purpose to each - pmm: Name
.
In general the config.yml is broken into 3 parts:
- metadata_path (used for Collections)
- overlay_path (used for Overlays)
- Operations (this can be its own separate section of the file or it can be part of the first two)
You will find the - pmm: Name
in both the metadata_path and the overlay_path sections but they are NOT ALWAYS interchangeable. For example the - pmm: actor
is used under the metadata_path because it is a collection, not an overlay. The - pmm: ribbon
is used in the overlay_path section because it is an overlay not a collection. But there are always exceptions, for example - pmm: studio
can be both an overlay and a collection.
The best way to avoid this silly error is to lookup the specific - pmm: Name
on the PMM Wiki and it will tell you if it belongs in the metadata_path or if it belongs in the overlay_path of the config.yml.
In conclusion: Here’s my config.yml
The end result in Plex looks like this for non-4K material:

The end result in Plex looks like this for 4K material:

I will probably try to tweak the placement for the 4K Audio codec so that it sits just below the 4KUHD black bar,but that experiment will be for another day.
A couple of important points:
- All the config files come directly from seamonkey420’s GitHub page so you should pull those first. Here’s that link THANK YOU seamonkey420!!!!!
- To use this file you need to change the names of each of the libraries to match your Plex server. For example I have a library named Christmas Films. Remove this entire section if you don’t have a library named Christmas Films or just rename it to match the name in Plex of your film library. Be careful not to mix Film libraries with TV show libraries as this file does different things for TV shows then it does for Movies.
- Line 338 is where you begin to change all of the API calls for your specific environment. I host my Plex Server directly on the QNAP and so instead of the IP address of the Plex server you need to know the correct full path to the Plex app. I left a sample of what the format looks like in here but it will be unique to your install of Plex.
- For each of the API’s starting on Line 345 (TMDb, Trakt, OMDb, and Mdblist) the PMM Wiki includes very detailed instructions for how to get your own API Keys and Tokens. Here are direct links to these documents:
libraries:
Movies:
metadata_path:
- file: config/movies_imdb.yml
- file: config/movies_tmdb.yml
- file: config/movies-rotten.yml
- file: config/movies-trakt.yml
- file: config/collections.yml
- pmm: separator_chart
- pmm: franchise
- pmm: universe
- pmm: content_rating_us
- pmm: resolution
- pmm: studio
- pmm: tmdb
overlay_path:
- remove_overlays: false # Set this to true to remove all overlays
- pmm: audio_codec
template_variables:
style: standard
horizontal_align: right
vertical_align: top
- pmm: ratings
template_variables:
rating1: critic
rating2: audience
rating3: user
rating1_image: imdb
rating2_image: rt_popcorn
rating3_image: tmdb
- file: config/overlays/imdb_top_250.yml
operations:
mass_critic_rating_update: imdb
mass_audience_rating_update: mdb_tomatoesaudience
mass_user_rating_update: tmdb
TV Shows: # TV Shows Library
overlay_path:
- remove_overlays: false # Set this to true to remove all overlays
- pmm: ratings
template_variables:
rating1: critic
rating2: audience
rating3: user
rating1_image: imdb
rating2_image: rt_popcorn
rating3_image: tmdb
- pmm: ratings
template_variables:
builder_level: episode
rating1: critic
rating2: audience
rating1_image: imdb
rating2_image: tmdb
metadata_path:
- file: config/collections.yml
- pmm: tmdb
- pmm: network
- pmm: streaming
- pmm: studio
- pmm: separator_chart
operations:
mass_critic_rating_update: imdb
mass_audience_rating_update: mdb_tomatoesaudience
mass_user_rating_update: tmdb
mass_episode_critic_rating_update: imdb
mass_episode_audience_rating_update: tmdb
4K: # 4K Movie Library
metadata_path:
- file: config/movies_imdb.yml
- file: config/movies_tmdb.yml
- file: config/movies-rotten.yml
- file: config/movies-trakt.yml
- file: config/collections.yml
- pmm: separator_chart
- pmm: franchise
- pmm: universe
- pmm: content_rating_us
- pmm: resolution
- pmm: studio
overlay_path:
- remove_overlays: false # Set this to true to remove all overlays
- file: config/overlays/4K.yml
- pmm: audio_codec
template_variables:
style: standard
horizontal_align: right
vertical_align: top
- pmm: ratings
template_variables:
rating1: critic
rating2: audience
rating3: user
rating1_image: imdb
rating2_image: rt_popcorn
rating3_image: tmdb
- file: config/overlays/imdb_top_250.yml
operations:
mass_critic_rating_update: imdb
mass_audience_rating_update: mdb_tomatoesaudience
mass_user_rating_update: tmdb
Christmas Films: # Christmas Films Library
metadata_path:
- file: config/movies_imdb.yml
- file: config/movies_tmdb.yml
- file: config/movies-rotten.yml
- file: config/movies-trakt.yml
- file: config/collections.yml
- pmm: separator_chart
- pmm: franchise
- pmm: universe
- pmm: content_rating_us
- pmm: resolution
- pmm: studio
overlay_path:
- remove_overlays: false # Set this to true to remove all overlays
- pmm: audio_codec
template_variables:
style: standard
horizontal_align: right
vertical_align: top
- pmm: ratings
template_variables:
rating1: critic
rating2: audience
rating3: user
rating1_image: imdb
rating2_image: rt_popcorn
rating3_image: tmdb
- file: config/overlays/imdb_top_250.yml
operations:
mass_critic_rating_update: imdb
mass_audience_rating_update: mdb_tomatoesaudience
mass_user_rating_update: tmdb
Classic Films: # Classic Films Library
metadata_path:
- file: config/movies_imdb.yml
- file: config/movies_tmdb.yml
- file: config/movies-rotten.yml
- file: config/movies-trakt.yml
- file: config/collections.yml
- pmm: separator_chart
- pmm: franchise
- pmm: universe
- pmm: content_rating_us
- pmm: resolution
- pmm: studio
overlay_path:
- remove_overlays: false # Set this to true to remove all overlays
- pmm: audio_codec
template_variables:
style: standard
horizontal_align: right
vertical_align: top
- pmm: ratings
template_variables:
rating1: critic
rating2: audience
rating3: user
rating1_image: imdb
rating2_image: rt_popcorn
rating3_image: tmdb
- file: config/overlays/imdb_top_250.yml
operations:
mass_critic_rating_update: imdb
mass_audience_rating_update: mdb_tomatoesaudience
mass_user_rating_update: tmdb
Horror: # Horror Films Library
metadata_path:
- file: config/movies_imdb.yml
- file: config/movies_tmdb.yml
- file: config/movies-rotten.yml
- file: config/movies-trakt.yml
- file: config/collections.yml
- pmm: separator_chart
- pmm: franchise
- pmm: universe
- pmm: content_rating_us
- pmm: resolution
- pmm: studio
overlay_path:
- remove_overlays: false # Set this to true to remove all overlays
- pmm: audio_codec
template_variables:
style: standard
horizontal_align: right
vertical_align: top
- pmm: ratings
template_variables:
rating1: critic
rating2: audience
rating3: user
rating1_image: imdb
rating2_image: rt_popcorn
rating3_image: tmdb
- file: config/overlays/imdb_top_250.yml
operations:
mass_critic_rating_update: imdb
mass_audience_rating_update: mdb_tomatoesaudience
mass_user_rating_update: tmdb
Kids Movies: # Kids Movies Films Library
metadata_path:
- file: config/movies_imdb.yml
- file: config/movies_tmdb.yml
- file: config/movies-rotten.yml
- file: config/movies-trakt.yml
- file: config/collections.yml
- pmm: separator_chart
- pmm: franchise
- pmm: universe
- pmm: content_rating_us
- pmm: resolution
- pmm: studio
overlay_path:
- remove_overlays: false # Set this to true to remove all overlays
- pmm: audio_codec
template_variables:
style: standard
horizontal_align: right
vertical_align: top
- pmm: ratings
template_variables:
rating1: critic
rating2: audience
rating3: user
rating1_image: imdb
rating2_image: rt_popcorn
rating3_image: tmdb
- file: config/overlays/imdb_top_250.yml
operations:
mass_critic_rating_update: imdb
mass_audience_rating_update: mdb_tomatoesaudience
mass_user_rating_update: tmdb
4K TV: # 4K TV Library
overlay_path:
- remove_overlays: false # Set this to true to remove all overlays
- pmm: ratings
template_variables:
rating1: critic
rating2: audience
rating3: user
rating1_image: imdb
rating2_image: rt_popcorn
rating3_image: tmdb
- pmm: ratings
template_variables:
builder_level: episode
rating1: critic
rating2: audience
rating1_image: imdb
rating2_image: tmdb
metadata_path:
- file: config/collections.yml
- pmm: tmdb
- pmm: network
- pmm: streaming
- pmm: studio
- pmm: separator_chart
operations:
mass_critic_rating_update: imdb
mass_audience_rating_update: mdb_tomatoesaudience
mass_user_rating_update: tmdb
mass_episode_critic_rating_update: imdb
mass_episode_audience_rating_update: tmdb
Cartoons: #Cartoons Library
overlay_path:
- remove_overlays: false # Set this to true to remove all overlays
- pmm: ratings
template_variables:
rating1: critic
rating2: audience
rating3: user
rating1_image: imdb
rating2_image: rt_popcorn
rating3_image: tmdb
- pmm: ratings
template_variables:
builder_level: episode
rating1: critic
rating2: audience
rating1_image: imdb
rating2_image: tmdb
metadata_path:
- file: config/collections.yml
- pmm: tmdb
- pmm: network
- pmm: streaming
- pmm: studio
- pmm: separator_chart
operations:
mass_critic_rating_update: imdb
mass_audience_rating_update: mdb_tomatoesaudience
mass_user_rating_update: tmdb
mass_episode_critic_rating_update: imdb
mass_episode_audience_rating_update: tmdb
playlist_files:
- pmm: playlist
template_variables:
libraries: Movies, 4K, Christmas Films, Classic Films, Horror, Kids Movies
settings:
cache: true
cache_expiration: 60
asset_directory: config/assets
asset_folders: true
asset_depth: 0
create_asset_folders: false
prioritize_assets: false
dimensional_asset_rename: false
download_url_assets: false
show_missing_season_assets: false
show_missing_episode_assets: false
show_asset_not_needed: true
sync_mode: append
minimum_items: 1
default_collection_order:
delete_below_minimum: true
delete_not_scheduled: false
run_again_delay: 2
missing_only_released: false
only_filter_missing: false
show_unmanaged: false
show_filtered: false
show_options: false
show_missing: false
show_missing_assets: false
save_report: false
tvdb_language: eng
ignore_ids:
ignore_imdb_ids:
item_refresh_delay: 0
playlist_sync_to_user: all
playlist_report: false
verify_ssl: true
custom_repo:
check_nightly: false
show_unconfigured: true
playlist_exclude_users:
# webhooks: # Can be individually specified per library as well
# error:
# version:
# run_start:
# run_end:
# changes:
# delete:
plex: # Can be individually specified per library as well; REQUIRED for the script to run
url: https://<YOURPLEXSERVERIPADDRESS.QnapRandomStringofNumbers.plex.direct:32400
token: YOURPLEXSERVERTOKEN
timeout: 60
clean_bundles: true
empty_trash: true
optimize: false
tmdb: # REQUIRED for the script to run
apikey: YOURTMDBTOKEN
language: en
cache_expiration: 60
region: US
trakt:
client_id: YOURTRAKTCLIENTID
client_secret: YOURTRAKTSECRET
authorization:
access_token: YOURTRAKTACCESSTOKEN
token_type: Bearer
expires_in: 7889238
refresh_token: YOURTRAKTREFRESHTOKEN
scope: public
created_at: YOURUNIQUEVALUE
omdb:
apikey: YOURAPIKEY
cache_expiration: 60
mdblist:
apikey: YOURAPIKEY
cache_expiration: 60
pin:
# everything below is autofilled by the script
access_token:
token_type:
expires_in:
refresh_token:
scope: public
created_at: