> ## Documentation Index
> This page is part of the Image and Video APIs product. Fetch the complete documentation index for Image and Video APIs at: https://cloudinary.com/documentation/llms-image-and-video-apis.txt?referrer=docpage and then use it to discover all relevant pages before exploring further.
> If your task extends beyond this product, fetch the top-level index covering all Cloudinary products and topics at: https://cloudinary.com/documentation/llms.txt?referrer=docpage

# User-defined variables and arithmetic video transformations


[conditional-transformations-link]:video_conditional_expressions
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.

* **[Arithmetic expressions](#arithmetic_expressions)** enable you to assign values to a parameter or variable based on an arithmetic equation. 
* **[User-defined variables](#user_defined_variables_overview)** enable you to keep value assignment separate from the transformation definition.

User-defined variables are especially valuable when used within [named transformations](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 transformations][conditional-transformations-link].
**See also**: [Variable and arithmetic image transformations](user_defined_variables).

## Arithmetic expressions

You can create arithmetic expressions by using arithmetic operators with numeric transformation parameters or [user-defined variables](#user_defined_variables_overview). 

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. 

![Scale a video clip to 20% of original width](https://res.cloudinary.com/demo/video/upload/c_scale,w_iw_div_5/rafting.mp4)

```nodejs
cloudinary.video("rafting", {width: "iw / 5", crop: "scale"})
```

```react
import { scale } from "@cloudinary/url-gen/actions/resize";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";

new CloudinaryVideo("rafting.mp4").resize(
  scale().width(expression("initial_width / 5"))
);
```

```vue
import { scale } from "@cloudinary/url-gen/actions/resize";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";

new CloudinaryVideo("rafting.mp4").resize(
  scale().width(expression("initial_width / 5"))
);
```

```angular
import { scale } from "@cloudinary/url-gen/actions/resize";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";

new CloudinaryVideo("rafting.mp4").resize(
  scale().width(expression("initial_width / 5"))
);
```

```js
import { scale } from "@cloudinary/url-gen/actions/resize";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";

new CloudinaryVideo("rafting.mp4").resize(
  scale().width(expression("initial_width / 5"))
);
```

```python
CloudinaryVideo("rafting").video(width="iw / 5", crop="scale")
```

```php
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Expression;

(new VideoTag('rafting.mp4'))
	->resize(Resize::scale()
	->width(
	Expression::expression("initial_width / 5"))
	);
```

```java
cloudinary.url().transformation(new Transformation().width("iw / 5").crop("scale")).videoTag("rafting");
```

```ruby
cl_video_tag("rafting", width: "iw / 5", crop: "scale")
```

```csharp
cloudinary.Api.UrlVideoUp.Transform(new Transformation().Width("iw / 5").Crop("scale")).BuildVideoTag("rafting")
```

```dart
cloudinary.video('rafting.mp4').transformation(Transformation()
	.resize(Resize.scale()
	.width(
	Expression.expression("initial_width / 5"))
	));
```

```swift
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setWidth("iw / 5").setCrop("scale")).generate("rafting.mp4")
```

```android
MediaManager.get().url().transformation(new Transformation().width("iw / 5").crop("scale")).resourceType("video").generate("rafting.mp4");
```

```flutter
cloudinary.video('rafting.mp4').transformation(Transformation()
	.resize(Resize.scale()
	.width(
	Expression.expression("initial_width / 5"))
	));
```

```kotlin
cloudinary.video {
	publicId("rafting.mp4")
	 resize(Resize.scale() {
	 width(
	Expression.expression("initial_width / 5"))
	 }) 
}.generate()
```

```jquery
$.cloudinary.video("rafting", {width: "iw / 5", crop: "scale"})
```

```react_native
import { scale } from "@cloudinary/url-gen/actions/resize";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";

new CloudinaryVideo("rafting.mp4").resize(
  scale().width(expression("initial_width / 5"))
);
```

```nodejs
cloudinary.video("rafting", {width: "iw / 5", crop: "scale"})
```

```react
import { scale } from "@cloudinary/url-gen/actions/resize";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";

new CloudinaryVideo("rafting.mp4").resize(
  scale().width(expression("initial_width / 5"))
);
```

```vue
import { scale } from "@cloudinary/url-gen/actions/resize";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";

new CloudinaryVideo("rafting.mp4").resize(
  scale().width(expression("initial_width / 5"))
);
```

```angular
import { scale } from "@cloudinary/url-gen/actions/resize";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";

new CloudinaryVideo("rafting.mp4").resize(
  scale().width(expression("initial_width / 5"))
);
```

```js
import { scale } from "@cloudinary/url-gen/actions/resize";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";

new CloudinaryVideo("rafting.mp4").resize(
  scale().width(expression("initial_width / 5"))
);
```

```python
CloudinaryVideo("rafting").video(width="iw / 5", crop="scale")
```

```php
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Expression;

(new VideoTag('rafting.mp4'))
	->resize(Resize::scale()
	->width(
	Expression::expression("initial_width / 5"))
	);
```

```java
cloudinary.url().transformation(new Transformation().width("iw / 5").crop("scale")).videoTag("rafting");
```

```ruby
cl_video_tag("rafting", width: "iw / 5", crop: "scale")
```

```csharp
cloudinary.Api.UrlVideoUp.Transform(new Transformation().Width("iw / 5").Crop("scale")).BuildVideoTag("rafting")
```

```dart
cloudinary.video('rafting.mp4').transformation(Transformation()
	.resize(Resize.scale()
	.width(
	Expression.expression("initial_width / 5"))
	));
```

```swift
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setWidth("iw / 5").setCrop("scale")).generate("rafting.mp4")
```

```android
MediaManager.get().url().transformation(new Transformation().width("iw / 5").crop("scale")).resourceType("video").generate("rafting.mp4");
```

```flutter
cloudinary.video('rafting.mp4').transformation(Transformation()
	.resize(Resize.scale()
	.width(
	Expression.expression("initial_width / 5"))
	));
```

```kotlin
cloudinary.video {
	publicId("rafting.mp4")
	 resize(Resize.scale() {
	 width(
	Expression.expression("initial_width / 5"))
	 }) 
}.generate()
```

```jquery
$.cloudinary.video("rafting", {width: "iw / 5", crop: "scale"})
```

```react_native
import { scale } from "@cloudinary/url-gen/actions/resize";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";

new CloudinaryVideo("rafting.mp4").resize(
  scale().width(expression("initial_width / 5"))
);
```

> **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_types_and_supported_parameters).

### Variable naming

User-defined variables start with the `
[conditional-transformations-link]:video_conditional_expressions
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.

* **[Arithmetic expressions](#arithmetic_expressions)** enable you to assign values to a parameter or variable based on an arithmetic equation. 
* **[User-defined variables](#user_defined_variables_overview)** enable you to keep value assignment separate from the transformation definition.

User-defined variables are especially valuable when used within [named transformations](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 transformations][conditional-transformations-link].
**See also**: [Variable and arithmetic image transformations](user_defined_variables).

## Arithmetic expressions

You can create arithmetic expressions by using arithmetic operators with numeric transformation parameters or [user-defined variables](#user_defined_variables_overview). 

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. 

![Scale a video clip to 20% of original width](https://res.cloudinary.com/demo/video/upload/c_scale,w_iw_div_5/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 <br/>(to the power of) | _pow_ | ^

## User-defined variables - overview
 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) or 
 `du` (duration). 
When working with string values:
	
* String values are bounded by `! !`. 
* To assign the value of an existing **contextual metadata** 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 contextual metadata key.	
* To assign the value of a **structured metadata** ID to a variable, use the syntax: `md:!!`, for example `md:!structid!`.  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 separators for public IDs with slashes 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](video_conditional_expressions#supported_operators). 

   * to specify RGB Hex values for the `border`, `background` or `color` parameters. For example: `!rgb:008000!`.

       <br/>When a variable that is defined as a string value and contains a colon, is passed to any other parameter, 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 the **contextual metadata** 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](#arithmetic_expressions) with numeric variables just as you do with numeric transformation parameters, or even in combination. Consider this example:<br/>

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

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

### Testing whether a variable has been defined

You can test whether or not a variable has been defined using the parameters `if_isdef_$` and `if_isndef_$`. 

For example, check if the `$big` variable has been defined, and if so, set the width:

`if_isdef_$big/c_scale,w_$big/if_end`

Similarly, if the `$small` variable is not defined, set it to a default value:

`if_isndef_$small/$small_300/if_end`

Learn more about [conditional transformations][conditional-transformations-link].

##  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.

> **INFO**: There are currently limitations on which parameters you can set a value for using a variable. The following sections describe all those that Cloudinary supports.

<a name="using_variables_to_transform_a_video" class="anchor">
### Using variables to resize a video

You can use variables for both the `width` and `height` parameters.

The following example defines two variables: `$mainvideowidth` and `$overlaywidth`.  The `$overlaywidth` is `$mainvideowidth` divided by 3. 

![Set video and video overlay widths using variable values](https://res.cloudinary.com/demo/video/upload/$mainvideowidth_500/$overlaywidth_$mainvideowidth_div_3/c_scale,w_$mainvideowidth/l_video:hotel_lounge/c_scale,w_$overlaywidth/fl_layer_apply,g_north_east,x_5,y_5/f_auto/q_auto/hotel_buffet.mp4)

```nodejs
cloudinary.video("hotel_buffet", {transformation: [
  {variables: [["$mainvideowidth", "500"]]},
  {variables: [["$overlaywidth", "$mainvideowidth / 3"]]},
  {width: "$mainvideowidth", crop: "scale"},
  {overlay: "video:hotel_lounge"},
  {width: "$overlaywidth", crop: "scale"},
  {gravity: "north_east", x: 5, y: 5, flags: "layer_apply"},
  {quality: "auto"}
  ]})
```

```react
import { set } from "@cloudinary/url-gen/actions/variable";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { format, quality } from "@cloudinary/url-gen/actions/delivery";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";
import { video } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { auto as autoFormat } from "@cloudinary/url-gen/qualifiers/format";
import { auto as autoQuality } from "@cloudinary/url-gen/qualifiers/quality";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryVideo("hotel_buffet.mp4")
  .addVariable(set("mainvideowidth", 500))
  .addVariable(set("overlaywidth", expression("$mainvideowidth / 3")))
  .resize(scale().width("$mainvideowidth"))
  .overlay(
    source(
      video("hotel_lounge").transformation(
        new Transformation().resize(scale().width("$overlaywidth"))
      )
    ).position(
      new Position()
        .gravity(compass("north_east"))
        .offsetX(5)
        .offsetY(5)
    )
  )
  .delivery(format(autoFormat()))
  .delivery(quality(autoQuality()));
```

```vue
import { set } from "@cloudinary/url-gen/actions/variable";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { format, quality } from "@cloudinary/url-gen/actions/delivery";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";
import { video } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { auto as autoFormat } from "@cloudinary/url-gen/qualifiers/format";
import { auto as autoQuality } from "@cloudinary/url-gen/qualifiers/quality";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryVideo("hotel_buffet.mp4")
  .addVariable(set("mainvideowidth", 500))
  .addVariable(set("overlaywidth", expression("$mainvideowidth / 3")))
  .resize(scale().width("$mainvideowidth"))
  .overlay(
    source(
      video("hotel_lounge").transformation(
        new Transformation().resize(scale().width("$overlaywidth"))
      )
    ).position(
      new Position()
        .gravity(compass("north_east"))
        .offsetX(5)
        .offsetY(5)
    )
  )
  .delivery(format(autoFormat()))
  .delivery(quality(autoQuality()));
```

```angular
import { set } from "@cloudinary/url-gen/actions/variable";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { format, quality } from "@cloudinary/url-gen/actions/delivery";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";
import { video } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { auto as autoFormat } from "@cloudinary/url-gen/qualifiers/format";
import { auto as autoQuality } from "@cloudinary/url-gen/qualifiers/quality";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryVideo("hotel_buffet.mp4")
  .addVariable(set("mainvideowidth", 500))
  .addVariable(set("overlaywidth", expression("$mainvideowidth / 3")))
  .resize(scale().width("$mainvideowidth"))
  .overlay(
    source(
      video("hotel_lounge").transformation(
        new Transformation().resize(scale().width("$overlaywidth"))
      )
    ).position(
      new Position()
        .gravity(compass("north_east"))
        .offsetX(5)
        .offsetY(5)
    )
  )
  .delivery(format(autoFormat()))
  .delivery(quality(autoQuality()));
```

```js
import { set } from "@cloudinary/url-gen/actions/variable";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { format, quality } from "@cloudinary/url-gen/actions/delivery";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";
import { video } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { auto as autoFormat } from "@cloudinary/url-gen/qualifiers/format";
import { auto as autoQuality } from "@cloudinary/url-gen/qualifiers/quality";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryVideo("hotel_buffet.mp4")
  .addVariable(set("mainvideowidth", 500))
  .addVariable(set("overlaywidth", expression("$mainvideowidth / 3")))
  .resize(scale().width("$mainvideowidth"))
  .overlay(
    source(
      video("hotel_lounge").transformation(
        new Transformation().resize(scale().width("$overlaywidth"))
      )
    ).position(
      new Position()
        .gravity(compass("north_east"))
        .offsetX(5)
        .offsetY(5)
    )
  )
  .delivery(format(autoFormat()))
  .delivery(quality(autoQuality()));
```

```python
CloudinaryVideo("hotel_buffet").video(transformation=[
  {'variables': [["$mainvideowidth", "500"]]},
  {'variables': [["$overlaywidth", "$mainvideowidth / 3"]]},
  {'width': "$mainvideowidth", 'crop': "scale"},
  {'overlay': "video:hotel_lounge"},
  {'width': "$overlaywidth", 'crop': "scale"},
  {'gravity': "north_east", 'x': 5, 'y': 5, 'flags': "layer_apply"},
  {'quality': "auto"}
  ])
```

```php
use Cloudinary\Transformation\Variable;
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Overlay;
use Cloudinary\Transformation\Delivery;
use Cloudinary\Transformation\Expression;
use Cloudinary\Transformation\Source;
use Cloudinary\Transformation\Position;
use Cloudinary\Transformation\Format;
use Cloudinary\Transformation\Quality;
use Cloudinary\Transformation\Gravity;
use Cloudinary\Transformation\Compass;

(new VideoTag('hotel_buffet.mp4'))
	->addVariable(Variable::set("mainvideowidth",500))
	->addVariable(Variable::set("overlaywidth",
	Expression::expression("$mainvideowidth / 3")))
	->resize(Resize::scale()->width("$mainvideowidth"))
	->overlay(Overlay::source(
	Source::video("hotel_lounge")
	->transformation((new Transformation())
	->resize(Resize::scale()->width("$overlaywidth")))
	)
	->position((new Position())
	->gravity(
	Gravity::compass(
	Compass::northEast()))
->offsetX(5)
->offsetY(5))
	)
	->delivery(Delivery::format(
	Format::auto()))
	->delivery(Delivery::quality(
	Quality::auto()));
```

```java
cloudinary.url().transformation(new Transformation()
  .variables(variable("$mainvideowidth","500")).chain()
  .variables(variable("$mainvideowidth","500")).variables(variable("$overlaywidth","$mainvideowidth / 3")).chain()
  .width("$mainvideowidth").crop("scale").chain()
  .overlay(new Layer().publicId("video:hotel_lounge")).chain()
  .width("$overlaywidth").crop("scale").chain()
  .gravity("north_east").x(5).y(5).flags("layer_apply").chain()
  .quality("auto")).videoTag("hotel_buffet");
```

```ruby
cl_video_tag("hotel_buffet", transformation: [
  {variables: [["$mainvideowidth", "500"]]},
  {variables: [["$overlaywidth", "$mainvideowidth / 3"]]},
  {width: "$mainvideowidth", crop: "scale"},
  {overlay: "video:hotel_lounge"},
  {width: "$overlaywidth", crop: "scale"},
  {gravity: "north_east", x: 5, y: 5, flags: "layer_apply"},
  {quality: "auto"}
  ])
```

```csharp
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Variables("$mainvideowidth", 500).Chain()
  .Variables("$overlaywidth", $mainvideowidth / 3).Chain()
  .Width("$mainvideowidth").Crop("scale").Chain()
  .Overlay(new Layer().PublicId("video:hotel_lounge")).Chain()
  .Width("$overlaywidth").Crop("scale").Chain()
  .Gravity("north_east").X(5).Y(5).Flags("layer_apply").Chain()
  .Quality("auto")).BuildVideoTag("hotel_buffet")
```

```dart
cloudinary.video('hotel_buffet.mp4').transformation(Transformation()
	.addTransformation("$mainvideowidth_500/$overlaywidth_$mainvideowidth_div_3/c_scale,w_$mainvideowidth/l_video:hotel_lounge/c_scale,w_$overlaywidth/fl_layer_apply,g_north_east,x_5,y_5/f_auto/q_auto"));
```

```swift
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .chain()
  .chain()
  .setWidth("$mainvideowidth").setCrop("scale").chain()
  .setOverlay("video:hotel_lounge").chain()
  .setWidth("$overlaywidth").setCrop("scale").chain()
  .setGravity("north_east").setX(5).setY(5).setFlags("layer_apply").chain()
  .setQuality("auto")).generate("hotel_buffet.mp4")
```

```android
MediaManager.get().url().transformation(new Transformation()
  .variables(variable("$mainvideowidth","500")).chain()
  .variables(variable("$mainvideowidth","500")).variables(variable("$overlaywidth","$mainvideowidth / 3")).chain()
  .width("$mainvideowidth").crop("scale").chain()
  .overlay(new Layer().publicId("video:hotel_lounge")).chain()
  .width("$overlaywidth").crop("scale").chain()
  .gravity("north_east").x(5).y(5).flags("layer_apply").chain()
  .quality("auto")).resourceType("video").generate("hotel_buffet.mp4");
```

```flutter
cloudinary.video('hotel_buffet.mp4').transformation(Transformation()
	.addTransformation("$mainvideowidth_500/$overlaywidth_$mainvideowidth_div_3/c_scale,w_$mainvideowidth/l_video:hotel_lounge/c_scale,w_$overlaywidth/fl_layer_apply,g_north_east,x_5,y_5/f_auto/q_auto"));
```

```kotlin
cloudinary.video {
	publicId("hotel_buffet.mp4")
	 addTransformation("\$mainvideowidth_500/\$overlaywidth_\$mainvideowidth_div_3/c_scale,w_\$mainvideowidth/l_video:hotel_lounge/c_scale,w_\$overlaywidth/fl_layer_apply,g_north_east,x_5,y_5/f_auto/q_auto") 
}.generate()
```

```jquery
$.cloudinary.video("hotel_buffet", {transformation: [
  {variables: [["$mainvideowidth", "500"]]},
  {variables: [["$overlaywidth", "$mainvideowidth / 3"]]},
  {width: "$mainvideowidth", crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("video:hotel_lounge")},
  {width: "$overlaywidth", crop: "scale"},
  {gravity: "north_east", x: 5, y: 5, flags: "layer_apply"},
  {quality: "auto"}
  ]})
```

```react_native
import { set } from "@cloudinary/url-gen/actions/variable";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { format, quality } from "@cloudinary/url-gen/actions/delivery";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";
import { video } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { auto as autoFormat } from "@cloudinary/url-gen/qualifiers/format";
import { auto as autoQuality } from "@cloudinary/url-gen/qualifiers/quality";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryVideo("hotel_buffet.mp4")
  .addVariable(set("mainvideowidth", 500))
  .addVariable(set("overlaywidth", expression("$mainvideowidth / 3")))
  .resize(scale().width("$mainvideowidth"))
  .overlay(
    source(
      video("hotel_lounge").transformation(
        new Transformation().resize(scale().width("$overlaywidth"))
      )
    ).position(
      new Position()
        .gravity(compass("north_east"))
        .offsetX(5)
        .offsetY(5)
    )
  )
  .delivery(format(autoFormat()))
  .delivery(quality(autoQuality()));
```

> **NOTE**:
>
> You can't use variables declared on a video for use within an **image overlay** on a video.

### Using variables in text overlays

You can use a variable for all or part of the text value in a [text overlay](video_layers#text_overlays). 

To mix static text with a string variable when specifying a text overlay, use the syntax: `static text $(variable) more static text`. For example:

* `$name_!Max!/l_text:arial_10:My name is $(name) the Magnificent/fl_layer_apply` 

You can also use a variable for the text color.  For example:

* `$color_!rgb:ff33cc!/co_$color,l_text:arial_10:hello/fl_layer_apply`

In this example, set the variable `$award` to the string value `!First!`. Then set the text overlay to use the text `$(award) Place`. The color of the text is also set using a variable (`$color`). The text overlay is placed near the bottom of the image on a semi-transparent, rounded border.

![text overlay with string variable](https://res.cloudinary.com/demo/video/upload/$award_!First!/$color_!rgb:FFFFFF!/b_gray,co_$color,l_text:Arial_150:%20%20$(award)

```nodejs
cloudinary.image("b_gray,co_$color,l_text:Arial_150:  $(award", {resource_type: "video", transformation: [
  {variables: [["$award", "!First!"]]},
  {variables: [["$color", "!rgb:FFFFFF!"]]}
  ]})
```

```react
import { set } from "@cloudinary/url-gen/actions/variable";

new CloudinaryImage("b_gray,co_$color,l_text:Arial_150:  $(award")
  .addVariable(set("award", "First"))
  .addVariable(set("color", "rgb:FFFFFF"))
  .setAssetType("video");
```

```vue
import { set } from "@cloudinary/url-gen/actions/variable";

new CloudinaryImage("b_gray,co_$color,l_text:Arial_150:  $(award")
  .addVariable(set("award", "First"))
  .addVariable(set("color", "rgb:FFFFFF"))
  .setAssetType("video");
```

```angular
import { set } from "@cloudinary/url-gen/actions/variable";

new CloudinaryImage("b_gray,co_$color,l_text:Arial_150:  $(award")
  .addVariable(set("award", "First"))
  .addVariable(set("color", "rgb:FFFFFF"))
  .setAssetType("video");
```

```js
import { set } from "@cloudinary/url-gen/actions/variable";

new CloudinaryImage("b_gray,co_$color,l_text:Arial_150:  $(award")
  .addVariable(set("award", "First"))
  .addVariable(set("color", "rgb:FFFFFF"))
  .setAssetType("video");
```

```python
CloudinaryVideo("b_gray,co_$color,l_text:Arial_150:  $(award").image(transformation=[
  {'variables': [["$award", "!First!"]]},
  {'variables': [["$color", "!rgb:FFFFFF!"]]}
  ])
```

```php
use Cloudinary\Transformation\Variable;

(new ImageTag('b_gray,co_$color,l_text:Arial_150:  $(award'))
	->addVariable(Variable::set("award","First"))
	->addVariable(Variable::set("color","rgb:FFFFFF"))
	->assetType("video");
```

```java
cloudinary.url().transformation(new Transformation()
  .variables(variable("$award","!First!")).chain()
  .variables(variable("$award","!First!")).variables(variable("$color","!rgb:FFFFFF!"))).resourceType("video").imageTag("b_gray,co_$color,l_text:Arial_150:  $(award");
```

```ruby
cl_image_tag("b_gray,co_$color,l_text:Arial_150:  $(award", resource_type: "video", transformation: [
  {variables: [["$award", "!First!"]]},
  {variables: [["$color", "!rgb:FFFFFF!"]]}
  ])
```

```csharp
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Variables("$award", !First!).Chain()
  .Variables("$color", !rgb:FFFFFF!)).BuildImageTag("b_gray,co_$color,l_text:Arial_150:  $(award")
