# Overview

This article shall give an example of the settings and best practices that we can use in the encoding configurations with Per-Title when we have a use case where we are restricted to specific requirements for renditions or bitrates. Following this tutorial, it is expected to have basic knowledge about the Per-Title functionality and how to set up a basic configuration. A comprehensive overview of the available parameters is available in [Per-Title Configuration Options explained](🔗).

# Use case requirements

The described use case has the following requirements and shall demonstrate an example.

  • We want to encode a fixed amount of H.264 renditions with specified resolutions.

  • We want to specify the maximum bitrate for each rendition.

  • The Per-Title algorithm shall calculate the optimal bitrate for each rendition to achieve an optimised bitrate ladder ([What is Per-Title Encoding?](🔗)).

An example could be if we want to take the recommended bitrate ladder from Apple for H.264 and limit the bitrate to these specifications. Still, according to the complexity of the content, we want to save as much bandwidth as possible.

416 x 234145k
640 x 360365k
768 x 432730k
768 x 4321100k
960 x 5402000k
1280 x 7203000k
1280 x 7204500k
1920 x 10806000k
1920 x 10807800k

_Table1: HTTP Live Streaming (HLS) Authoring Specification for Apple Devices_

# Stream Modes

When configuring Per-Title, we need to specify at least one Per-Title template for the stream mode to enable the algorithm to do its magic.

These three different kinds of Per-Title-Templates are available.




For a simple Per-Title encoding, we usually specify one `PER_TITLE_TEMPLATE`, enable `autoRepresentations`, and Per-Title will take care of the rest. More information can be found in our tutorial [How to create a Per-Title Encoding](🔗).

But according to our requirements, we need control over the resolutions and bitrates of each of our renditions; therefore, we will specify one `PER_TITLE_TEMPLATE_FIXED_RESOLUTION_AND_BITRATE` per required rendition.

# Creating stream templates and setting encoding parameters

To specify the resolution and the maximum bitrate, we must create one stream template for each rendition. We assign individual H.264 configurations with the required `width` or `height` specified. In the `per_title_settings` of the streams, we set our boundaries via the `stream_fixed_res_bit_settings`. The here-defined `min_bitrate` and `max_bitrate` per rendition are crucial to enable Per-Title to pick the correct renditions. Together with the common settings `min_bitrate_step_size`, `max_bitrate_step_size`, `min_bitrate` and `max_bitrate` in the Per-Title settings' `start_encoding_request`, it is essential to find the right combination. Suppose these settings are not optimised to each other; in that case, Per-Title will be forced to drop desired renditions or add additional unwanted renditions. In the worst case, finding renditions based on the given boundaries is impossible, leading to an encoding error.

To start with, we can specify all the settings specific to the single renditions in an object to keep a clear overview.

The `width` and the `max` (bitrate) are clear; this comes from our initial requirements. The`min` (bitrate) needs a bit of gut feeling (or complicated calculation). You don't want to set this parameter too low, even if this seems to widen the boundaries. As said before, this parameter works especially in combination with the `min_bitrate_step_size` and the `max_bitrate_step_size` in the `start_encoding_request` settings.

While the `width` (or the `height`) is specified in the configuration,

the individual `min_bitrate` and `max_bitrate` are configured in the stream settings.

For this use case, I found promising results for the `min_bitrate` by dividing the `max_bitrate` / `max_bitrate_stepsize` and setting the `max_bitrate_stepsize = 4`. Increasing the `max_bitrate_stepsize` was also necessary to set the proper boundaries for this use case. Here we have a good example of what happens when not finding the correct settings – Per-Title was forced to generate only seven renditions out of the nine desired renditions when using the default setting of `max_bitrate_stepsize = 1.9`.

The same counts for the `min_bitrate_step_size`; this can also mess up the algorithm if not chosen carefully. Having found the right combination of bitrate and step size settings, one must understand that the normal Per-Title behaviour calculates the renditions from bottom to top. To gain some influence over the bitrate of the highest rendition, we can use the `COMPLEXITY_RANGE` in the `bitrate_selection_mode` of the stream settings.

Here the algorithm first calculates the bitrate of the top rendition in the ladder based on the complexity analysis of the source file and the configured Per-Title settings (such as `targetQualityCrf` and `complexityFactor`) and takes this into account while picking the renditions. It then compares this top bitrate with a configurable complexity range defined by its minimum and maximum bitrates. To ensure that the highest rendition falls into this range, in this use case, I specified the min and max values according to the specified min and max bitrates of this rendition.

With all these settings in place, we achieve the desired outcome with all the required renditions.

# Influence the bitrate of the highest rendition

The main advantage of Per-Title is to determine the optimal renditions based on the complexity of the content. When setting the proper boundaries, Per-Title can significantly save bandwidth and storage for low-complex content compared to static renditions or ensure that quality requirements are still fulfilled with very high-complex content.

The default settings for using the contents’ calculated complexity to pick the optimum bitrates usually provide good results. Nevertheless, it is still possible to tweak the rendition ladder to achieve an overall higher or lower quality (or lower or higher bitrates). It is also possible to process different kinds of content with various complexities individually, for example, to reduce the bitrates of videos that are known to have high complexity.

One can influence these factors with the `target_quality_crf` and the `complexity_factor` in the `start_encoding_request`. With the `target_quality_crf`, it is possible to shift the quality of the entire ladder up or down (within the boundaries limited by all the other settings). The default CRF for H.264 is specified as 22; anything below will increase the quality (and the bitrates), and anything above will reduce accordingly.

The `complexity_factor` has basically the same effect. The default here is `1.0`; a higher factor will affect Per-Title to consider the content more complex and assign higher bitrates, while a lower factor (>0) will cause the content to be considered lower complex and assign lower bitrates. Small changes to `complexity_factor` (ie +/- 0.2) is recommended for your initial testing.

This is especially useful to specify the desired quality for an entire library with one target CRF but still be able to treat various kinds of content differently.

# Appendix

Please refer to the [per\_title\_constraints.py](🔗) Python script for a full example!

# Frequently asked questions

**Q.** The default output from the algorithm is too high in quality

A1. Bring **all** assets up or down in quality using _targetCRF_ (increase to reduce quality)

A2. Bring **all** assets up or down in quality using _complexity factor_ (reduce to reduce quality). Note: only change by 0.1 initially. Recommend changing one, not both.

**Q.** My complex assets are too high in quality, but my simple assets are perfect. I want to change the **bias**.

A1. Adjust the gap between _low_ and _high\_complexity\_boundaries_ , think of this like a magnifying glass. The smaller the gap between the numbers, the more variation in quality you see between a complex and simple asset (you are bringing the magnifying glass closer to the page)

**Q.** In my assets, on average the lower **renditions** are too low in quality, the upper renditions are perfect.

A1. Adjust the _minimum_ and _maximum_ bitrate, found in the start request. In this scenario increasing the _minimum_ would likely produce the output you are looking for.