User-defined variables and arithmetic video transformations

You can add arithmetic and/or user-defined variables to your transformations. These expressions are evaluated on-the-fly, enabling you to add an additional layer of sophistication and flexibility to your transformations.

User-defined variables are especially valuable when used within named transformations. This enables complete separation of the transformation from the varying values used for delivery. This also makes it significantly easier to reuse common transformations for many assets, even when some specific adjustments must be made to the transformation depending on the specific asset or other data passed from another source.

You can achieve many complex transformation goals by using user-defined variables in conjunction with arithmetic expressions and conditional video transformations.

See also: Variable and arithmetic image transformations.

Arithmetic expressions

You can create arithmetic expressions by using arithmetic operators to assign values to numeric transformation parameters or user-defined variables.

The following example demonstrates using an arithmetic expression to define the final delivery width of the video to be 20% of the video's original width.

Ruby:
Copy to clipboard
cl_video_tag("rafting", :width=>"iw / 5", :crop=>"scale")
PHP:
Copy to clipboard
cl_video_tag("rafting", array("width"=>"iw / 5", "crop"=>"scale"))
Python:
Copy to clipboard
CloudinaryVideo("rafting").video(width="iw / 5", crop="scale")
Node.js:
Copy to clipboard
cloudinary.video("rafting", {width: "iw / 5", crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width("iw / 5").crop("scale")).videoTag("rafting");
JS:
Copy to clipboard
cloudinary.videoTag('rafting', {width: "iw / 5", crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("rafting", {width: "iw / 5", crop: "scale"})
React:
Copy to clipboard
<Video publicId="rafting" >
  <Transformation width="iw / 5" crop="scale" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="rafting" >
  <cld-transformation width="iw / 5" crop="scale" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="rafting" >
  <cl-transformation width="iw / 5" crop="scale">
  </cl-transformation>
</cl-video>
.Net:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation().Width("iw / 5").Crop("scale")).BuildVideoTag("rafting")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width("iw / 5").crop("scale")).resourceType("video").generate("rafting.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setWidth("iw / 5").setCrop("scale")).generate("rafting.mp4")

Note
When you use multiple arithmetic operators in an expression, standard order of operations apply (multiplication and division before addition and subtraction).

For example, iw_mul_2_add_ih_mul_2 would give you the perimeter measurement of the initial asset by first multiplying both the initial width by 2 and the initial height by 2, and then adding these two products.

Supported arithmetic operators

operation URL syntax SDK syntax
add add +
subtract sub -
multiply mul *
divide div /
modulo (remainder) mod %
pow
(to the power of)
pow ^

User-defined variables - overview

To use user-defined variables in your transformations, you first declare and assign values to the variables you want to use. In later components of your chained transformation, you can use the variables as the values of your transformation parameters.

Note
Not all transformation parameters are supported for use with variables. For details, see Variable types and supported parameters.

Variable naming

User-defined variables start with the $ sign, for example $newwidth. The name can include only alphanumeric characters and must begin with a letter.

Variable value types

Variables can be assigned a number value, string value, or they can take on the value of a numeric asset characteristic, such as iw (initial width), fc (face count - images only), or du (duration - video only).

When working with string values:

  • String values are bounded by ! !.
  • To assign the value of an existing context key to a variable, use the syntax: ctx:!key_name!. When you set a transformation parameter to that variable, it gets the value of the specified context key.
  • To assign the value of a structured metadata ID to a variable, use the syntax: md:!external_id!. Be sure to use the external ID, not the label. When you set a transformation parameter to that variable, it gets the value of the specified metadata.
  • You can provide several values in a string using a colon : as the delimiter. For example: !string1:string2:string3!. These multiple-value strings can be used:

    • as folder separators when the variable will be used to control the public ID of an overlay.
    • for comparing multiple values when the variable will be used in conjunction with the _in_ or _nin_ conditional transformation comparison operators.
    • to specify RGB Hex values for the border, background or color parameters. For example: !rgb:008000!.


    When a variable that is defined as a string value and contains a colon, is passed to any other parameter (for example if the variable is used to set a text overlay string), the colon is treated as a literal character.

Assigning values to variables

Use the underscore to assign a value to a variable. For example: $newwidth_200, $newheight_iw, $label_!sale!, $stringset_!string1:string2!

To convert a string value to a numeric value, append _to_i for an integer, or _to_f for a float. For example, to assign the value of context key, breadth, to the variable $newwidth:

  • as an integer, use the syntax: $newwidth_ctx:!breadth!_to_i
  • as a float, use the syntax: $newwidth_ctx:!breadth!_to_f

If assigning structured metadata to a variable, and the metadata type is numeric, you do not need to specify _to_i. For example, if you have a number field with external ID, position, you can use the syntax: $newwidth_md:!position!. However, if it is a text field you still need to append _to_i or _to_f to convert it to an integer or float.

Using arithmetic expressions with variables

You can use arithmetic operators with numeric variables just as you do with numeric transformation parameters, or even in combination. Consider this example:

$small_150,$big_2_mul_$small/c_fill,w_$big,h_$small_add_20

  • The $small variable is set to 150
  • The $big variable is assigned the value of 2 times the $small variable
  • The width parameter is set to use the value of $big
  • The height parameter is set to use the value of $small plus 20

Variable types and supported parameters

You can use user-defined variables with videos to compare how the current value of a parameter relates to the assigned value of a user-defined variable, or you can transform your video by setting the value of a parameter with a variable.

Using variables to transform a video

Important
Currently, setting the value of a parameter is supported only for the width and height parameters.

The following example defines 2 variables: $mainvideowidth and $overlaywidth. The $overlaywidth is defined as 1/3 of the $mainvideowidth.

Ruby:
Copy to clipboard
cl_video_tag("dog", :variables=>[["$mainvideowidth", "500"], ["$overlaywidth", "$mainvideowidth / 3"]], :transformation=>[
  {:width=>"$mainvideowidth", :crop=>"scale"},
  {:overlay=>"video:kitten_fighting", :width=>"$overlaywidth", :gravity=>"south_east"}
  ])
PHP:
Copy to clipboard
cl_video_tag("dog", array("variables"=>array("$mainvideowidth"=>"500", "$overlaywidth"=>"$mainvideowidth / 3"), "transformation"=>array(
  array("width"=>"$mainvideowidth", "crop"=>"scale"),
  array("overlay"=>"video:kitten_fighting", "width"=>"$overlaywidth", "gravity"=>"south_east")
  )))
Python:
Copy to clipboard
CloudinaryVideo("dog").video(variables={"$mainvideowidth": "500", "$overlaywidth": "$mainvideowidth / 3"}, transformation=[
  {'width': "$mainvideowidth", 'crop': "scale"},
  {'overlay': "video:kitten_fighting", 'width': "$overlaywidth", 'gravity': "south_east"}
  ])
Node.js:
Copy to clipboard
cloudinary.video("dog", {variables: [["$mainvideowidth", "500"], ["$overlaywidth", "$mainvideowidth / 3"]], transformation: [
  {width: "$mainvideowidth", crop: "scale"},
  {overlay: "video:kitten_fighting", width: "$overlaywidth", gravity: "south_east"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
.variables(variable("$mainvideowidth","500"),variable("$overlaywidth","$mainvideowidth / 3")).chain()
  .width("$mainvideowidth").crop("scale").chain()
  .overlay(new Layer().publicId("video:kitten_fighting")).width("$overlaywidth").gravity("south_east")).videoTag("dog");
JS:
Copy to clipboard
cloudinary.videoTag('dog', {variables: [["$mainvideowidth", "500"], ["$overlaywidth", "$mainvideowidth / 3"]], transformation: [
  {width: "$mainvideowidth", crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("video:kitten_fighting"), width: "$overlaywidth", gravity: "south_east"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("dog", {variables: [["$mainvideowidth", "500"], ["$overlaywidth", "$mainvideowidth / 3"]], transformation: [
  {width: "$mainvideowidth", crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("video:kitten_fighting"), width: "$overlaywidth", gravity: "south_east"}
  ]})
React:
Copy to clipboard
<Video publicId="dog" variables={[["$mainvideowidth", "500"], ["$overlaywidth", "$mainvideowidth / 3"]]}>
  <Transformation width="$mainvideowidth" crop="scale" />
  <Transformation overlay="video:kitten_fighting" width="$overlaywidth" gravity="south_east" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="dog" :variables="[['$mainvideowidth', '500'], ['$overlaywidth', '$mainvideowidth / 3']]">
  <cld-transformation width="$mainvideowidth" crop="scale" />
  <cld-transformation overlay="video:kitten_fighting" width="$overlaywidth" gravity="south_east" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="dog" variables="[['$mainvideowidth', '500'], ['$overlaywidth', '$mainvideowidth / 3']]">
  <cl-transformation width="$mainvideowidth" crop="scale">
  </cl-transformation>
  <cl-transformation overlay="video:kitten_fighting" width="$overlaywidth" gravity="south_east">
  </cl-transformation>
</cl-video>
.Net:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Width("$mainvideowidth").Crop("scale").Chain()
  .Overlay(new Layer().PublicId("video:kitten_fighting")).Width("$overlaywidth").Gravity("south_east")).BuildVideoTag("dog")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
.variables(variable("$mainvideowidth","500"),variable("$overlaywidth","$mainvideowidth / 3")).chain()
  .width("$mainvideowidth").crop("scale").chain()
  .overlay(new Layer().publicId("video:kitten_fighting")).width("$overlaywidth").gravity("south_east")).resourceType("video").generate("dog.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .setWidth("$mainvideowidth").setCrop("scale").chain()
  .setOverlay("video:kitten_fighting").setWidth("$overlaywidth").setGravity("south_east")).generate("dog.mp4")

Note
You cannot use variables declared on a video for use within an image overlay on a video.

Using variables in video conditions

You can check the value of a video characteristic against a user-defined variable value within the IF part of conditional transformation.

For this purpose, you can use any parameter that is supported within conditional transformations.

In the example below, the conditional transformation checks whether the video has a certain tag. If it does, the video is delivered at a high quality level of 90. Otherwise, it's delivered at a low quality level of 30. The value of the tag that controls this behavior is declared using the $qualtag variable. In this case, only videos that are tagged as 'Pro' will be delivered with high quality.

Ruby:
Copy to clipboard
cl_video_tag("docs/kitten_fighting2", :variables=>[["$qualtag", "!Pro!"]], :transformation=>[
  {:if=>"$qualtag_in_tags", :quality=>80},
  {:if=>"else", :quality=>30},
  {:width=>500, :crop=>"scale"}
  ])
PHP:
Copy to clipboard
cl_video_tag("docs/kitten_fighting2", array("variables"=>array("$qualtag"=>"!Pro!"), "transformation"=>array(
  array("if"=>"$qualtag_in_tags", "quality"=>80),
  array("if"=>"else", "quality"=>30),
  array("width"=>500, "crop"=>"scale")
  )))
Python:
Copy to clipboard
CloudinaryVideo("docs/kitten_fighting2").video(variables={"$qualtag": "!Pro!"}, transformation=[
  {'if': "$qualtag_in_tags", 'quality': 80},
  {'if': "else", 'quality': 30},
  {'width': 500, 'crop': "scale"}
  ])
Node.js:
Copy to clipboard
cloudinary.video("docs/kitten_fighting2", {variables: [["$qualtag", "!Pro!"]], transformation: [
  {if: "$qualtag_in_tags", quality: 80},
  {if: "else", quality: 30},
  {width: 500, crop: "scale"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
.variables(variable("$qualtag","!Pro!")).chain()
  .if("$qualtag_in_tags").quality(80).chain()
  .if("else").quality(30).chain()
  .width(500).crop("scale")).videoTag("docs/kitten_fighting2");
JS:
Copy to clipboard
cloudinary.videoTag('docs/kitten_fighting2', {variables: [["$qualtag", "!Pro!"]], transformation: [
  {if: "$qualtag_in_tags", quality: 80},
  {if: "else", quality: 30},
  {width: 500, crop: "scale"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("docs/kitten_fighting2", {variables: [["$qualtag", "!Pro!"]], transformation: [
  {if: "$qualtag_in_tags", quality: 80},
  {if: "else", quality: 30},
  {width: 500, crop: "scale"}
  ]})
React:
Copy to clipboard
<Video publicId="docs/kitten_fighting2" variables={[["$qualtag", "!Pro!"]]}>
  <Transformation if="$qualtag_in_tags" quality="80" />
  <Transformation if="else" quality="30" />
  <Transformation width="500" crop="scale" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="docs/kitten_fighting2" :variables="[['$qualtag', '!Pro!']]">
  <cld-transformation if="$qualtag_in_tags" quality="80" />
  <cld-transformation if="else" quality="30" />
  <cld-transformation width="500" crop="scale" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="docs/kitten_fighting2" variables="[['$qualtag', '!Pro!']]">
  <cl-transformation if="$qualtag_in_tags" quality="80">
  </cl-transformation>
  <cl-transformation if="else" quality="30">
  </cl-transformation>
  <cl-transformation width="500" crop="scale">
  </cl-transformation>
</cl-video>
.Net:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .If("$qualtag_in_tags").Quality(80).Chain()
  .If("else").Quality(30).Chain()
  .Width(500).Crop("scale")).BuildVideoTag("docs/kitten_fighting2")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
.variables(variable("$qualtag","!Pro!")).chain()
  .if("$qualtag_in_tags").quality(80).chain()
  .if("else").quality(30).chain()
  .width(500).crop("scale")).resourceType("video").generate("docs/kitten_fighting2.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .setIf("$qualtag_in_tags").setQuality(80).chain()
  .setIf("else").setQuality(30).chain()
  .setWidth(500).setCrop("scale")).generate("docs/kitten_fighting2.mp4")

The above transformation is running on kitten_fighting2, which has a tag value of 'Pro', and thus it's delivered with a quality value of 90. If you use the same transformation as above with the kitten_fighting video, which is identical, except without the 'Pro' tag, it's delivered with a low quality value of 30.

Using variables with named transformations

By using variables to set the determining values of a condition, you could then define the conditional transformation as a named transformation that could be used with many video assets, and assign the variable value externally.

For example, you could set the named transformation highqual-if-tagged to a transformation similar to the one we used above for the kitten video: if_$qualtag_in_tags,q_80/if_else,q_50/w_$delwidth, and then use it to deliver any video, controlling both the quality and final delivery width by setting the relevant variable values. In this case, we chose to apply the quality condition when the tag = 'important'. Regardless of the tag, the deliver width will be 450px.

Ruby:
Copy to clipboard
cl_video_tag("rafting", :transformation=>["highqual-if-tagged"], :variables=>[["$qualtag", "!important!"], ["$delwidth", "450"]])
PHP:
Copy to clipboard
cl_video_tag("rafting", array("transformation"=>array("highqual-if-tagged"), "variables"=>array("$qualtag"=>"!important!", "$delwidth"=>"450")))
Python:
Copy to clipboard
CloudinaryVideo("rafting").video(transformation=["highqual-if-tagged"], variables={"$qualtag": "!important!", "$delwidth": "450"})
Node.js:
Copy to clipboard
cloudinary.video("rafting", {transformation: ["highqual-if-tagged"], variables: [["$qualtag", "!important!"], ["$delwidth", "450"]]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
.variables(variable("$qualtag","!important!"),variable("$delwidth","450")).chain().named("highqual-if-tagged")).videoTag("rafting");
JS:
Copy to clipboard
cloudinary.videoTag('rafting', {transformation: ["highqual-if-tagged"], variables: [["$qualtag", "!important!"], ["$delwidth", "450"]]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("rafting", {transformation: ["highqual-if-tagged"], variables: [["$qualtag", "!important!"], ["$delwidth", "450"]]})
React:
Copy to clipboard
<Video publicId="rafting" variables={[["$qualtag", "!important!"], ["$delwidth", "450"]]}>
  <Transformation transformation={["highqual-if-tagged"]} />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="rafting" :variables="[['$qualtag', '!important!'], ['$delwidth', '450']]">
  <cld-transformation transformation={["highqual-if-tagged"]} />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="rafting" variables="[['$qualtag', '!important!'], ['$delwidth', '450']]">
  <cl-transformation transformation={{["highqual-if-tagged"]}}>
  </cl-transformation>
</cl-video>
.Net:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation().Named("highqual-if-tagged")).BuildVideoTag("rafting")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
.variables(variable("$qualtag","!important!"),variable("$delwidth","450")).chain().named("highqual-if-tagged")).resourceType("video").generate("rafting.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setNamed("highqual-if-tagged")).generate("rafting.mp4")

Note
When you use variable or conditional expressions that include the tags, ctx or md parameters, their values are exposed publicly in the URL. If you want to prevent such values from being exposed, you can disable the Usage of tags/context/metadata in transformation URLs option in the Security tab of your account settings (enabled by default). When this setting is disabled, any URL that exposes tags, context or metadata values will return an error.

✔️ Feedback sent!