```

```dart
cloudinary.image('b_gray,co_$color,l_text:Arial_150:  $(award').transformation(Transformation()
	.addVariable(Variable.set("award","First"))
	.addVariable(Variable.set("color","rgb:FFFFFF"))
	.setAssetType("video"));
```

```swift
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .chain()
  ).generate("b_gray,co_$color,l_text:Arial_150:  $(award")
```

```android
MediaManager.get().url().transformation(new Transformation()
  .variables(variable("$award","!First!")).chain()
  .variables(variable("$award","!First!")).variables(variable("$color","!rgb:FFFFFF!"))).resourceType("video").generate("b_gray,co_$color,l_text:Arial_150:  $(award");
```

```flutter
cloudinary.image('b_gray,co_$color,l_text:Arial_150:  $(award').transformation(Transformation()
	.addVariable(Variable.set("award","First"))
	.addVariable(Variable.set("color","rgb:FFFFFF"))
	.setAssetType("video"));
```

```kotlin
cloudinary.image {
	publicId("b_gray,co_\$color,l_text:Arial_150:  \$(award")
	 addVariable(Variable.set("award","First"))
	 addVariable(Variable.set("color","rgb:FFFFFF"))
	 assetType("video") 
}.generate()
```

```jquery
$.cloudinary.image("b_gray,co_$color,l_text:Arial_150:  $(award", {resource_type: "video", transformation: [
  {variables: [["$award", "!First!"]]},
  {variables: [["$color", "!rgb:FFFFFF!"]]}
  ]})
