How to encode with a custom transform - .NET

media services logo v3

Looking for Media Services v2 documentation?

When encoding with Azure Media Services, you can get started quickly with one of the recommended built-in presets based on industry best practices as demonstrated in the Streaming files tutorial. You can also build a custom preset to target your specific scenario or device requirements.


When creating custom presets, the following considerations apply:

  • All values for height and width on AVC content must be a multiple of 4.
  • In Azure Media Services v3, all of the encoding bitrates are in bits per second. This is different from the presets with our v2 APIs, which used kilobits/second as the unit. For example, if the bitrate in v2 was specified as 128 (kilobits/second), in v3 it would be set to 128000 (bits/second).


Create a Media Services account

Download the sample

Clone a GitHub repository that contains the full .NET Core sample to your machine using the following command:

git clone

The custom preset sample is located in the Encoding with a custom preset using .NET folder.

Create a transform with a custom preset

When creating a new Transform, you need to specify what you want it to produce as an output. The required parameter is a TransformOutput object, as shown in the code below. Each TransformOutput contains a Preset. The Preset describes the step-by-step instructions of video and/or audio processing operations that are to be used to generate the desired TransformOutput. The following TransformOutput creates custom codec and layer output settings.

When creating a Transform, you should first check if one already exists using the Get method, as shown in the code that follows. In Media Services v3, Get methods on entities return null if the entity doesn't exist (a case-insensitive check on the name).

Example custom transform

The following example defines a set of outputs that we want to be generated when this Transform is used. We first add an AacAudio layer for the audio encoding and two H264Video layers for the video encoding. In the video layers, we assign labels so that they can be used in the output file names. Next, we want the output to also include thumbnails. In the example below we specify images in PNG format, generated at 50% of the resolution of the input video, and at three timestamps - {25%, 50%, 75%} of the length of the input video. Lastly, we specify the format for the output files - one for video + audio, and another for the thumbnails. Since we have multiple H264Layers, we have to use macros that produce unique names per layer. We can either use a {Label} or {Bitrate} macro, the example shows the former.

/// <summary>
/// If the specified transform exists, return that transform. If the it does not
/// exist, creates a new transform with the specified output. In this case, the
/// output is set to encode a video using a custom preset.
/// </summary>
/// <param name="client">The Media Services client.</param>
/// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param>
/// <param name="accountName"> The Media Services account name.</param>
/// <param name="transformName">The transform name.</param>
/// <returns></returns>
private static async Task<Transform> CreateCustomTransform(IAzureMediaServicesClient client, string resourceGroupName, string accountName, string transformName)

    Console.WriteLine("Creating a custom transform...");

    // Create a new Transform Outputs array - this defines the set of outputs for the Transform
    TransformOutput[] outputs = new TransformOutput[]
            // Create a new TransformOutput with a custom Standard Encoder Preset
            // This demonstrates how to create custom codec and layer output settings

          new TransformOutput(
                new StandardEncoderPreset(
                    codecs: new Codec[]
                        // Add an AAC Audio layer for the audio encoding
                        new AacAudio(
                            channels: 2,
                            samplingRate: 48000,
                            bitrate: 128000,
                            profile: AacAudioProfile.AacLc
                        // Next, add a H264Video for the video encoding
                       new H264Video (
                            // Set the GOP interval to 2 seconds for all H264Layers
                             // Add H264Layers. Assign a label that you can use for the output filename
                            layers:  new H264Layer[]
                                new H264Layer (
                                    bitrate: 3600000, // Units are in bits per second and not kbps or Mbps - 3.6 Mbps or 3,600 kbps
                                    width: "1280",
                                    height: "720",
                                    label: "HD-3600kbps" // This label is used to modify the file name in the output formats
                                new H264Layer (
                                    bitrate: 1600000, // Units are in bits per second and not kbps or Mbps - 1.6 Mbps or 1600 kbps
                                    width: "960",
                                    height: "540",
                                    label: "SD-1600kbps" // This label is used to modify the file name in the output formats
                                new H264Layer (
                                    bitrate: 600000, // Units are in bits per second and not kbps or Mbps - 0.6 Mbps or 600 kbps
                                    width: "640",
                                    height: "360",
                                    label: "SD-600kbps" // This label is used to modify the file name in the output formats
                        // Also generate a set of PNG thumbnails
                        new PngImage(
                            start: "25%",
                            step: "25%",
                            range: "80%",
                            layers: new PngLayer[]{
                                new PngLayer(
                                    width: "50%",
                                    height: "50%"
                    // Specify the format for the output files - one for video+audio, and another for the thumbnails
                    formats: new Format[]
                        // Mux the H.264 video and AAC audio into MP4 files, using basename, label, bitrate and extension macros
                        // Note that since you have multiple H264Layers defined above, you have to use a macro that produces unique names per H264Layer
                        // Either {Label} or {Bitrate} should suffice
                        new Mp4Format(
                        new PngFormat(
                onError: OnErrorType.StopProcessingJob,
                relativePriority: Priority.Normal

    string description = "A simple custom encoding transform with 2 MP4 bitrates";

    // Does a Transform already exist with the desired name? This method will just overwrite (Update) the Transform if it exists already. 
    // In production code, you may want to be cautious about that. It really depends on your scenario.
    Transform transform = await client.Transforms.CreateOrUpdateAsync(resourceGroupName, accountName, transformName, outputs, description);

    return transform;

Next steps

Streaming files