FFEncoder is a cross-platform PowerShell script and module that is meant to make high definition video encoding workflows easier. FFEncoder uses ffmpeg, ffprobe, VapourSynth, Mkvtoolnix, the x264 H.264 encoder, and the x265 H.265 HEVC encoder to compress, filter, and multiplex multimedia files for streaming or archiving.
Dynamic Metadata such as Dolby Vision and/or HDR10+ is fully supported.
FFEncoder is a simple script that allows you to pass dynamic parameters to ffmpeg without needing to modify complicated CLI arguments for each source. As much as I love the ffmpeg suite, it can be complicated to learn and use; the syntax is extensive, and many of the arguments are not easy to remember unless you use them often. The goal of FFEncoder is to take common encoding workflows and make them easier, while continuing to leverage the power and flexibility of the ffmpeg tool chain.
Capability can be further expanded with the VapourSynth frameserver. FFEncoder fully supports audio, subtitle, and chapter options and will mux the streams together for you after the encode finishes. Other than video filtering options, every parameter available works with VapourSynth scripts.
Check out the wiki for additional information.
For Windows users, PowerShell 7.x is a supplemental installation and will will be installed alongside PowerShell 5.1
NOTE: PowerShell 7.3 completely changed the way string arguments are parsed with third party executables. I have updated the code to support this, and it should be backward compatible to version 7.0.0. If issues are found, please let me know
- ffmpeg / ffprobe
- PowerShell v. 7.0 or newer
- Mkvtoolnix (optional, but highly recommended)
- VapourSynth (optional)
- Dolby Encoding Engine (DEE) (optional)
For users with PowerShell 7.2 or newer, the script uses ANSI output in certain scenarios to enhance the console experience.
Expand
You can compile ffmpeg manually from source on all platforms, which allows you to select additional libraries (like Fraunhofer's libfdk AAC encoder). Some features of this script are unavailable unless these libraries are included. For more information, see here.
To download ffmpeg, navigate to the ffmpeg downloads page and install one of the prebuilt Windows exe packages. I recommend the builds provided by Gyan.
To install the latest version of PowerShell 7, follow the instructions provided by Microsoft here.
You can install ffmpeg using your distro's package manager (apt/yum/pacman/zypper):
apt install ffmpeg
To install PowerShell 7, see Microsoft's instructions for your distribution here.
The easiest way to install ffmpeg and PowerShell 7 is through the Homebrew package manager:
brew install ffmpeg
One of the other benefits of using Homebrew is that you can easily install a build that includes non-free libraries like fdk_aac:
brew install ffmpeg --with-fdk-aac
To install PowerShell, run the following command using Homebrew:
brew install --cask powershell
The following binaries are expected to be available via system PATH in order for the script to work properly:
- ffmpeg
- ffprobe
- x265 (Dolby Vision Only)
- mkvextract, mkvmerge, mkvpropedit (optional, but recommended)
- These should be added to PATH automatically when you install MkvToolNix
- Dolby Encoding Engine, AKA dee (Optional)
Adding contents to PATH is relatively straightforward and platform dependent. Below are some examples of how you can add software to your system PATH:
# Whatever the path is to your ffmpeg install
$ffmpeg = 'C:\Users\SomeUser\Software\ffmpeg.exe'
$ffprobe = 'C:\Users\SomeUser\Software\ffprobe.exe'
$newPath = $env:PATH + ";$ffmpeg;$ffprobe"
[Environment]::SetEnvironmentVariable('PATH', $newPath, 'User')
# Now close and reopen PowerShell to update
Here is a quick example using bash/zsh on Linux/macOS:
# Set this equal to wherever ffmpeg is
ffmpeg="/home/someuser/software/ffmpeg"
# If you're using zsh (mac default), replace .bashrc with .zshrc
echo "export PATH=${ffmpeg}:${PATH}" >> ~/.bashrc
# Source the file to update
source ~/.bashrc
NOTE: FFEncoder uses modulus 2 rounding to detect black borders. I've found this to be the most consistent choice for the majority content. If you do not want the script to auto-crop your video, you may pass override crop values via the
-FFMpegExtra
parameter (see here for more info)
FFEncoder will auto-crop your video, and works similarly to programs like Handbrake with more emphasis on accuracy. The script analyzes up to 6 separate segments of the source simultaneously, collects the output, and saves it to a file which is used to determine cropping values for encoding.
FFEncoder will automatically fetch and fill HDR metadata before encoding begins. This includes:
NOTE: Color Range (Limited) and Chroma Subsampling (4:2:0) are currently hard coded as they are the same for all Blu-Ray sources. If you need dynamic parameters, put in a feature request and I will add them.
- Mastering Display Color Primaries
- Pixel format
- Color Space (Matrix Coefficients)
- Color Primaries
- Color Transfer Characteristics
- Maximum/Minimum Luminance
- Maximum Content Light Level
- Maximum Frame Average Light Level
- HDR10+ Metadata
- WARNING: Depending on the source, the metadata ordering may be incorrect after extraction. Evaluate the generated JSON file manually and use the
-HDR10PlusSkipReorder
parameter if necessary to correct this- Read the author's documentation to learn why this parameter might be required and when to use it
- WARNING: Depending on the source, the metadata ordering may be incorrect after extraction. Evaluate the generated JSON file manually and use the
- Dolby Vision Metadata
- Automatically edits the generated RPU file to ensure the metadata is accurate
- Requires
x265
(mods are fine) to be available via PATH because ffmpeg still doesn't handle RPU files correctly, even in version 5. If there is more than onex265*
option in PATH, the first option returned is selected - Currently, only profile 8.1 is supported due it it's backwards compatibility with HDR10
- It is recommended to have
mkvmerge
/mkvextract
available. The script will multiplex tracks back together after encoding
FFEncoder supports the following rate control options:
- Constant Rate Factor (CRF) - CRF encoding targets a specific quality level throughout, and isn't concerned with file size. Lower CRF values will result in a higher perceived quality and bitrate. For those familiar with Handbrake, this is essentially the same as
RF
- For high quality encodes, CRF 17-19 is generally considered a good starting range.
- If file size is more important than quality, CRF 20-23 is a good starting range
- Average Bitrate (Not Adaptive Bitrate) - This is also sometimes referred to as Variable Constrained Bitrate encoding. Average bitrate encoding targets a specific output file size, and isn't concerned with quality. There are 2 varieties of ABR encoding that FFEncoder supports:
- 1-Pass - This option uses a single pass, and isn't aware of the complexities of future frames and can only be scaled based on the past. Lower quality than 2-pass, but faster
- 2-Pass - 2-Pass encoding uses a first pass to calculate bitrate distribution, which is then used to allocate bits more accurately on the second pass
- Constant QP - Forces a constant quantization parameter value throughout the entire encode in the form of an integer value (0 - 51). This is useful for testing as well as comparing the efficacy of encoders
- NOTE: Forcing a constant QP will generally result in poor compression efficiency, and thus it is not recommended for general use (unless you know what you're doing)
The script can compare two files using Netflix's Video Multi-Method Assessment Fusion (VMAF) as a quality measurement.
The machine Learning model files are already provided, and Frames-Per-Second (FPS), resolution/cropping, and scaling are handled automatically; libvmaf
requires that these parameters be identical before it will run.
Additionally, you may add SSIM
and PSNR
measurements as well during the same VMAF run - see the wiki for full details.
If the selected output format is Matroska (MKV), you can use the parameter -GenerateMKVTagFile
(or its alias, -CreateTagFile
) to dynamically pull down metadata from TMDB, create a valid XML file, and multiplex it into the output file. This allows you to add useful metadata to your container for things like Plex and Emby to detect, or add other cool properties like Directors, Writers, and Actors for your own reference; any parameter that is available via the TMDB API can be added to your container.
To use this parameter, you will need a valid TMDB API key. See the wiki for more information.
Three configuration files, ffmpeg.ini
, encoder.ini
, and script.ini
, are included and can be leveraged to set frequently used options. These files are located in the config
directory and are loaded each time the script runs.
See the wiki for more information.
FFEncoder can accept the following parameters from the command line:
An Asterisk * denotes that the parameter is mandatory only for its given parameter set (for example, you can choose either
-CRF
or-VideoBitrate
for rate control, but not both):
Parameter Name | Default | Mandatory | Alias | Description | Mandatory For |
---|---|---|---|---|---|
InputPath | N/A | True | I, Source, Reference | The path to the source file, i.e. remux. Also acts as the reference path for VMAF comparisons | All |
OutputPath | N/A | True | O, Encode, Distorted | The path of the the encoded output file, or the encoded (distorted) file path during VMAF comparisons | All |
CRF | N/A | *True | C | Rate control parameter that targets a specific quality level. Ranges from 0.0 to 51.0. Lower values result in higher quality | Rate Control |
ConstantQP | N/A | *True | QP | Constant quantizer rate control mode. Forces a consistent QP throughout the encode. Generally not recommended outside of testing. | Rate Control |
VideoBitrate | N/A | *True | VBitrate | Rate control parameter that targets a specific bitrate. Can be used as an alternative to CRF when file size is a priority | Rate Control |
ScaleKernel | None | *True | ResizeKernel | Scaling/resizing filter to use. See Rescaling Video for more info | Scaling |
Unsharp | None | *True | U | Enable unsharp filter and set search range, in the form <luma|chroma|yuv>_<small|medium|large> or custom=<filter> |
Sharpen/Blur |
CompareVMAF | N/A | *True | None | Flag to enable a VMAF comparison on two video files | VMAF |
Parameter Name | Default | Mandatory | Alias | Description |
---|---|---|---|---|
Help | False | False | H, ? | Switch to display help information, including examples and parameter descriptions |
RemoveFiles | False | False | Del, RM | Switch that deletes extra files generated by the script (crop file, log file, etc.). Does not delete the input, output, or report file (if created) |
GenerateReport | False | False | Report, GR | Switch that generates a report file of the encode. Data is pulled from the log file and written in a reading friendly format |
GenerateMKVTagFile | False | False | CreateTagFile | Generates an MKV tag file using the TMDB API (key required). See the wiki |
Verbose | False | False | None | CmdletBinding switch to enable verbose logging - cascaded down to relevant functions for additional information. Useful for debugging |
ExitOnError | False | False | Exit | Switch that forcibly exits the script on certain non-terminating errors that prompt for re-input. Can be used to prevent blocking during automation |
EnablePSNR | False | False | PSNR | Enables an additional Peak Signal-to-Noise (PSNR) measurement during VMAF comparisons |
EnableSSIM | False | False | SSIM | Specify the resizing kernel used for upscaling/downscaling encodes for comparison |
VMAFResizeKernel | BiCubic | False | VMAFKernel | Enables an additional Structural Similarity Index (SSIM) measurement during VMAF comparisons |
DisableProgress | False | False | NoProgressBar | Switch to disable the progress bar during encoding |
See Audio Options and Subtitle Options in the wiki for more info
Using deew requires some initial configuration before it will work properly. See the wiki for more info
Parameter Name | Default | Mandatory | Alias | Description |
---|---|---|---|---|
Audio | Copy | False | A | Audio preference for the primary stream |
AudioBitrate | Codec | False | AB, ABitrate | Specifies the bitrate for -Audio (primary stream). Compatible with Dolby DEE, AAC, FDK AAC, AC3, EAC3, and DTS |
Stereo | False | False | 2CH, ST | Switch to downmix the first audio track to stereo |
Audio2 | None | False | A2 | Audio preference for the secondary stream |
AudioBitrate2 | Codec | False | AB2, ABitrate2 | Specifies the bitrate for -Audio2 (secondary stream). Compatible with Dolby DEE, AAC, FDK AAC, AC3, EAC3, and DTS |
Stereo2 | False | False | 2CH2, ST2 | Switch to downmix the second audio track to stereo |
Subtitles | Default | False | S, Subs | Subtitle passthrough preference |
See the Mandatory section above for parameters needed to enable certain filters
Parameter Name | Default | Mandatory | Alias | Description |
---|---|---|---|---|
Deinterlace | Disabled | False | DI | Switch to enable deinterlacing of interlaced content using yadif |
NLMeans | Disabled | False | NL | High quality de-noising filter. Accepts a hashtable containing 5 values. See here for more info |
Scale | bilinear | False | ScaleType, SF | Scaling/resizing filter to use. See Rescaling Video for more info |
Resolution | Source Dependent | False | Res, R | Scaling resolution. See Rescaling Video for more info |
UnsharpStrength | luma_mild | False | UStrength | Specify the unsharp filters strength, in the form <sharpen|blur>_<mild|medium|strong> |
Parameter Name | Default | Mandatory | Alias | Description |
---|---|---|---|---|
Encoder | x265 | False | Enc | Specifies which encoder to use - x264 or x265 |
FirstPassType | Default | False | PassType, FTP | Tuning option for two pass encoding. See Two Pass Encoding Options for more info |
SkipDolbyVision | False | False | NoDV, SDV | Switch to disable Dolby Vision encoding, even if metadata is present |
SkipHDR10Plus | False | False | No10P, NTP | Switch to disable HDR10+ encoding, even if metadata is present |
HDR10PlusSkipReorder | False | False | SkipReorder | Switch to correct improper HDR10+ metadata ordering on some sources. You must verify yourself if this is required or not |
TestFrames | 0 (Disabled) | False | T, Test | Integer value representing the number of test frames to encode. When -TestStart is not set, encoding starts at 00:01:30 so that title screens are skipped |
TestStart | Disabled | False | Start, TS | Starting point for test encodes. Accepts formats 00:01:30 (sexagesimal time), 200f (frame start), 200t (decimal time in seconds) |
VapourSynthScript | Disabled | False | VSScript, VPY | Path to VapourSynth script. Video filtering parameters are ignored when enabled, and must be done in the vpy script |
NOTE: Encoder means the default is specific to the encoder used. System is based on system hardware
Parameter Name | Default | Mandatory | Alias | Description |
---|---|---|---|---|
AqMode | 2 | False | AQM | x265 Adaptive Quantization setting. Ranges from 0 - 4. See the x265 Docs for more info on AQ Modes and how they work |
AqStrength | 1.00 | False | AQS | Adjusts the adaptive quantization offsets for AQ. Raising AqStrength higher than 2 will drastically affect the QP offsets, and can lead to high bitrates |
Deblock | -2, -2 | False | DBF | Deblock filter. The first value controls strength, and the second value controls threshold. Passed as an array in the form (alpha, beta) |
BFrames | Preset | False | B | The number of consecutive B-Frames within a GOP. This is especially helpful for test encodes to determine the ideal number of B-Frames to use |
Level | None | False | Level, L | Specify the encoder level for device compatibility. Default is unset, and will be chosen by the encoder based on rate control. Affects VBV options (see below) |
Merange | Preset | False | MR | Sets the motion estimation search range. Higher values result in a better motion vector search during inter-frame prediction |
NoiseReduction | Encoder | False | NR | Fast Noise reduction filter. For x265, the first value represents intra frames, and the second value inter frames; values range from 0-2000 |
Pass | 2 | False | None | The number of passes the encoder will perform on ABR encodes. Used with the -VideoBitrate parameter. Default is 2-Pass |
Preset | Slow | False | P | The x265 preset to be used. Ranges from placebo (slowest) to ultrafast (fastest). See x265 documentation for more info on preset options |
PsyRd | Encoder | False | PsyRDO | Psycho-visual enhancement. Strongly favor similar energy over blur. For x264, you can set psy-RDO & psy-trellis (i.e. 1.00,0.04 ) or psyRDO only |
PsyRdoq | Preset | False | PsyTrellis | Psycho-visual enhancement. Favors high AC energy in the reconstructed image. For x264, this can be used to set psy-trellis separately from psy-RDO |
QComp | 0.60 | False | Q | Sets the quantizer curve compression factor, which effects the bitrate variance throughout the encode. x265: Must be between 0.50 and 1.0. x264: Between 0 and 1 |
RCLookahead | Preset | False | RCL, Lookahead | Sets the rate control lookahead option. Larger values use more memory, but can improve compression efficiency |
Ref | Preset | False | None | Sets the number of reference frames to use. Default value is based on the encoder preset. For x264, this might affect hardware compatibility |
Subme | Preset | False | Subpel, SPM | The amount of subpel motion refinement to perform. At values larger than 2, chroma residual cost is included. Has a significant performance impact |
Threads | System | False | FrameThreads | Set the number of threads. More threads equate to faster encoding. System default is based on the number of logical CPU cores |
Tree | 1 (Enabled) | False | CUTree, MBTree | Enable or disable encoder-specific lowres motion vector lookahead algorithm. 1 is enabled, 0 is disabled. Best disabled for noisy content |
VBV | Level |
False | None | Video buffering verifier. Default is based on the encoder level (except DoVi, which defaults to level 5.1). Requires 2 arguments: (vbv-bufsize , vbv-maxrate ) |
Parameter Name | Default | Mandatory | Alias | Description |
---|---|---|---|---|
BIntra | Preset | False | BINT | Enables the evaluation of intra modes in B slices. Has a minor impact on performance |
LimitTU | 0 | False | LTU | Limits the TU recursion depth based on the value passed. Acceptable values are 0 - 4. Settings are not linear, and have different impacts |
TuDepth | 1, 1 | False | TU | Transform Unit recursion depth. Accepted values are 1-4. First value represents intra depth, and the second value inter depth, i.e. (tu-intra-depth , tu-inter-depth ) |
StrongIntraSmoothing | 1 (on) | False | SIS | Enable/disable strong-intra-smoothing. Accepted values are 1 (on) and 0 (off) |
See here for examples of how to use these parameters
Parameter Name | Default | Mandatory | Alias | Description |
---|---|---|---|---|
FFMpegExtra | N/A | False | FE | Pass additional settings to ffmpeg as a generic array of single and multi-valued elements. Useful for options not covered by other parameters |
EncoderExtra | N/A | False | XE | Pass additional settings to the specified encoder as a hashtable of values. Useful for options not covered by other parameters |
This section contains acknowledgements for the authors of tools distributed with this project. All credit goes to them!
- dovi_tool - Developed by quietvoid
- hdr10plus_tool - Developed by quietvoid
- deew - While this project contains a modified, custom compiled version of
deew
, the original project was developed by pcroland
Not distributed with the project, although used frequently in various pieces of the automation for those who have it installed. An invaluable tool for any video enthusiast (consider contributing to their development!):
- MkvToolNix - Developed by Mortiz Bunkus