```

```react_native
import { set } from "@cloudinary/url-gen/actions/variable";

new CloudinaryImage("b_gray,co_$color,l_text:Arial_150:  $(award")
  .addVariable(set("award", "First"))
  .addVariable(set("color", "rgb:FFFFFF"))
  .setAssetType("video");
```%20%20Place%20,r_10,o_76,g_south,y_10/docs/car-film.mp4 "thumb: w_350,dpr_2, width: 350")

You can also populate the text or color from contextual metadata or structured metadata. For example:

* `$vidtext_ctx:!videotext!/$color_ctx:!textcolor!/co_$color,l_text:Roboto_35_bold:$(vidtext)`
* `$vidtext_md:!videotext!/$color_md:!textcolor!/co_$color,l_text:Roboto_35_bold:$(vidtext)`

> **NOTE**: For structured metadata, use the syntax: `md:!!`. Be sure to use the external ID, not the label.

### 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](video_conditional_expressions#supported_video_characteristics).

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. 

![Use a variable value to determine whether a conditional transformation will be applied](https://res.cloudinary.com/demo/video/upload/$qualtag_!Pro!/if_$qualtag_in_tags/q_90/if_else/q_30/if_end/c_scale,w_500/meadow_walk.mp4)

```nodejs
cloudinary.video("meadow_walk", {transformation: [
  {variables: [["$qualtag", "!Pro!"]]},
  {if: "$qualtag_in_tags"},
  {quality: 90},
  {if: "else"},
  {quality: 30},
  {if: "end"},
  {width: 500, crop: "scale"}
  ]})
