Utility to optimize media files for Direct Play in Plex, Emby, Jellyfin
Utility to optimize media files for Direct Play in Plex, Emby, Jellyfin.
Licensed under the MIT License
Code and Pipeline is on GitHub.
Binary releases are published on GitHub Releases.
Docker images are published on Docker Hub.
ProcessOptions:FileIgnoreMasks
to support skipping (not deleting) sample files per discussions request.
*
and ?
are supported, e.g. *.sample
or *.sample.*
.*.fuse_hidden*
.ProcessOptions:KeepExtensions
has been deprecated, existing values will be converted to ProcessOptions:FileIgnoreMasks
.
ProcessOptions:KeepExtensions
: .nfo
will be converted to ProcessOptions:FileIgnoreMasks
: *.nfo
.ConvertOptions:FfMpegOptions:Output
has been deprecated, no need to for user configurable values.ConvertOptions:FfMpegOptions:Global
no longer requires defaults values and will only be used during encoding, only add custom values for e.g. hardware acceleration, existing values will be converted.
-analyzeduration 2147483647 -probesize 2147483647 -hwaccel cuda -hwaccel_output_format cuda
will be converted to -hwaccel cuda -hwaccel_output_format cuda
.Newtonsoft.Json
to .NET native Text.Json
.Newtonsoft.Json.Schema
to JsonSchema.Net.Generation
.alpine-edge
.The objective of PlexCleaner is to modify media content such that it will always Direct Play in Plex, Emby, Jellyfin.
Below are examples of issues that can be resolved using the primary process
command:
Constrained Baseline@30
cause playback issues, re-encode to H.264 High@40
.--comb-detect --decomb
options.MuxingMode
attribute is not set, re-multiplex to set the correct MuxingMode
.Dolby Vision
(profile 5) vs. Dolby Vision / SMPTE ST 2086
(profile 7) that supports DV and HDR10/HDR10+ displays.process
command for more details.filename.mkv
-> filename.PlexCleaner
)--parallel
option, is useful when a single instance of FFmpeg or HandBrake does not saturate all the available CPU resources.--threadcount
option.Ctrl-C
, if using sidecar files restarting will skip previously verified files.Docker builds are the easiest and most up to date way to run, and can be used on any platform that supports linux/amd64
, linux/arm64
, or linux/arm/v7
architectures.
Alternatively, install directly on Windows, Linux, or MacOS following the provided instructions.
latest
is based on Ubuntu and contains the most up to date media processing tools.alpine
is based on Alpine and is the smallest image.debian
is based on Debian and supports the most platforms.screen
session.Example, run in an interactive shell:
# The host "/data/media" directory is mapped to the container "/media" directory
# Replace the volume mappings to suit your needs
# Run the bash shell in an interactive session
docker run \
-it \
--rm \
--pull always \
--name PlexCleaner \
--volume /data/media:/media:rw \
docker.io/ptr727/plexcleaner \
/bin/bash
# Create default settings file
# Edit the settings file to suit your needs
/PlexCleaner/PlexCleaner \
defaultsettings \
--settingsfile /media/PlexCleaner/PlexCleaner.json
# Process media files
/PlexCleaner/PlexCleaner \
--logfile /media/PlexCleaner/PlexCleaner.log \
process \
--settingsfile /media/PlexCleaner/PlexCleaner.json \
--mediafiles /media/Movies \
--mediafiles /media/Series
# Exit the interactive session
exit
Example, run in a screen session:
# Start a new screen session
screen
# Or attach to an existing screen session
screen -r
# Make sure the media file permissions allow writing
sudo chown -R nobody:users /data/media
sudo chmod -R u=rwx,g=rwx+s,o=rx /data/media
# Run the process command in an interactive session
docker run \
-it \
--rm \
--pull always \
--log-driver json-file --log-opt max-size=10m \
--name PlexCleaner \
--user nobody:users \
--env TZ=America/Los_Angeles \
--volume /data/media:/media:rw \
docker.io/ptr727/plexcleaner \
/PlexCleaner/PlexCleaner \
--logfile /media/PlexCleaner/PlexCleaner.log \
--logwarning \
process \
--settingsfile /media/PlexCleaner/PlexCleaner.json \
--parallel \
--mediafiles /media/Movies \
--mediafiles /media/Series
defaultsettings
command:
PlexCleaner defaultsettings --settingsfile PlexCleaner.json
checkfornewtools
command:
PlexCleaner checkfornewtools --settingsfile PlexCleaner.json
Tools
folder will be created in the same folder as the PlexCleaner
binary file.Tools\Tools.json
.checkfornewtools
command, or update tools on every run by setting ToolsOptions:AutoUpdate
to true
.ffmpeg-6.0-full.7z
: \Tools\FfMpeg
HandBrakeCLI-1.6.1-win-x86_64.zip
: \Tools\HandBrake
MediaInfo_CLI_23.07_Windows_x64.zip
: \Tools\MediaInfo
mkvtoolnix-64-bit-79.0.7z
: \Tools\MkvToolNix
7z2301-extra.7z
: \Tools\SevenZip
ToolsOptions:AutoUpdate
to false
.defaultsettings
command:
./PlexCleaner defaultsettings --settingsfile PlexCleaner.json
Create a default JSON configuration file by running:
PlexCleaner defaultsettings --settingsfile PlexCleaner.json
Refer to the commented default JSON settings file for usage.
The ConvertOptions:FfMpegOptions
and ConvertOptions:HandBrakeOptions
settings allows for custom CLI parameters to be used during processing.
Note that hardware assisted encoding options are operating system, hardware, and tool version specific.
Refer to the Jellyfin hardware acceleration docs for hints on usage.
The example configurations are from documentation and minimal testing with Intel QuickSync on Windows only, please discuss and post working configurations in Discussions.
See the FFmpeg documentation for complete commandline option details.
The typical FFmpeg commandline is ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url}
.
E.g. ffmpeg "-analyzeduration 2147483647 -probesize 2147483647 -i "/media/foo.mkv" -max_muxing_queue_size 1024 -abort_on empty_output -hide_banner -nostats -map 0 -c:v libx265 -crf 26 -preset medium -c:a ac3 -c:s copy -f matroska "/media/bar.mkv"
Settings allows for custom configuration of:
FfMpegOptions:Global
: Custom hardware global options, e.g. -hwaccel cuda -hwaccel_output_format cuda
FfMpegOptions:Video
: Video encoder options following the -c:v
parameter, e.g. libx264 -crf 22 -preset medium
FfMpegOptions:Audio
: Audio encoder options following the -c:a
parameter, e.g. ac3
Get encoder options:
ffmpeg -encoders
ffmpeg -h encoder=libsvtav1
Example video encoder options:
libx264 -crf 22 -preset medium
libx265 -crf 26 -preset medium
libsvtav1 -crf 30 -preset 5
Example hardware assisted video encoding options:
ffmpeg -h encoder=h264_qsv
FfMpegOptions:Global
: -hwaccel qsv -hwaccel_output_format qsv
FfMpegOptions:Video
: h264_qsv -crf 22 -preset medium
See the HandBrake documentation for complete commandline option details.
The typical HandBrake commandline is HandBrakeCLI [options] -i <source> -o <destination>
.
E.g. HandBrakeCLI --input "/media/foo.mkv" --output "/media/bar.mkv" --format av_mkv --encoder x265 --quality 26 --encoder-preset medium --comb-detect --decomb --all-audio --aencoder copy --audio-fallback ac3
Settings allows for custom configuration of:
HandBrakeOptions:Video
: Video encoder options following the --encode
parameter, e.g. x264 --quality 22 --encoder-preset medium
HandBrakeOptions:Audio
: Audio encoder options following the --aencode
parameter, e.g. copy --audio-fallback ac3
Get encoder options:
HandBrakeCLI.exe --help
HandBrakeCLI --encoder-preset-list svt_av1
Example video encoder options:
x264 --quality 22 --encoder-preset medium
x265 --quality 26 --encoder-preset medium
svt_av1 --quality 30 --encoder-preset 5
Example hardware assisted video encoding options:
HandBrakeOptions:Video
: nvenc_h264 --quality 22 --encoder-preset medium
HandBrakeOptions:Video
: qsv_h264 --quality 22 --encoder-preset medium
Note that HandBrake is primarily used for video deinterlacing, and only as backup encoder when FFmpeg fails.
The default HandBrakeOptions:Audio
configuration is set to copy --audio-fallback ac3
that will copy all supported audio tracks as is, and only encode to ac3
if the audio codec is not natively supported.
Language tag matching supports IETF / RFC 5646 / BCP 47 tag formats as implemented by MkvMerge.
During processing the absence of IETF language tags will treated as a track warning, and an RFC 5646 IETF language will be temporarily assigned based on the ISO639-2B tag.
If ProcessOptions.SetIetfLanguageTags
is enabled MkvMerge will be used to remux the file using the --normalize-language-ietf extlang
option, see the MkvMerge docs for more details.
Tags are in the form of language-extlang-script-region-variant-extension-privateuse
, and matching happens left to right.
E.g. pt
will match pt
Portuguese, or pt-BR
Brazilian Portuguese, or pt-PT
European Portuguese.
E.g. pt-BR
will only match only pt-BR
Brazilian Portuguese.
E.g. zh
will match zh
Chinese, or zh-Hans
simplified Chinese, or zh-Hant
for traditional Chinese, and other variants.
E.g. zh-Hans
will only match zh-Hans
simplified Chinese.
Normalized tags will be expanded for matching.
E.g. cmn-Hant
will be expanded to zh-cmn-Hant
allowing matching with zh
.
See the W3C Language tags in HTML and XML and BCP47 language subtag lookup for more details.
Use the PlexCleaner --help
commandline option to get a list of commands and options.
To get help for a specific command run PlexCleaner <command> --help
.
> ./PlexCleaner --help
Description:
Utility to optimize media files for Direct Play in Plex, Emby, Jellyfin
Usage:
PlexCleaner [command] [options]
Options:
--logfile <logfile> Path to log file
--logappend Append to existing log file
--logwarning Log warnings and errors only
--debug Wait for debugger to attach
--version Show version information
-?, -h, --help Show help and usage information
Commands:
defaultsettings Write default values to settings file
checkfornewtools Check for new tool versions and download if newer
process Process media files
monitor Monitor for file changes and process changed media files
remux Re-Multiplex media files
reencode Re-Encode media files
deinterlace De-Interlace media files
removesubtitles Remove subtitles from media files
createsidecar Create new sidecar files
updatesidecar Update existing sidecar files
getversioninfo Print application and tools version information
getsidecarinfo Print sidecar file information
gettagmap Print media information tag-map
getmediainfo Print media information using sidecar files
gettoolinfo Print media information using media tools
createschema Write settings schema to file
Global options apply to all commands.
--logfile
:
--logappend
:
--logwarning
:
--debug
:
> ./PlexCleaner process --help
Description:
Process media files
Usage:
PlexCleaner process [options]
Options:
--settingsfile <settingsfile> (REQUIRED) Path to settings file
--mediafiles <mediafiles> (REQUIRED) Path to media file or folder
--parallel Enable parallel processing
--threadcount <threadcount> Number of threads to use for parallel processing
--testsnippets Create short media clips
--testnomodify Do not make any file modifications
--reverify Re-verify and repair media files in the VerifyFailed state
--logfile <logfile> Path to log file
--logappend Append to existing log file
--logwarning Log warnings and errors only
--debug Wait for debugger to attach
-?, -h, --help Show help and usage information
The process
command will process the media content using options as defined in the settings file and the optional commandline arguments:
KeepExtensions
list.ReMuxExtensions
list to MKV container format.DefaultLanguage
for any track with an undefined language.PreferredAudioFormats
.KeepLanguages
list.ReEncodeVideo
.ReEncodeAudioFormats
list.Options:
--settingsfile
: (required)
--mediafiles
: (required)
--mediafiles path1 --mediafiles "path with space" --mediafiles file1 --mediafiles file2
.--reverify
:
VerifyFailed
state.--parallel
:
--threadcount
:
--parallel
option is enabled.--testsnippets
:
--testnomodify
:
Example:
./PlexCleaner \
--logfile PlexCleaner.log \
process \
--settingsfile PlexCleaner.json \
--parallel \
--mediafiles "C:\Foo With Space\Test.mkv" \
--mediafiles D:\Media
These commands have no conditional logic and will process all specified media files.
remux
:
reencode
:
deinterlace
:
removesubtitles
:
monitor
:
process
command on the changed folders.monitor
command honors the process
options.createsidecar
:
updatesidecar
:
gettagmap
:
getmediainfo
:
gettoolinfo
:
getsidecarinfo
:
getversioninfo
: