@@ -42,7 +42,8 @@ With JVC, you'd write this spec file and save it to a file | |||||
"operation": "split", | "operation": "split", | ||||
"creates": "src_split_files", | "creates": "src_split_files", | ||||
"source": "src", | "source": "src", | ||||
"interval": "60" | |||||
"interval": "60", | |||||
"validate": [{ "comment": "expected 12 files", "test": "output.length === 12" }] | |||||
}] | }] | ||||
} | } | ||||
``` | ``` | ||||
@@ -53,6 +54,9 @@ jvc my-spec.jvc | |||||
Yes, the JVC is longer, but I think many would agree it is easier to read | Yes, the JVC is longer, but I think many would agree it is easier to read | ||||
and maintain. | and maintain. | ||||
As you can see above, JVC can also `validate` your operations to ensure that | |||||
the output assets are what you expect them to be. | |||||
**As the number of media assets and operations grows, hand-crafted shell | **As the number of media assets and operations grows, hand-crafted shell | ||||
scripts with magical ffmpeg incantations become ever more inscrutable.** | scripts with magical ffmpeg incantations become ever more inscrutable.** | ||||
@@ -143,6 +147,13 @@ Trim audio/video; crop a section of an asset, becomes a new asset. | |||||
Here is a [long, complex example](docs/complex_example.md) that uses | Here is a [long, complex example](docs/complex_example.md) that uses | ||||
every operation. | every operation. | ||||
## JVC JavaScript Expressions | |||||
There are actually two DSLs in JVC. One is the JSON format for JVC files, | |||||
which tells jvc where the assets are and what to do with them. | |||||
The second DSL is not really a full DSL, it's more a JavaScript context | |||||
in which you can evaluate expressions. | |||||
## What's with the name? | ## What's with the name? | ||||
A cross between a javelin and an icicle? JSON and a miracle? | A cross between a javelin and an icicle? JSON and a miracle? | ||||
Something with positive connotations? | Something with positive connotations? | ||||
@@ -0,0 +1,29 @@ | |||||
# Asset References | |||||
Most operations have a `source` parameter that indicates what asset is | |||||
considered the primary input to that operation. | |||||
The value of `source` is the name of an asset, either defined in `assets` | |||||
or as the output of a previous operation (named in the `creates` block). | |||||
## List Assets | |||||
The `split` operation creates multiple assets under the same name, this | |||||
is called a "list asset", in contrast to a "singular asset" that only | |||||
refers to one file. | |||||
If you want to reference a specific file within a list asset, use square | |||||
bracket notation: | |||||
```shell script | |||||
some_list_asset[0] # first sub-asset | |||||
some_list_asset[-1] # last sub-asset | |||||
some_list_asset[1..3] # 2nd, 3rd and 4th assets | |||||
some_list_asset[..3] # 1st, 2nd, 3rd and 4th assets | |||||
some_list_asset[3..] # 4th asset and everything after | |||||
``` | |||||
## Concat Operation `sources` | |||||
The `concat` operation does not take a `source` param (which would name | |||||
one asset), it takes a `sources` array of asset names. | |||||
The named assets can be either singular assets or list assets. | |||||
`concat` flattens the list of assets and concatenates them all together. |
@@ -32,14 +32,32 @@ Assets expose properties that can be referenced in operations. The properties cu | |||||
* `height`: width of the video in pixels (video and image assets only) | * `height`: width of the video in pixels (video and image assets only) | ||||
## Operations | ## Operations | ||||
Operations are transformations to perform on the inputs. | |||||
Operations represent transformations to perform on the inputs, and validations | |||||
to ensure correctness. | |||||
### Operation Assets | |||||
An operation requires one or more input assets. These assets are referenced | |||||
using the `source` (or for `concat`, `sources`) parameter. | |||||
An operation can produce one or more new assets, which can then be referenced in | An operation can produce one or more new assets, which can then be referenced in | ||||
later operations. | later operations. | ||||
Most of the operation settings can be JavaScript expressions, for example: | |||||
Learn more about [Asset References](asset_refs.md). | |||||
### Operation Configuration | |||||
Many of the operation settings can be JavaScript expressions, for example: | |||||
"start": "someAsset.duration - 10" | "start": "someAsset.duration - 10" | ||||
The above would set the `start` value to ten seconds before the end of `someAsset`. | The above would set the `start` value to ten seconds before the end of `someAsset`. | ||||
Learn more about [JavaScript expressions in JVC](jvc_js.md). | |||||
### Operation Validation | |||||
An operation may define validations to perform by defining a `validation` array. | |||||
Each object in the array has properties `comment` (to describe the test) and | |||||
`test` which is a JavaScript expression. If it evaluates to `true` then the | |||||
test passes. If `false`, the test fails and the `comment` is printed. | |||||
Learn more about [JavaScript expressions in JVC](jvc_js.md). |
@@ -0,0 +1,50 @@ | |||||
# JVC JavaScript Expressions | |||||
JavaScript expressions are used in a couple of places in JVC. | |||||
* Operation configuration | |||||
* Operation validations | |||||
## Operation Configuration | |||||
When you're writing the JSON for an operation, many of the operation's | |||||
config parameters can be JS expressions that will be evaluated | |||||
when the operation is run. | |||||
For example, say you wanted to use `trim` to just chop a video in half. | |||||
The `start` and `end` parameters of the `trim` operation support JavaScript | |||||
expressions, so you could write: | |||||
```js | |||||
{ | |||||
"comment": "cut video at midpoint", | |||||
"operation": "trim", | |||||
"creates": "chopped" | |||||
"source": "some_vid", | |||||
"end": "source.duration / 2" | |||||
} | |||||
``` | |||||
or run: | |||||
```shell script | |||||
jtrim some_vid.mp4 output_vid.mp4 0 "source.duration / 2" | |||||
``` | |||||
In the above, `source` is referring to the source asset, `some_vid`. | |||||
When JVC loads an asset (like `some_vid`), or an operation creates a new asset, | |||||
the asset metadata is read using `mediainfo`. The metadata is stored in an object | |||||
that is then put into the JavaScript context using the variable name `source`. | |||||
## Operation Validations | |||||
Once an operation completes, the validations run to ensure that the output | |||||
assets pass whatever tests you want to run. | |||||
Each test is a JavaScript expressions, which is evaluated to a boolean value. | |||||
If the expression is true, the test passes. If false, the test fails and the | |||||
`comment` associated with the failing test is printed. | |||||
## JavaScript Context | |||||
What variables are available in the JS context? And what properties do they have? | |||||
### Assets | |||||
Assets can be defined in the JVC's `assets` array, or as the output of an | |||||
operation. | |||||
Assets are referenced by their asset name. |
@@ -32,6 +32,7 @@ public abstract class JOperation { | |||||
@Getter @Setter private String operation; | @Getter @Setter private String operation; | ||||
@Getter @Setter private JsonNode creates; | @Getter @Setter private JsonNode creates; | ||||
@Getter @Setter private JValidation[] validate; | |||||
@Getter @Setter private boolean noExec = false; | @Getter @Setter private boolean noExec = false; | ||||
@Getter @Setter private String comment; | @Getter @Setter private String comment; | ||||
@@ -0,0 +1,18 @@ | |||||
package jvc.model.operation; | |||||
import lombok.Getter; | |||||
import lombok.Setter; | |||||
import org.cobbzilla.util.javascript.JsEngine; | |||||
import java.util.Map; | |||||
public class JValidation { | |||||
@Getter @Setter private String comment; | |||||
@Getter @Setter private String test; | |||||
public boolean eval(Map<String, Object> ctx, JsEngine js) { | |||||
return js.evaluateBoolean(test, ctx); | |||||
} | |||||
} |