```

```react
import { set } from "@cloudinary/url-gen/actions/variable";
import { ifCondition } from "@cloudinary/url-gen/actions/conditional";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { quality } from "@cloudinary/url-gen/actions/delivery";

new CloudinaryVideo("meadow_walk.mp4")
  .addVariable(set("qualtag", "Pro"))
  .conditional(
    ifCondition(
      "$qualtag in tags",
      new Transformation().delivery(quality(90))
    ).otherwise(new Transformation().delivery(quality(30)))
  )
  .resize(scale().width(500));
```

```vue
import { set } from "@cloudinary/url-gen/actions/variable";
import { ifCondition } from "@cloudinary/url-gen/actions/conditional";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { quality } from "@cloudinary/url-gen/actions/delivery";

new CloudinaryVideo("meadow_walk.mp4")
  .addVariable(set("qualtag", "Pro"))
  .conditional(
    ifCondition(
      "$qualtag in tags",
      new Transformation().delivery(quality(90))
    ).otherwise(new Transformation().delivery(quality(30)))
  )
  .resize(scale().width(500));
```

```angular
import { set } from "@cloudinary/url-gen/actions/variable";
import { ifCondition } from "@cloudinary/url-gen/actions/conditional";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { quality } from "@cloudinary/url-gen/actions/delivery";

new CloudinaryVideo("meadow_walk.mp4")
  .addVariable(set("qualtag", "Pro"))
  .conditional(
    ifCondition(
      "$qualtag in tags",
      new Transformation().delivery(quality(90))
    ).otherwise(new Transformation().delivery(quality(30)))
  )
  .resize(scale().width(500));
```

```js
import { set } from "@cloudinary/url-gen/actions/variable";
import { ifCondition } from "@cloudinary/url-gen/actions/conditional";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { quality } from "@cloudinary/url-gen/actions/delivery";

new CloudinaryVideo("meadow_walk.mp4")
  .addVariable(set("qualtag", "Pro"))
  .conditional(
    ifCondition(
      "$qualtag in tags",
      new Transformation().delivery(quality(90))
    ).otherwise(new Transformation().delivery(quality(30)))
  )
  .resize(scale().width(500));
```

```python
CloudinaryVideo("meadow_walk").video(transformation=[
  {'variables': [["$qualtag", "!Pro!"]]},
  {'if': "$qualtag_in_tags"},
  {'quality': 90},
  {'if': "else"},
  {'quality': 30},
  {'if': "end"},
  {'width': 500, 'crop': "scale"}
  ])
```

```php
use Cloudinary\Transformation\Variable;
use Cloudinary\Transformation\Conditional;
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Delivery;

(new VideoTag('meadow_walk.mp4'))
	->addVariable(Variable::set("qualtag","Pro"))
	->conditional(Conditional::ifCondition("$qualtag in tags",(new Transformation())
	->delivery(Delivery::quality(90)))
	->otherwise((new Transformation())
	->delivery(Delivery::quality(30)))
	)
	->resize(Resize::scale()->width(500));
```

```java
cloudinary.url().transformation(new Transformation()
  .variables(variable("$qualtag","!Pro!")).chain()
  .if("$qualtag_in_tags").chain()
  .quality(90).chain()
  .if("else").chain()
  .quality(30).chain()
  .if("end").chain()
  .width(500).crop("scale")).videoTag("meadow_walk");
```

```ruby
cl_video_tag("meadow_walk", transformation: [
  {variables: [["$qualtag", "!Pro!"]]},
  {if: "$qualtag_in_tags"},
  {quality: 90},
  {if: "else"},
  {quality: 30},
  {if: "end"},
  {width: 500, crop: "scale"}
  ])
```

```csharp
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Variables("$qualtag", !Pro!).Chain()
  .If("$qualtag_in_tags").Chain()
  .Quality(90).Chain()
  .If("else").Chain()
  .Quality(30).Chain()
  .If("end").Chain()
  .Width(500).Crop("scale")).BuildVideoTag("meadow_walk")
```

```dart
cloudinary.video('meadow_walk.mp4').transformation(Transformation()
	.addTransformation("$qualtag_!Pro!/if_$qualtag_in_tags/q_90/if_else/q_30/if_end/c_scale,w_500"));
```

```swift
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .chain()
  .setIf("$qualtag_in_tags").chain()
  .setQuality(90).chain()
  .setIf("else").chain()
  .setQuality(30).chain()
  .setIf("end").chain()
  .setWidth(500).setCrop("scale")).generate("meadow_walk.mp4")
```

```android
MediaManager.get().url().transformation(new Transformation()
  .variables(variable("$qualtag","!Pro!")).chain()
  .if("$qualtag_in_tags").chain()
  .quality(90).chain()
  .if("else").chain()
  .quality(30).chain()
  .if("end").chain()
  .width(500).crop("scale")).resourceType("video").generate("meadow_walk.mp4");
```

```flutter
cloudinary.video('meadow_walk.mp4').transformation(Transformation()
	.addTransformation("$qualtag_!Pro!/if_$qualtag_in_tags/q_90/if_else/q_30/if_end/c_scale,w_500"));
```

```kotlin
cloudinary.video {
	publicId("meadow_walk.mp4")
	 addTransformation("\$qualtag_!Pro!/if_\$qualtag_in_tags/q_90/if_else/q_30/if_end/c_scale,w_500") 
}.generate()
```

```jquery
$.cloudinary.video("meadow_walk", {transformation: [
  {variables: [["$qualtag", "!Pro!"]]},
  {if: "$qualtag_in_tags"},
  {quality: 90},
  {if: "else"},
  {quality: 30},
  {if: "end"},
  {width: 500, crop: "scale"}
  ]})
```

```react_native
import { set } from "@cloudinary/url-gen/actions/variable";
import { ifCondition } from "@cloudinary/url-gen/actions/conditional";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { quality } from "@cloudinary/url-gen/actions/delivery";

new CloudinaryVideo("meadow_walk.mp4")
  .addVariable(set("qualtag", "Pro"))
  .conditional(
    ifCondition(
      "$qualtag in tags",
      new Transformation().delivery(quality(90))
    ).otherwise(new Transformation().delivery(quality(30)))
  )
  .resize(scale().width(500));
```

<br>

The above transformation is running on 'meadow_walk', 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 'meadow_walk2' video, which is identical, except without the 'Pro' tag, <a href="https://res.cloudinary.com/demo/video/upload/$qualtag_!Pro!/if_$qualtag_in_tags/q_90/if_else/q_30/if_end/c_scale,w_500/meadow_walk2.mp4" target="_blank">it's delivered with a low quality value of 30</a>.
## Expression evaluation order

Within a transformation component, condition (if) statements are evaluated first, then variable assignments, then transformations. Therefore:

* When an assignment is made in a conditional component, the assignment is evaluated only if the condition is true.

* Even if a transformation is specified before a variable assignment within the same URL component, the value is assigned before the transformation. For example, if you deliver a URL containing the following condition: <br/>
   `if_w_gt_5,w_$x,$x_5` <br/>
  Even though the variable `x` is assigned the value `5` only at the end of the transformation, that assignment will be applied first. Afterwards, the `width` transformation takes on the value (5) of the `x` variable.

  However, the best practice is to separate conditions from results in separate URL components in the order you want them evaluated. For example: `if_w_gt_5/$x_5/c_scale,w_$x/if_end`, as explained in  [Conditional transformations](using_video_conditional_expressions#specifying_transformations_for_a_condition).

## 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](named_transformations) 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, the quality condition is applied if the video has a tag set to `important`. Regardless of the tag, the delivery width will be 450px.

![Use variables with a named transformation](https://res.cloudinary.com/demo/video/upload/$qualtag_!important!/$delwidth_450/t_highqual-if-tagged/rafting.mp4)

```nodejs
cloudinary.video("rafting", {transformation: [
  {variables: [["$qualtag", "!important!"]]},
  {variables: [["$delwidth", "450"]]},
  {transformation: ["highqual-if-tagged"]}
  ]})
```

```react
import { set } from "@cloudinary/url-gen/actions/variable";
import { name } from "@cloudinary/url-gen/actions/namedTransformation";

new CloudinaryVideo("rafting.mp4")
  .addVariable(set("qualtag", "important"))
  .addVariable(set("delwidth", 450))
  .namedTransformation(name("highqual-if-tagged"));
```

```vue
import { set } from "@cloudinary/url-gen/actions/variable";
import { name } from "@cloudinary/url-gen/actions/namedTransformation";

new CloudinaryVideo("rafting.mp4")
  .addVariable(set("qualtag", "important"))
  .addVariable(set("delwidth", 450))
  .namedTransformation(name("highqual-if-tagged"));
```

```angular
import { set } from "@cloudinary/url-gen/actions/variable";
import { name } from "@cloudinary/url-gen/actions/namedTransformation";

new CloudinaryVideo("rafting.mp4")
  .addVariable(set("qualtag", "important"))
  .addVariable(set("delwidth", 450))
  .namedTransformation(name("highqual-if-tagged"));
```

```js
import { set } from "@cloudinary/url-gen/actions/variable";
import { name } from "@cloudinary/url-gen/actions/namedTransformation";

new CloudinaryVideo("rafting.mp4")
  .addVariable(set("qualtag", "important"))
  .addVariable(set("delwidth", 450))
  .namedTransformation(name("highqual-if-tagged"));
```

```python
CloudinaryVideo("rafting").video(transformation=[
  {'variables': [["$qualtag", "!important!"]]},
  {'variables': [["$delwidth", "450"]]},
  {'transformation': ["highqual-if-tagged"]}
  ])
```

```php
use Cloudinary\Transformation\Variable;
use Cloudinary\Transformation\NamedTransformation;

(new VideoTag('rafting.mp4'))
	->addVariable(Variable::set("qualtag","important"))
	->addVariable(Variable::set("delwidth",450))
	->namedTransformation(NamedTransformation::name("highqual-if-tagged"));
```

```java
cloudinary.url().transformation(new Transformation()
  .variables(variable("$qualtag","!important!")).chain()
  .variables(variable("$qualtag","!important!")).variables(variable("$delwidth","450")).chain()
  .named("highqual-if-tagged")).videoTag("rafting");
```

```ruby
cl_video_tag("rafting", transformation: [
  {variables: [["$qualtag", "!important!"]]},
  {variables: [["$delwidth", "450"]]},
  {transformation: ["highqual-if-tagged"]}
  ])
```

```csharp
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Variables("$qualtag", !important!).Chain()
  .Variables("$delwidth", 450).Chain()
  .Named("highqual-if-tagged")).BuildVideoTag("rafting")
```

```dart
cloudinary.video('rafting.mp4').transformation(Transformation()
	.addVariable(Variable.set("qualtag","important"))
	.addVariable(Variable.set("delwidth",450))
	.namedTransformation(NamedTransformation.name("highqual-if-tagged")));
```

```swift
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .chain()
  .chain()
  .setNamed("highqual-if-tagged")).generate("rafting.mp4")
```

```android
MediaManager.get().url().transformation(new Transformation()
  .variables(variable("$qualtag","!important!")).chain()
  .variables(variable("$qualtag","!important!")).variables(variable("$delwidth","450")).chain()
  .named("highqual-if-tagged")).resourceType("video").generate("rafting.mp4");
```

```flutter
cloudinary.video('rafting.mp4').transformation(Transformation()
	.addVariable(Variable.set("qualtag","important"))
	.addVariable(Variable.set("delwidth",450))
	.namedTransformation(NamedTransformation.name("highqual-if-tagged")));
```

```kotlin
cloudinary.video {
	publicId("rafting.mp4")
	 addVariable(Variable.set("qualtag","important"))
	 addVariable(Variable.set("delwidth",450))
	 namedTransformation(NamedTransformation.name("highqual-if-tagged")) 
}.generate()
```

```jquery
$.cloudinary.video("rafting", {transformation: [
  {variables: [["$qualtag", "!important!"]]},
  {variables: [["$delwidth", "450"]]},
  {transformation: ["highqual-if-tagged"]}
  ]})
```

```react_native
import { set } from "@cloudinary/url-gen/actions/variable";
import { name } from "@cloudinary/url-gen/actions/namedTransformation";

new CloudinaryVideo("rafting.mp4")
  .addVariable(set("qualtag", "important"))
  .addVariable(set("delwidth", 450))
  .namedTransformation(name("highqual-if-tagged"));
```

> **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** Settings (enabled by default). When this setting is disabled, any URL that exposes tags, contextual metadata or structured metadata values will return an error.

