# AI agents (/docs/ai-agents) Give an AI assistant these docs, and what it must know to write a correct rule. A rule file is plain JSON checked strictly when it loads, which makes it a good task for an AI assistant: it writes the file, and the panel tells you exactly what is wrong if anything is. ## Give the docs to your assistant [#give-the-docs-to-your-assistant] These docs are published as Markdown for language models: | URL | Content | | :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------ | | [`/llms.txt`](/llms.txt) | An index of every page, with its description ([llms.txt](https://llmstxt.org)). | | [`/llms-full.txt`](/llms-full.txt) | Every page in one Markdown file. Give this one to an assistant that writes rules. | | `/llms.mdx/docs//content.md` | One page as Markdown, such as [`/llms.mdx/docs/reference/fields/content.md`](/llms.mdx/docs/reference/fields/content.md). | Every page also has a **Copy Markdown** button under its title, and a menu to open it in an AI assistant. ## A prompt that works [#a-prompt-that-works] ```text Read the PPROLint rule documentation: /llms-full.txt Write a PPROLint rule file that reports . - Use only fields listed in the Fields reference, in the scope you choose. - Put thresholds in options, with defaults that rarely fire on a correct timeline. - Messages name the item and give the measured value and the threshold. - Output the complete file, named .rule.json. ``` Save the answer in your rules folder and click **Reload rules**. If the file has problems, paste them back to the assistant: each one gives the JSON path and the reason. ## Checklist for agents [#checklist-for-agents] When writing a rule file: 1. **Start from a built-in rule** with a similar purpose: the [built-in rules](/docs/rules) show complete, valid files. Reusing an existing id replaces that rule; choose a new id otherwise. 2. **Pick the scope** whose items you report on: `clip`, `track`, `effect`, `marker` or `sequence` ([Scopes](/docs/reference/scopes)). 3. **Use only listed fields** of that scope ([Fields](/docs/reference/fields)). Paths are checked; there are no other fields and no expressions. 4. **Respect types.** Number operators need number fields and values; `in` takes a list; `exists` takes no value ([Operators](/docs/reference/operators)). 5. **Guard unknown values.** A comparison on an unknown value is false, and `not` turns it true: prefer positive comparisons, or add `exists` ([Unknown values](/docs/guides/conditions#unknown-values)). 6. **Put thresholds in `options`** and refer to them as `{ "field": "options." }` ([Options](/docs/guides/options)). 7. **Severity**: `info` for something unusual, `warning` or `error` for a certain problem. 8. **Write self-explaining messages** with `{field.path}` placeholders, and plural forms when a number changes the grammar ([Messages](/docs/guides/messages)). 9. **Add `data`** with the measured value and the thresholds ([Data](/docs/guides/data)). 10. **No unknown properties.** Every property is listed in [Rule file](/docs/reference/rule-file); anything else is an error. # Changelog (/docs/changelog) What changed in each version of PPROLint. Each version lists what changed for users. ## 1.0.0 [#100] The first release. * A Premiere Pro panel that checks the active sequence while you edit, or when you click **Check now**, and lists errors, warnings and notes with their timecodes. * Clicking a problem moves the playhead to it and selects the clips involved. PPROLint never changes the timeline. * [Built-in rules](/docs/rules): technical checks (offline media, gaps, disabled clips…), consistency between clips (audio levels, scale, speed, duration) and project conventions (required tracks, markers and effects, sequence settings). * Every rule can be turned off in the settings. * A [rule editor](/docs/editor) in the panel's settings to change built-in rules, their thresholds included, and build your own, saved as [rule files](/docs/guides/your-first-rule-file) you can share. * The panel follows Premiere's theme and speaks English, German, Spanish, French, Italian, Japanese, Korean, Brazilian Portuguese, Russian and Simplified Chinese. * Requires Premiere Pro 25.6 or later, on macOS or Windows. # Checks (/docs/editor/checks) What a check holds, how several checks combine, and how to run a check on another scope or point it elsewhere in the timeline. A **check** is one reason to report: a condition, and the message shown when it holds. Every rule has at least one. ![Check 1 of Fast clips: Scope Same as the rule (Clip), Report when clip.speed is greater than 2, the message, Plural forms unchecked, Position Default for the scope, Data with Add entry](/docs/editor/tutorial-check-done.webp) Click **Add check** to add one. Each check is titled *Check 1*, *Check 2*… with its message at the right of the title; click the title to fold it. The trash button removes a check, except the last one: a rule needs a check. ## What a check holds [#what-a-check-holds] | Row | What it does | Page | | :-------------- | :-------------------------------------------------------------- | :------------------------------------ | | **Scope** | The items the check runs on. *Same as the rule* by default. | [below](#scope) | | **Report when** | The condition: when it holds for an item, the item is reported. | [Conditions](/docs/editor/conditions) | | **Message** | What the panel shows for the item. | [Messages](/docs/editor/messages) | | **Position** | Where the report points in the timeline. | [below](#position) | | **Data** | Values attached to this check's reports. | [Data](/docs/editor/data) | ## Several checks [#several-checks] A rule has several checks when it reports for different reasons, or words two situations differently. The built-in *Subframe video edits* rule has five: a clip that starts between two frames, one that ends between two frames, one that does both, and the sequence's in and out points. ![The Checks section of Subframe video edits with five folded checks, each showing its message](/docs/editor/checks-collapsed.webp) How they combine depends on **Matching**, in the [Rule section](/docs/editor/rule-section#matching): * **First check that holds**: the checks are tried from top to bottom, and only the first that holds reports. Put the most specific check first. * **Every check that holds**: each check that holds reports, so one item can get several reports. *Subframe video edits* works this way, and its conditions exclude each other where needed: "starts between two frames" also requires that the clip ends on a frame. There is no condition shared by all the checks: when every check needs the same condition (an enabled clip, say), add it to each. ## Scope [#scope] A check runs on the rule's scope unless you choose another one. Pick **Same as the rule** to follow the rule's scope, or any other scope. ![The check's Scope list: Same as the rule (Clip), then Sequence, Track, Clip, Effect, Marker and the analyzers](/docs/editor/picker-check-scope.webp) The last check of *Subframe video edits* runs on the **Sequence** while the rule runs on clips: it reads `sequence.outPoint` to report the sequence's out point. ![Check 5 of Subframe video edits: Scope Sequence, Report when sequence.outPointFrameOffset is greater than 0, message Sequence out point is between two frames, Position sequence.outPoint, and two data entries](/docs/editor/check-scope.webp) The condition, message, position and data of a check use the fields of the check's scope. The rule's own [diagnostic data](/docs/editor/data) must make sense in every check's scope. ## Position [#position] Where the report points in the timeline: clicking it in the panel moves the playhead there. **Default for the scope** is the start of the clip for clip and effect checks, and the start of the marker for marker checks. Track and sequence checks have no default position. To choose one, pick a number field that holds a time, such as `track.firstClipStart` (the built-in *Muted tracks* rule) or `sequence.outPoint`. ## In a rule file [#in-a-rule-file] Checks are the `checks` list of the rule file; each has `condition`, `message`, and optionally `scope`, `location` (the position) and `data`. See [Checks](/docs/guides/checks). # Conditions (/docs/editor/conditions) Build the condition of a check from comparisons and groups — fields, operators, values, all / any / not. The **Report when** row of a check is its condition: an item is reported when the condition holds for it. A condition is either one **comparison**, or a **group** of conditions. ## Comparisons [#comparisons] A comparison is one row of three boxes that reads like a sentence: *field*, *operator*, *value*. ![A comparison: clip.speed is greater than 2](/docs/editor/tutorial-condition.webp) ### The field [#the-field] The first box is the value of the item that the comparison looks at. Its list holds every field of the check's [scope](/docs/editor/rule-section#scope), grouped by what it describes (`sequence`, `track`, `clip`…), then the rule's options. Each field has a short description under its name. ![The field list: clip fields such as clip.duration, clip.speed, clip.disabled, each with a description](/docs/editor/tutorial-field-picker.webp) All the fields are listed in the [Fields](/docs/reference/fields) reference. Times are in **ticks** (254,016,000,000 per second) unless the field's name says frames, seconds or timecode: compare `clip.durationFrames` with a number of frames, not `clip.duration`. Choosing another field keeps the operator and the value when they still fit its type, and resets them otherwise. ### The operator [#the-operator] The second box lists the operators that fit the field's type. ![The operators for a number field: is, is not, is greater than, is at least, is less than, is at most, is between, is one of, is not one of, is known, is unknown](/docs/editor/tutorial-operator-picker.webp) | Operator | Fields | Holds when the field… | Rule file | | :------------------- | :------------- | :----------------------------------- | :------------------- | | **is** | all | equals the value | `equals` | | **is not** | all | differs from the value | `notEquals` | | **is greater than** | numbers | is more than the value | `greaterThan` | | **is at least** | numbers | is the value or more | `greaterThanOrEqual` | | **is less than** | numbers | is less than the value | `lessThan` | | **is at most** | numbers | is the value or less | `lessThanOrEqual` | | **is between** | numbers | is between two values, both included | `between` | | **is one of** | numbers, texts | is one of a list of values | `in` | | **is not one of** | numbers, texts | is none of a list of values | `notIn` | | **contains** | texts | contains the text (case matters) | `contains` | | **does not contain** | texts | does not contain the text | `notContains` | | **matches** | texts | matches a regular expression | `matches` | | **is known** | all | has a value | `exists` | | **is unknown** | all | has no value | `notExists` | Yes/no fields offer **is**, **is not**, **is known** and **is unknown**. ### The value [#the-value] The value box changes with the operator. **A single value** (is, is greater than, contains…): type a number or a text. For a number field, the box only accepts a number; `Infinity` and `-Infinity` are accepted too (a silent audio clip has a volume of `-Infinity` dB). **Yes or No**, for a yes/no field: ![clip.reversed is No](/docs/editor/condition-boolean.webp) **Two values**, for **is between**. Both bounds are included: `50` and `150` match 50 % and 150 %. ![clip.scale is between 50 and 150](/docs/editor/condition-between.webp) **A list**, for **is one of** and **is not one of**. Type a value and press **Enter** to add it; click the **×** of a value to remove it. ![clip.source.extension is one of mov, mxf](/docs/editor/condition-list.webp) **A regular expression**, for **matches**. `^TEMP` matches names that start with TEMP; `\d` is a digit; `$` is the end of the text. The editor reports an invalid expression. ![clip.name matches ^TEMP](/docs/editor/condition-matches.webp) **Nothing**, for **is known** and **is unknown**. ![clip.source.mediaPath is unknown](/docs/editor/condition-unknown.webp) ### Compare with a field or an option [#compare-with-a-field-or-an-option] Instead of typing a value, you can compare with another field of the same item, or with one of the rule's [options](/docs/editor/options). Click the arrow of the value box: the list shows the fields and options of the same type. Pick one, and the comparison uses its value for each item. ![The value list open: number fields, then an options group with options.maxSpeed](/docs/editor/tutorial-value-option.webp) For **is one of**, the list offers the list options of the rule (a *List of texts* option for a text field). Typing in the box again replaces the field with what you type. ## Groups [#groups] To combine conditions, put them in a group. A group is a row with its kind and *of the following*, and its conditions indented under it. ![All of the following: clip.speed is greater than options.maxSpeed, clip.disabled is No](/docs/editor/tutorial-group.webp) | Group | Holds when | Rule file | | :----------------------- | :-------------------------------------- | :-------- | | **All** of the following | every condition in it holds (and) | `all` | | **Any** of the following | at least one condition in it holds (or) | `any` | | **Not** the following | its one condition does not hold | `not` | ![The group kind list: All, Any, Not](/docs/editor/picker-group-kind.webp) Change a group's kind with its first box. Switching between **All** and **Any** keeps its conditions; switching to **Not** keeps the first one only. Groups nest: an **Any** inside an **All** reads "this, and (that or that)". The built-in *Tiny clips* rule nests two: ![All of: clip.duration is greater than 0, clip.durationFrames is less than options.minFrames, Any of (clip.trackType is video, options.includeAudio is Yes), Any of (clip.adjustmentLayer is No, options.includeAdjustmentLayers is Yes)](/docs/editor/condition-nested.webp) ## Add, wrap and remove [#add-wrap-and-remove] **+ Add**, under a condition or at the end of a group, adds to it: ![The Add menu: Add condition, Add an all group, Add an any group, Add a not](/docs/editor/tutorial-add-menu.webp) * **Add condition**: a new comparison. * **Add an "all" group**, **Add an "any" group**: a new group, with one comparison in it. * **Add a "not"**: a comparison inside a **Not**. When the condition is a single comparison, adding turns it into an **All** group holding the comparison and the new condition. The **…** button at the end of each row has more: ![The … menu of a group: Wrap in a group, Keep only its first condition](/docs/editor/menu-row-group.webp) | Action | What it does | | :-------------------------------- | :------------------------------------------------------------------------------------------------------------------- | | **Wrap in a group** | Puts the row inside a new **All** group, to add conditions next to it. Change the group's kind afterwards if needed. | | **Keep only its first condition** | Replaces a group with its first comparison. | | **Remove condition** | Removes the row, and everything in it for a group. The top condition of a check cannot be removed, only changed. | ## Unknown values [#unknown-values] Some fields can have **no value**: an audio clip has no scale, a clip without media has no media path, an in point may not be set. The [Fields](/docs/reference/fields) reference marks these with a `?` type. A comparison on a field without a value is **false**, whatever the operator, except **is known** and **is unknown**. So `clip.scale is less than 50` never reports an audio clip, and neither does `clip.scale is not 100`. **Not** turns a false comparison into true. **Not** `clip.scale is 100` reports *every audio clip*, since they have no scale. Prefer positive comparisons (`is less than` the minimum, *or* `is greater than` the maximum) over **Not** `is between`, or add `clip.scale is known` to an **All** group. ## In a rule file [#in-a-rule-file] A comparison is `{ "field", "operator", "value" }`, and groups are `{ "all": [...] }`, `{ "any": [...] }` and `{ "not": ... }`; the table above gives each operator's name. See [Conditions](/docs/guides/conditions) and [Operators](/docs/reference/operators). # Data (/docs/editor/data) Attach the measured value and the limits to every report. **Diagnostic data** are named values attached to a rule's reports: the measured value and the limit that caused each one. The panel shows them with the results, and tools reading the reports use them without parsing the message. ![Diagnostic data with two entries: speed from clip.speed, maxSpeed from options.maxSpeed](/docs/editor/tutorial-data.webp) ## Add an entry [#add-an-entry] Click **Add entry**, then fill in: * **Key**: the name of the value, such as `speed`. * **Field or constant**: pick a field or an option from the list, or type a constant. A constant typed as `12` or `true` is kept as a number or a yes/no; anything else is text. The trash button removes an entry. A constant is useful to tell checks apart, as in the example below. ## Rule data and check data [#rule-data-and-check-data] There are two places for entries: * the **Diagnostic data** section, at the bottom of the editor, applies to every check of the rule; * the **Data** row of a [check](/docs/editor/checks) applies to that check only, and wins over a rule entry with the same key. The built-in *Markers outside the work area* rule attaches the sequence's end and in and out points to every report, and each of its three checks adds a constant `reason`: `after-end`, `before-in` or `after-out`. ![The Diagnostic data section of Markers outside the work area: sequenceEnd, inPoint and outPoint from sequence.end, sequence.inPoint and sequence.outPoint](/docs/editor/data-section.webp) A rule entry must make sense for every check: when the checks run on different [scopes](/docs/editor/checks#scope), use fields every scope has, such as `sequence.*`. ## In a rule file [#in-a-rule-file] Data are the `data` objects of the rule and of its checks: a field path, or `{ "literal": value }` for a constant. See [Data](/docs/guides/data). # The rule editor (/docs/editor) Create and change rules in the PPROLint panel, without writing any JSON. The rule editor builds rules with menus and fields, in the PPROLint settings. Every rule you can write as a [rule file](/docs/guides/your-first-rule-file) can be built here, and the editor checks the rule as you type: you cannot save a rule that would not work. ![The rule editor showing the Fast clips rule: the Rule, Options, Checks, Labels and Diagnostic data sections, with Delete rule, Cancel and Save at the bottom](/docs/editor/editor-overview.webp) ## Open the editor [#open-the-editor] Open the PPROLint panel's settings and choose **Rules**. Then: * to **create** a rule, click the **New rule** button next to the search field and choose **New rule from scratch**; * to **change** a rule, built-in or yours, click the cogwheel at the right of its row. The editor replaces the list of rules. **‹ Rules**, at the top left, takes you back. See [The Rules settings](/docs/editor/rules-list) for everything else the list does. ## How the editor is laid out [#how-the-editor-is-laid-out] The editor reads from top to bottom, like Premiere's Effect Controls panel. ![The editor header: a Rules back button, the rule name Fast clips, and Custom rule at the right](/docs/editor/editor-header.webp) **The header** shows the rule's name and what kind of rule it is: | Kind | Meaning | | :----------------------- | :---------------------------------------------------------- | | *Built-in rule* | A rule PPROLint ships with. Saving it writes your own copy. | | *Custom rule* | A rule you created or imported. | | *Modified built-in rule* | Your copy of a built-in rule, which replaces it. | **The sections** hold the parts of the rule. Click a section's title to fold it; a folded section shows a summary at the right of its title (the option names, the number of checks). ![All sections folded: Rule, Options with maxSpeed, Checks with 1 check, Labels with None, Diagnostic data with speed and maxSpeed](/docs/editor/editor-collapsed.webp) | Section | What it holds | Page | | :------------------ | :------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------ | | **Rule** | Id, name, description, category, scope, severity, matching. | [Rule section](/docs/editor/rule-section) | | **Options** | Values a user can tune, such as a threshold. | [Options](/docs/editor/options) | | **Checks** | When to report (the condition) and what to say (the message). | [Checks](/docs/editor/checks), [Conditions](/docs/editor/conditions), [Messages](/docs/editor/messages) | | **Labels** | Words that change with a value, in each language. | [Labels](/docs/editor/labels) | | **Diagnostic data** | Values attached to every report. | [Data](/docs/editor/data) | **The footer** says where the rule is saved and in which language you are editing its texts, with the buttons to save or leave. ![The editor footer: Saved in max-clip-speed.rule.json. Texts are edited in English; other languages keep their own. Buttons: Delete rule, Cancel, Save](/docs/editor/editor-footer-custom.webp) ## Problems are shown as you type [#problems-are-shown-as-you-type] The editor checks the rule a moment after each change. When something is wrong, a box under the header lists every problem, and the control at fault turns red with the reason under it. **Save** stays disabled until the list is empty. ![A red box: 3 problems to fix before saving, listing an unknown field options.maxSpeed in the data, the condition and the message](/docs/editor/editor-problems.webp) Each problem starts with the place it was found, such as `checks[0].message.en_US`: the message of the first check, in English. See [Saving and leaving](/docs/editor/saving#problems). ## What the editor writes [#what-the-editor-writes] The editor writes an ordinary rule file, `.rule.json`, in your rules folder. You can open it in a text editor, share it with your team, or [import](/docs/editor/rules-list#import-rule-files) it on another computer. Anything you learn here applies to rule files, and the other way round: each page of this section links to its counterpart in [Rule files](/docs/guides/your-first-rule-file). ## Where to go next [#where-to-go-next] # Labels (/docs/editor/labels) Show a value as words that depend on the value and the language, such as a marker type or "named" versus "unnamed". A [placeholder](/docs/editor/messages#placeholders) shows a value as it is: `{marker.type}` shows `Comment`, in every language, and `{marker.named}` shows `true`. A **label** shows words instead, chosen by the value: *Comment marker "Intro"*, or *Unnamed marker*. Labels are optional. Most rules don't need any. ## The Labels section [#the-labels-section] The built-in *Markers outside the work area* rule has two labels: ![The Labels section with two labels. {labels.markerType}, field marker.type, wording Comment → Comment, Chapter → Chapter, WebLink → Web Link, FLVCuePoint → Flash Cue Point, Segmentation → Segmentation. {labels.marker}, field marker.named, wording true → Marker {marker.name} ({labels.markerType}), false → Unnamed marker ({labels.markerType})](/docs/editor/labels-section.webp) Each label has: * a **Name**: messages insert the label as `{labels.}`, shown in the label's title; * a **Field**: the value that picks the words; * its **Wording**: one row per value, with the **Value** to match and the **Text** to show for it. Its message is then: > `{labels.marker} at {marker.startTimecode} is after the end of the sequence ({sequence.endTimecode}).` which reads *Marker "Intro" (Comment) at 00:01:10:00 is after the end of the sequence (00:01:00:00).*, or *Unnamed marker (Chapter) at …*. ## Build a label [#build-a-label] 1. Click **Add label**, and give it a name. 2. Pick its **Field**. 3. For each value, click **Add value**, type the value in **Value** and the words in **Text**. How values are matched: * as text: the values of a yes/no field are `true` and `false`; * a value with no row shows as it is; * a text may contain placeholders, and other labels (`{labels.markerType}` above); * a text may be empty, to leave out a part of the sentence for some values; * the **…** button of a row inserts a placeholder, or turns the text into [plural forms](/docs/editor/messages#plural-forms). ## Labels and languages [#labels-and-languages] The texts of a label are edited in the panel's language, like messages, and fall back to English in the others. Translating the label is how a rule words a value in each language. See [Translations](/docs/editor/translations). ## In a rule file [#in-a-rule-file] Labels are the `labels` object of the rule file: `{ "field", "values" }` per name. See [Labels](/docs/guides/labels). # Messages (/docs/editor/messages) Write the sentence shown for each report, with placeholders for the item's values and plural forms. The **Message** of a check is the sentence the panel shows for each item it reports. A good message names the item and gives the measured value and the limit, so it explains itself: > Clip "A002.mov" on V1 plays at 3× speed (maximum 1.5×). ## Placeholders [#placeholders] A word in braces is a **placeholder**: `{clip.name}` is replaced by the name of the reported clip, `{options.maxSpeed}` by the option's value. Any field of the check's scope and any option can be a placeholder. The **{ }** button at the right of the message lists them all, and adds the one you pick at the end of the text. You can also type them; the editor reports a placeholder that names no field. ![The Insert field menu, listing the fields that can be inserted](/docs/editor/tutorial-insert-field.webp) How values are shown: | Value | Shown as | | :------- | :------------------------------------------------------------------------------------- | | text | as it is: `A002.mov` | | number | formatted for the panel's language, with at most one decimal: `12.5`, `12,5` in French | | yes/no | `true` or `false` | | no value | `?` | `{clip.speed:3}` shows up to three decimals instead of one. Times are numbers of ticks, which mean nothing to a reader: show the timecode fields instead, such as `{clip.startTimecode}` or `{marker.startTimecode}`. To show a value as words that depend on the language, such as a marker type, use a [label](/docs/editor/labels). ## Plural forms [#plural-forms] "1 frames long" reads badly. When a number in the sentence changes its grammar, tick **Plural forms**: the message becomes one sentence per form, and a **Count field** picks the form from a number. ![Plural forms ticked on the Tiny clips message: Count field clip.durationFrames, One: …{clip.durationFrames} frame long…, Other: …{clip.durationFrames} frames long…, and Add form](/docs/editor/message-plural.webp) * **Count field**: the number that decides the form, here `clip.durationFrames`. * **One**: the sentence for one (1 frame). * **Other**: the sentence for every other number. It is required. * **Add form** adds **Few** or **Many**, for languages that have them, such as Russian. ![The Add form menu: Few, Many](/docs/editor/menu-add-form.webp) Write the whole sentence in each form. Unticking **Plural forms** keeps the **Other** sentence as the message. ## Messages and languages [#messages-and-languages] The message is edited in the panel's language, like the name and description. Other languages keep their own text, or show the English one until they have it. See [Translations](/docs/editor/translations). ## In a rule file [#in-a-rule-file] The message is the `message` of a check: a string, or an object keyed by language; plural forms are `{ "count", "one", "other" }`. See [Messages](/docs/guides/messages). # Options (/docs/editor/options) Turn thresholds and lists into settings with a default value, and use them in conditions and messages. An **option** is a value of the rule that you can change without touching its checks: a threshold, a switch, a list of allowed names. Conditions compare with it, messages show it, and its default is the value the rule uses. ![The Options section of the Tiny clips rule: minFrames (Number, 3), includeAudio (Yes/no, Yes) and includeAdjustmentLayers (Yes/no, No), each with a description](/docs/editor/options-section.webp) ## Add an option [#add-an-option] Click **Add option**. A row appears with: * **Name**: how conditions and messages refer to it, as `options.`. Use a short word without spaces, such as `maxSpeed` or `includeAudio`. Two options cannot share a name. * **Type**: what the option holds (see below). * **Default**: the value the rule uses. * **Description**: what the option changes, for whoever adjusts the rule later. The trash button at the right of the row removes the option. ## Types [#types] ![The Type list: Number, Text, Yes/no, List of numbers, List of texts, JSON](/docs/editor/picker-option-type.webp) | Type | Holds | The default is entered as | | :------------------ | :----------------------------------------------- | :------------------------------------------------- | | **Number** | a number, such as a limit | a number. `Infinity` and `-Infinity` are accepted. | | **Text** | a word or a sentence | text. | | **Yes/no** | a switch | **Yes** or **No**. | | **List of numbers** | several numbers, such as frame rates | a list (see below). | | **List of texts** | several words, such as effect or file names | a list (see below). | | **JSON** | a structured value, read by computed scopes only | JSON text. | Changing the type keeps the default when it still fits, and resets it otherwise. ### Lists [#lists] A list default shows its values as tags. Type a value in the box under them and press **Enter** to add it; click the **×** of a tag to remove it. ![The allow option of Duplicate effects: type List of texts, with tags AE.ADBE Crop and AE.ADBE Geometry2 and AE.ADBE Lumetri typed in the box](/docs/editor/options-list.webp) ### JSON [#json] Some built-in rules, such as [Required markers](/docs/rules/required-markers), take a JSON option: a list of requirements, each with several properties. Its default is edited as JSON text; the editor says *Not valid JSON.* until the text parses. The option's description says what the value must look like. ![The markers option of Required markers: type JSON, default [] in a text area, and a description of the expected requirement objects](/docs/editor/options-json.webp) ## Use an option [#use-an-option] An option is a field named `options.`, available wherever fields are: * **In a condition**, as the value: open the value list with its arrow and pick the option. It is listed with the fields of the same type, in the *options* group. See [Conditions](/docs/editor/conditions#compare-with-a-field-or-an-option). * **In a message**, as the placeholder `{options.}`, from the **{ }** menu. See [Messages](/docs/editor/messages). * **In diagnostic data**, to attach the threshold to every report. See [Data](/docs/editor/data). A list option is used with **is one of** and **is not one of**. ### A switch for part of a rule [#a-switch-for-part-of-a-rule] A **Yes/no** option can turn a part of the rule on or off. The built-in *Tiny clips* rule checks audio clips only when `includeAudio` is on: its condition holds for a video clip, *or* when the option is on. ![The condition of Tiny clips: All of clip.duration is greater than 0, clip.durationFrames is less than options.minFrames, Any of (clip.trackType is video, options.includeAudio is Yes), Any of (clip.adjustmentLayer is No, options.includeAdjustmentLayers is Yes)](/docs/editor/condition-nested.webp) ## Renaming an option [#renaming-an-option] The editor does not rename the uses of an option. After renaming one, every condition, message or data entry still using the old name shows a problem, *Unknown field "options.…"*: pick the new name there too. ## In a rule file [#in-a-rule-file] Options are the `options` object of the rule file, `{ "type", "default", "description" }` per name. The types are `number`, `string`, `boolean`, `number[]`, `string[]` and `json`. See [Options](/docs/guides/options). # Recipes (/docs/editor/recipes) Complete rules to build in the editor, each with its settings and the file it writes. Each recipe gives the settings to enter in the editor, then the rule file the editor writes. Start each with **New rule > New rule from scratch** in the [Rules settings](/docs/editor/rules-list). A recipe's file can also be saved as is in your rules folder. Conditions are written as they read in the editor: *field* **operator** *value*. ## Temporary clip names [#temporary-clip-names] Report clips still named after a placeholder, such as `TEMP shot 3`. | Setting | Value | | :---------- | :--------------------------------------------------------------- | | Id | `no-temp-clip-names` | | Name | Temporary clip names | | Scope | Clip | | Severity | Warning | | Report when | `clip.name` **matches** `^(TEMP\|TMP)\b` | | Message | `Clip "{clip.name}" on {clip.track} still has a temporary name.` | ```json title="no-temp-clip-names.rule.json" { "formatVersion": 1, "id": "no-temp-clip-names", "name": "Temporary clip names", "description": "Reports clips whose name starts with TEMP or TMP.", "category": "static", "scope": "clip", "severity": "warning", "checks": [ { "condition": { "field": "clip.name", "operator": "matches", "value": "^(TEMP|TMP)\\b" }, "message": "Clip \"{clip.name}\" on {clip.track} still has a temporary name." } ] } ``` ## Unwanted file types [#unwanted-file-types] Report clips whose media is a file type your delivery does not accept. The list is an option, so it can change per project. | Setting | Value | | :---------- | :------------------------------------------------------------------------- | | Id | `no-unwanted-media-types` | | Name | Unwanted media types | | Scope | Clip | | Severity | Error | | Option | `extensions`, List of texts, default `mp3`, `wma`, `gif` | | Report when | `clip.source.extension` **is one of** `options.extensions` | | Message | `Clip "{clip.name}" on {clip.track} uses a .{clip.source.extension} file.` | The extension is lower case and without the dot. Clips without media (titles, adjustment layers) have no extension, so they are never reported. ```json title="no-unwanted-media-types.rule.json" { "formatVersion": 1, "id": "no-unwanted-media-types", "name": "Unwanted media types", "description": "Reports clips whose media file type is not accepted.", "category": "static", "scope": "clip", "severity": "error", "options": { "extensions": { "type": "string[]", "default": ["mp3", "wma", "gif"], "description": "File extensions not accepted, lower case, without the dot." } }, "checks": [ { "condition": { "field": "clip.source.extension", "operator": "in", "value": { "field": "options.extensions" } }, "message": "Clip \"{clip.name}\" on {clip.track} uses a .{clip.source.extension} file." } ] } ``` ## Unnamed chapter markers [#unnamed-chapter-markers] Report chapter markers without a name, which export as empty chapters. | Setting | Value | | :---------- | :------------------------------------------------------------------- | | Id | `no-unnamed-chapters` | | Name | Unnamed chapters | | Scope | Marker | | Severity | Warning | | Report when | **All** of: `marker.type` **is** `Chapter`, `marker.named` **is** No | | Message | `Chapter marker at {marker.startTimecode} has no name.` | ```json title="no-unnamed-chapters.rule.json" { "formatVersion": 1, "id": "no-unnamed-chapters", "name": "Unnamed chapters", "description": "Reports chapter markers without a name.", "category": "static", "scope": "marker", "severity": "warning", "checks": [ { "condition": { "all": [ { "field": "marker.type", "operator": "equals", "value": "Chapter" }, { "field": "marker.named", "operator": "equals", "value": false } ] }, "message": "Chapter marker at {marker.startTimecode} has no name." } ] } ``` ## Loud audio clips [#loud-audio-clips] Report audio clips whose volume is raised above a limit. Video clips have no volume, so they are never reported. | Setting | Value | | :---------- | :----------------------------------------------------------------------------------------------- | | Id | `max-clip-volume` | | Name | Loud audio clips | | Scope | Clip | | Severity | Info | | Option | `maxDb`, Number, default `6` | | Report when | **All** of: `clip.disabled` **is** No, `clip.volume` **is greater than** `options.maxDb` | | Message | `Clip "{clip.name}" on {clip.track} is raised to {clip.volume} dB (maximum {options.maxDb} dB).` | | Data | `volumeDb` from `clip.volume` | ```json title="max-clip-volume.rule.json" { "formatVersion": 1, "id": "max-clip-volume", "name": "Loud audio clips", "description": "Reports audio clips whose volume is raised above a limit.", "category": "static", "scope": "clip", "severity": "info", "options": { "maxDb": { "type": "number", "default": 6, "description": "Highest allowed clip volume, in dB." } }, "checks": [ { "condition": { "all": [ { "field": "clip.disabled", "operator": "equals", "value": false }, { "field": "clip.volume", "operator": "greaterThan", "value": { "field": "options.maxDb" } } ] }, "message": "Clip \"{clip.name}\" on {clip.track} is raised to {clip.volume} dB (maximum {options.maxDb} dB)." } ], "data": { "volumeDb": "clip.volume" } } ``` ## Too many video tracks [#too-many-video-tracks] Report a sequence with more video tracks than your template allows. This rule runs once, on the sequence. | Setting | Value | | :---------- | :--------------------------------------------------------------------------------------------- | | Id | `max-video-tracks` | | Name | Too many video tracks | | Category | Project | | Scope | Sequence | | Severity | Warning | | Option | `max`, Number, default `6` | | Report when | `sequence.videoTrackCount` **is greater than** `options.max` | | Message | `The sequence has {sequence.videoTrackCount} video tracks; the template allows {options.max}.` | ```json title="max-video-tracks.rule.json" { "formatVersion": 1, "id": "max-video-tracks", "name": "Too many video tracks", "description": "Reports sequences with more video tracks than allowed.", "category": "project", "scope": "sequence", "severity": "warning", "options": { "max": { "type": "number", "default": 6, "description": "Highest number of video tracks." } }, "checks": [ { "condition": { "field": "sequence.videoTrackCount", "operator": "greaterThan", "value": { "field": "options.max" } }, "message": "The sequence has {sequence.videoTrackCount} video tracks; the template allows {options.max}." } ] } ``` ## Tighten a built-in rule [#tighten-a-built-in-rule] The built-in [Scale range](/docs/rules/scale-range) rule allows 25 % to 200 %. For a project that must never upscale: 1. Open **Scale range** with its cogwheel. 2. In **Options**, set the default of `max` to `100`. 3. Save. Your copy replaces the built-in rule, marked *Modified built-in rule* ([Revert to built-in](/docs/editor/saving#revert-a-built-in-rule) to undo). Every built-in rule can be adjusted the same way. The [Built-in rules](/docs/rules) pages list their options. # Rule section (/docs/editor/rule-section) The id, name, description, category, scope, severity and matching of a rule. The **Rule** section, at the top of the editor, says what the rule is and what it looks at. ![The Rule section: Id max-clip-speed, Name Fast clips, Description, Category Static, Scope Clip, Severity Warning, Matching First check that holds](/docs/editor/rule-section.webp) ## Id [#id] The id is the rule's permanent name, such as `max-clip-speed`: lower-case letters and digits in words joined by hyphens. The rule's file is named after it (`max-clip-speed.rule.json`), and every report names it. You choose the id when you create a rule, and it cannot change afterwards: the field becomes plain text once the rule is saved. A new rule cannot take the id of an existing rule; the editor says *A rule with id "…" already exists*. To replace a built-in rule, [edit it](/docs/editor/saving#change-a-built-in-rule) instead. ## Name and description [#name-and-description] The **Name** is the short title of the rule in the Rules settings. The **Description** is one sentence saying what the rule reports, shown under the name. Both are required. They are edited in the panel's language. See [Translations](/docs/editor/translations). ## Category [#category] Where the rule sits among the others. It does not change what the rule does. ![The Category list: Static, Local consistency, Global consistency, Project](/docs/editor/picker-category.webp) | Category | For a rule that… | | :--------------------- | :---------------------------------------------------------------------- | | **Static** | checks a fact about one item: an offline clip, a disabled clip, a gap. | | **Local consistency** | compares a clip with the clips around it. | | **Global consistency** | compares a clip with all the clips of the sequence. | | **Project** | checks a requirement for the whole sequence: tracks, markers, settings. | ## Scope [#scope] The scope decides **what the rule looks at**. The rule's checks run once for every item of the scope, and the fields you can use are the fields of that item. ![The Scope list: Items of the sequence (Sequence, Track, Clip, Effect, Marker), then Analyzers, each with a description](/docs/editor/picker-scope.webp) Under **Items of the sequence**: | Scope | The checks run on… | Fields you can use | | :----------- | :---------------------------------------- | :-------------------------------------------- | | **Sequence** | the sequence, once | `sequence.*` | | **Track** | every video track, then every audio track | `track.*`, `sequence.*` | | **Clip** | every clip, video tracks first | `clip.*`, `track.*`, `sequence.*` | | **Effect** | every effect you applied to a clip | `effect.*`, `clip.*`, `track.*`, `sequence.*` | | **Marker** | every sequence marker | `marker.*`, `sequence.*` | The rule's options (`options.*`) are available in every scope. The [Fields](/docs/reference/fields) reference describes each field. Under **Analyzers** are computed scopes, which the built-in rules use for gaps, outliers, pairs of clips and requirements; their items are computed by PPROLint. Picking one adds the options it needs to the [Options](/docs/editor/options) section. [Computed scopes](/docs/reference/computed-scopes) describes each, with its fields; the simplest way to use one is to start from the [built-in rule](/docs/rules) that uses it. Fields belong to a scope. After a change of scope, a condition that names a field the new scope does not have shows a problem: pick another field, or change the scope back. A single check can also run on another scope than the rule's: see [Checks](/docs/editor/checks#scope). ## Severity [#severity] How serious a report is: **Info**, **Warning** or **Error**. The panel shows each with its icon. ![The Severity list: Info, Warning, Error](/docs/editor/picker-severity.webp) Use **Info** for something unusual that may be deliberate, **Warning** or **Error** for a certain problem. ## Matching [#matching] What happens when an item meets the condition of several checks. ![The Matching list: First check that holds, Every check that holds](/docs/editor/picker-matching.webp) * **First check that holds** (the default): checks are tried in order, and the first one that holds reports. An item gets at most one report from the rule. * **Every check that holds**: every check that holds reports, so an item can get several reports. Use it when the checks describe different problems. See [Checks](/docs/editor/checks#several-checks). ## In a rule file [#in-a-rule-file] | Editor | Rule file | | :-------------------- | :------------------------------------------------------------------------------- | | Id, Name, Description | `id`, `name`, `description` | | Category | `category`: `static`, `local-consistency`, `global-consistency`, `project` | | Scope | `scope`: `sequence`, `track`, `clip`, `effect`, `marker`, or a computed scope id | | Severity | `severity`: `info`, `warning`, `error` | | Matching | `matching`: `first`, `all` | See [Rule file](/docs/reference/rule-file). # The Rules settings (/docs/editor/rules-list) Turn rules on and off, search them, create, import and reload rule files, and see which files failed to load. Every rule PPROLint runs is listed in the panel's settings, under **Rules**: the built-in rules and yours, with their name and description. ![The Rules settings: the sections of the settings on the left; on the right a search field, three buttons, and the list of rules with a checkbox and a cogwheel each](/docs/editor/rules-list.webp) ## Turn a rule on or off [#turn-a-rule-on-or-off] Each rule has a checkbox. A rule that is off does not run, and the next check drops its reports. Turning a rule off keeps its file and its settings: turn it back on at any time. ## Find a rule [#find-a-rule] Type in **Search rules** to keep only the rules whose name or description contains the text. The search ignores case and accents. ![Searching scale keeps Invisible video clips, Scale range and Scale outliers](/docs/editor/rules-search.webp) ## Which rules are yours [#which-rules-are-yours] The description of a rule tells where it comes from: | Shown before the description | The rule is… | | :--------------------------- | :----------------------------------------------------------------------------------------------------------------------------- | | nothing | a built-in rule, as PPROLint ships it. | | *Custom rule* | a rule you created or imported. | | *Modified built-in rule* | your copy of a built-in rule. It replaces the built-in rule until you [revert it](/docs/editor/saving#revert-a-built-in-rule). | ![The top of the list: Fast clips described as Custom rule, then built-in rules](/docs/editor/rules-list-toolbar.webp) ## The buttons next to the search [#the-buttons-next-to-the-search] From left to right: | Button | What it does | | :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------- | | **New rule** | A menu: **New rule from scratch** opens an empty rule in the [editor](/docs/editor); **Import rules…** copies rule files into your rules folder. | | **Reload rules** | Reads your rules folder again. Use it after changing or adding a file by hand. | | **Open rules folder** | Shows your rules folder in Finder or Explorer. Premiere asks your permission first. | ![The New rule menu: New rule from scratch, Import rules…](/docs/editor/new-rule-menu.webp) ### Import rule files [#import-rule-files] **New rule > Import rules…** lets you pick one or more rule files, for example files a colleague sent you. PPROLint copies them into your rules folder and reloads the rules. A `.json` file is renamed `.rule.json`, and a file never overwrites another one: if the name is taken, a number is added to it. If an imported file uses the id of a built-in rule, it replaces that rule and shows as *Modified built-in rule*. ## Edit a rule [#edit-a-rule] The cogwheel at the right of a rule opens it in the [rule editor](/docs/editor). Built-in rules open too: saving one writes your own copy, which replaces it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule files that could not be loaded [#rule-files-that-could-not-be-loaded] A rule file with a mistake is not loaded. The list shows it in a box at the top, with the file name and each problem. The other rules still run. ![A box: 1 rule file could not be loaded. temp-names.rule.json: checks[0].condition.field: Unknown field clip.nam](/docs/editor/rules-file-errors.webp) This only happens to files edited outside the editor, since the editor never saves a rule with problems. Fix the file in a text editor and click **Reload rules**, or delete it from the rules folder. [Troubleshooting](/docs/guides/troubleshooting) explains the messages. # Saving and leaving (/docs/editor/saving) Save a rule, fix the problems that block saving, change and revert built-in rules, delete your rules. The footer of the editor says where the rule is saved and holds its buttons. ![The footer of a custom rule: Saved in max-clip-speed.rule.json. Texts are edited in English; other languages keep their own. Delete rule, Cancel, Save](/docs/editor/editor-footer-custom.webp) ## Save [#save] **Save** writes the rule to your rules folder, closes the editor and reloads the rules: the change applies from the next check, and the panel confirms with *Rule saved.* **Save** is disabled while: * the rule has [problems](#problems); * nothing has changed since you opened the rule. | You are editing | Save writes | | :---------------- | :---------------------------------------------------------------------------------------- | | a new rule | a new file, `.rule.json`. | | one of your rules | its own file, whatever its name. | | a built-in rule | your copy, `.rule.json`, which [replaces the built-in rule](#change-a-built-in-rule). | ## Problems [#problems] The editor checks the rule a moment after every change. Each problem shows twice: in the list under the header, and under the control at fault, in red. ![3 problems to fix before saving: data.maxSpeed, checks[0].condition.all[1].value.field and checks[0].message.en_US name the unknown field options.maxSpeed](/docs/editor/editor-problems.webp) ![The same problem under the value of the condition, in red: Unknown field options.maxSpeed. Declared options: limit.](/docs/editor/editor-problem-inline.webp) The list gives the place of each problem in the rule: | Place | Means | | :--------------------------- | :----------------------------------------------------------- | | `name.en_US` | the rule's name, in English | | `options.maxSpeed.default` | the default of the option `maxSpeed` | | `checks[0].condition` | the condition of the first check (`checks[1]` is the second) | | `checks[0].condition.all[1]` | the second condition of the first check's **All** group | | `checks[0].message.fr_FR` | the message of the first check, in French | | `data.speed` | the diagnostic data entry `speed` | Common problems: | Problem | Fix | | :------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------- | | *Must be a non-empty string.* | Fill in the name, the description or the message. | | *Must be a non-empty array…* on `checks` | Add a check. | | *Unknown field "…"* | The field is not in the check's scope, or names an option that does not exist (renamed or removed). Pick another field. | | *A rule with id "…" already exists.* | Choose another id for the new rule. | | *Must be a number, like the field it is compared with.* | The value does not fit the field's type. | ## Leave without saving [#leave-without-saving] **Cancel**, or **‹ Rules** in the header, leaves the editor. If you changed something, PPROLint asks first: ![A dialog: Discard changes? Your changes to Fast clips! have not been saved. Cancel, Discard](/docs/editor/dialog-discard.webp) **Discard** drops your changes; **Cancel** goes back to the editor. ## Change a built-in rule [#change-a-built-in-rule] A built-in rule opens in the editor like any other. Change its options, severity, condition or messages, then save: the editor writes your copy, `.rule.json`, in your rules folder. The footer says so before you save: ![The editor on the built-in Tiny clips rule; the footer says Saving creates no-tiny-clips.rule.json in your rules folder. It replaces the built-in rule until you revert.](/docs/editor/editor-footer-builtin.webp) From then on, your copy runs instead of the built-in rule, and the Rules settings mark it *Modified built-in rule*. Updates of PPROLint never overwrite it. ### Revert a built-in rule [#revert-a-built-in-rule] Open your copy and click **Revert to built-in**. ![The footer of a modified built-in rule: Saved in scale-range.rule.json, which replaces the built-in rule. Revert to built-in, Cancel, Save](/docs/editor/editor-footer-override.webp) PPROLint asks to confirm, then deletes your file: the built-in rule runs again. ![A dialog: Revert to the built-in rule? scale-range.rule.json will be deleted and the built-in rule Scale range will run again. Cancel, Revert to built-in](/docs/editor/dialog-revert.webp) ## Delete a rule [#delete-a-rule] Open one of your rules and click **Delete rule**. PPROLint asks to confirm, then deletes its file. ![A dialog: Delete this rule? max-clip-speed.rule.json will be deleted. Cancel, Delete rule](/docs/editor/dialog-delete.webp) To stop a rule without deleting it, turn it off in the [Rules settings](/docs/editor/rules-list#turn-a-rule-on-or-off) instead. Built-in rules cannot be deleted, only turned off. ## The saved file [#the-saved-file] The editor writes a tidy rule file: defaults are left out, and texts with English only are plain strings. You can open it in a text editor, change it and click **Reload rules**, then open it in the editor again. See [Rule files](/docs/guides/your-first-rule-file). # Translations (/docs/editor/translations) Give a rule's name, description, messages and labels a text in each language of Premiere. A rule speaks the languages of Premiere's interface: English, German, Spanish, French, Italian, Japanese, Korean, Brazilian Portuguese, Russian and Simplified Chinese. Each of its texts (name, description, messages and label wordings) can have one text per language. ## You edit in the panel's language [#you-edit-in-the-panels-language] The editor edits the texts **in the panel's language**. The footer says which one: ![The footer of the editor in French: Enregistrée dans max-clip-speed.rule.json. Les textes sont modifiés en Français ; les autres langues conservent les leurs.](/docs/editor/translation-footer.webp) Other languages keep their own texts. A rule needs English; a language without its own text shows the English one. ## Translate a rule [#translate-a-rule] 1. Write the rule in English first: set the panel's language to English in the settings, under **General > Language**. 2. Switch the panel's language to the language to add, and open the rule again. 3. Each text without a translation shows the English one, with a note under it. Type the translation over it. ![The Rule section in French: Nom Fast clips and Description in English, each with the note Pas encore de texte en Français : l'anglais est affiché. Le modifier en crée un.](/docs/editor/translation-fallback.webp) 4. Save. Repeat for each language. **Language: Auto** follows Premiere's own language. Translate whole sentences: word order changes between languages, and [plural forms](/docs/editor/messages#plural-forms) differ too. Values that must be worded per language, such as a marker type, are [labels](/docs/editor/labels). ## In a rule file [#in-a-rule-file] A translated text is an object keyed by locale, `{ "en_US": "…", "fr_FR": "…" }`. See [Messages](/docs/guides/messages#translations). # Your first rule (/docs/editor/your-first-rule) Build a rule that reports sped-up clips in the rule editor, see it report in Premiere, then make its limit an option. In this tutorial you build **Fast clips**, a rule that reports clips played faster than 200 %. You will create the rule, write its condition and message, save it, see it report a clip, and then turn the 200 % into a setting. It takes about ten minutes, and you need nothing but Premiere Pro with PPROLint. ## 1. Create the rule [#1-create-the-rule] 1. Open the PPROLint panel's settings and choose **Rules**. 2. Click the **New rule** button, at the right of the search field, and choose **New rule from scratch**. ![The New rule button's menu open next to the Search rules field, with New rule from scratch and Import rules…](/docs/editor/new-rule-menu.webp) The editor opens on an empty rule. A red box already lists three problems: the rule has no name, no description and no check yet. That is expected. You fix them in the next steps, and **Save** turns on once the list is empty. ![The editor on a new rule named new-rule, with 3 problems to fix before saving: an empty name, an empty description and no checks](/docs/editor/editor-blank.webp) ## 2. Name the rule [#2-name-the-rule] In the **Rule** section: * **Id**: `max-clip-speed`. The id is the rule's permanent name: lower-case words joined by hyphens. It can only be changed now, while the rule is new. * **Name**: `Fast clips`. This is what the Rules settings list shows. * **Description**: `Reports clips played faster than the allowed speed.` Leave the other settings as they are. **Scope: Clip** means the rule looks at every clip of the sequence; **Severity: Warning** is how serious a report is. ![The Rule section filled in: Id max-clip-speed, Name Fast clips, the description, Category Static, Scope Clip, Severity Warning, Matching First check that holds](/docs/editor/tutorial-rule-section.webp) ## 3. Add a check [#3-add-a-check] A **check** says when to report and what to say. In the **Checks** section, click **Add check**. ![A new Check 1 with Scope Same as the rule (Clip), a condition clip.id is (empty), an empty Message marked Must not be empty, Position and Data](/docs/editor/tutorial-check-added.webp) The **Report when** row is the condition. It reads like a sentence: *field*, *operator*, *value*. 1. Click the first box, which shows `clip.id`, and choose **clip.speed**. Each field has a short description under its name; `clip.speed` is the playback speed, where 1 is 100 %. ![The field list open, showing clip fields with their descriptions; clip.speed reads Playback speed, 1 = 100 %](/docs/editor/tutorial-field-picker.webp) 2. Click the second box, the operator, and choose **is greater than**. The list only offers operators that make sense for a number. ![The operator list for a number field: is, is not, is greater than, is at least, is less than, is at most, is between, is one of, is not one of, is known, is unknown](/docs/editor/tutorial-operator-picker.webp) 3. Type `2` in the third box, the value. ![The finished condition: Report when clip.speed is greater than 2](/docs/editor/tutorial-condition.webp) ## 4. Write the message [#4-write-the-message] The message is what the panel shows for each clip the rule reports. A good message says which clip and why. Type in **Message**: `Clip "{clip.name}" on {clip.track} plays at {clip.speed}× speed.` Words in braces are **placeholders**: PPROLint replaces `{clip.name}` with the clip's name, `{clip.track}` with its track (`V1`) and `{clip.speed}` with its speed. You don't have to type them: the **{ }** button at the right of the message lists every field and inserts the one you pick. ![The Insert field menu open next to the message, listing fields such as sequence.name and sequence.fps](/docs/editor/tutorial-insert-field.webp) The check is complete, and the problems box is gone: ![Check 1 complete: clip.speed is greater than 2, and the message Clip {clip.name} on {clip.track} plays at {clip.speed}× speed.](/docs/editor/tutorial-check-done.webp) ## 5. Save and try it [#5-save-and-try-it] Click **Save**. The editor closes and *Fast clips* is in the list, marked *Custom rule*. It is on, and it runs from the next check. ![The Rules settings with Fast clips at the top, described as Custom rule · Reports clips played faster than the allowed speed, and a Rule saved. notification](/docs/editor/tutorial-saved.webp) To see it report, set a clip of your sequence to 300 % (**Clip > Speed/Duration…**). The PPROLint panel shows: ![The PPROLint panel listing one warning: Clip A002.mov on V1 plays at 3× speed, at 00:00:10:00, from max-clip-speed](/docs/editor/tutorial-results.webp) Click the result to select the clip in the timeline. ## 6. Make the limit an option [#6-make-the-limit-an-option] A fixed 200 % suits one project, not every one. An **option** turns the limit into a setting with a default value, which you can change later without touching the condition. Open the rule again with its cogwheel. In **Options**, click **Add option** and fill in: * **Name**: `maxSpeed` * **Type**: Number * **Default**: `2` * **Description**: `Highest allowed speed; 1 is 100 %.` ![The Options section with one option: name maxSpeed, type Number, default 2, description Highest allowed speed; 1 is 100 %.](/docs/editor/tutorial-option.webp) Now use it in the condition. In the value box, which still says `2`, clear the text and click its arrow: the list shows the number fields **and your options**. Choose **options.maxSpeed**. ![The value list open under the condition, ending with an options group holding options.maxSpeed](/docs/editor/tutorial-value-option.webp) Change the message so it gives the limit too: `Clip "{clip.name}" on {clip.track} plays at {clip.speed}× speed (maximum {options.maxSpeed}×).` ## 7. Skip disabled clips [#7-skip-disabled-clips] A disabled clip does not play, so its speed does not matter. Add a second condition: 1. Click **+ Add** under the condition and choose **Add condition**. ![The Add menu under the condition: Add condition, Add an all group, Add an any group, Add a not](/docs/editor/tutorial-add-menu.webp) 2. The condition becomes a group: **All of the following**, which holds when every condition in it does. Set the new row to **clip.disabled** **is** **No**. ![Report when All of the following: clip.speed is greater than options.maxSpeed, clip.disabled is No](/docs/editor/tutorial-group.webp) ## 8. Attach the measured values [#8-attach-the-measured-values] The panel can show values next to each report. In **Diagnostic data**, click **Add entry** twice and fill in two entries: `speed` from **clip.speed**, and `maxSpeed` from **options.maxSpeed**. ![Diagnostic data with two entries: speed from clip.speed and maxSpeed from options.maxSpeed](/docs/editor/tutorial-data.webp) Click **Save**. With `maxSpeed` set to 1.5, the panel now reports: ![The PPROLint panel listing: Clip A002.mov on V1 plays at 3× speed (maximum 1.5×)](/docs/editor/tutorial-results-option.webp) ## What you built [#what-you-built] Your rule is a file, `max-clip-speed.rule.json`, in your rules folder: ```json title="max-clip-speed.rule.json" { "formatVersion": 1, "id": "max-clip-speed", "name": "Fast clips", "description": "Reports clips played faster than the allowed speed.", "category": "static", "scope": "clip", "severity": "warning", "options": { "maxSpeed": { "type": "number", "default": 2, "description": "Highest allowed speed; 1 is 100 %." } }, "checks": [ { "condition": { "all": [ { "field": "clip.speed", "operator": "greaterThan", "value": { "field": "options.maxSpeed" } }, { "field": "clip.disabled", "operator": "equals", "value": false } ] }, "message": "Clip \"{clip.name}\" on {clip.track} plays at {clip.speed}× speed (maximum {options.maxSpeed}×)." } ], "data": { "speed": "clip.speed", "maxSpeed": "options.maxSpeed" } } ``` Along the way you used every part of the editor that most rules need: * the [Rule section](/docs/editor/rule-section): id, name, scope, severity; * a [check](/docs/editor/checks) with a [condition](/docs/editor/conditions) and a [message](/docs/editor/messages); * an [option](/docs/editor/options), and [diagnostic data](/docs/editor/data). Next, browse the [recipes](/docs/editor/recipes) for more rules to build, or read [How rules work](/docs/how-rules-work). # Checks (/docs/guides/checks) Word different situations differently, report several problems per item, change the scope or position of a check. Every rule lists its `checks`, even when there is only one. A check pairs a [condition](/docs/guides/conditions) with the [message](/docs/guides/messages) reported when it holds, and optional [data](/docs/guides/data) merged over the rule's own. | Property | Required | Meaning | | :---------- | :------- | :-------------------------------------------------------------------------- | | `condition` | yes | When to report. | | `message` | yes | What to say. | | `data` | no | Values attached to this check's diagnostics, merged over the rule's `data`. | | `scope` | no | Runs this check on another [scope](/docs/reference/scopes) than the rule's. | | `location` | no | A number field, in ticks, giving the diagnostic's position in the timeline. | ## Several checks [#several-checks] A rule that words two situations differently has one check per situation. They are tried **in order**, and the first whose condition holds gives the item its diagnostic. An item is reported at most once per rule: ```json "checks": [ { "condition": { "field": "clip.duration", "operator": "equals", "value": 0 }, "message": "Clip \"{clip.name}\" on {clip.track} has zero duration." }, { "condition": { "field": "clip.duration", "operator": "lessThan", "value": 0 }, "message": "Clip \"{clip.name}\" on {clip.track} ends before it starts." } ], "data": { "durationTicks": "clip.duration" } ``` Since the first check that holds wins, put the most specific one first. ## One diagnostic per check: `matching` [#one-diagnostic-per-check-matching] With `"matching": "all"` at the top of the rule file, every check that holds reports, so one item can get several diagnostics. Use it when the checks describe independent problems, and make sure they exclude each other where they should. The built-in [Subframe video edits](/docs/rules/no-subframe-video-edits) rule does this: a clip is reported for its start, its end, or both. `"matching": "first"`, the default, is the behavior above. ## A check on another scope [#a-check-on-another-scope] A check may set its own `scope` when one rule reports on items of different kinds. Its condition, message and data then read the fields of that scope. The rule's shared `data` must be valid in the scope of every check. [Subframe video edits](/docs/rules/no-subframe-video-edits) has clip checks and sequence checks: the sequence's in and out points are reported apart from the clips. ## Where the diagnostic points [#where-the-diagnostic-points] Each scope gives its diagnostics a default position: the start of the clip or the marker. Tracks and the sequence have none. Set `location` to a number field, in ticks, to choose it. The built-in [Muted tracks](/docs/rules/no-muted-tracks) rule points at the track's first clip (simplified here): ```json { "condition": { "field": "track.muted", "operator": "equals", "value": true }, "message": "Track {track.ref} is muted.", "location": "track.firstClipStart" } ``` # Conditions (/docs/guides/conditions) Compare fields with values, combine conditions and handle unknown values. A condition decides whether an item is reported. It is a **comparison**, or a **combination** of conditions. ## Comparisons [#comparisons] A comparison names a [field](/docs/reference/fields), an [operator](/docs/reference/operators) and, for most operators, a value: ```json { "field": "clip.scale", "operator": "greaterThan", "value": 120 } ``` The value is a literal (a number, a string or a boolean), or a reference to another field, including an option: ```json { "field": "clip.scale", "operator": "greaterThan", "value": { "field": "options.max" } } ``` ```json { "field": "clip.end", "operator": "lessThanOrEqual", "value": { "field": "sequence.inPoint" } } ``` Types must match: `greaterThan` on a string field, or a string value for a number field, is rejected when the rule loads. Some operators take a particular value: ```json { "field": "clip.scale", "operator": "between", "value": [50, 150] } ``` ```json { "field": "clip.source.extension", "operator": "in", "value": ["mov", "mxf"] } ``` ```json { "field": "marker.name", "operator": "matches", "value": "^Chapter \\d+$" } ``` ```json { "field": "clip.source.mediaPath", "operator": "exists" } ``` `between` includes its bounds. `matches` takes a JavaScript regular expression, written as a JSON string (so `\d` is `"\\d"`), and matches anywhere unless anchored with `^` and `$`. `exists` takes no value. All operators are listed in [Operators](/docs/reference/operators). JSON has no infinity: write `"Infinity"` or `"-Infinity"` where a number is expected. A silenced audio clip is `{ "field": "clip.volume", "operator": "equals", "value": "-Infinity" }`. ## Combinations [#combinations] ```json { "all": [ /* conditions */ ] } { "any": [ /* conditions */ ] } { "not": /* condition */ } ``` * `all` holds when every condition in it holds (and). * `any` holds when at least one does (or). * `not` inverts one condition. They nest freely. Each combination object holds exactly one of these keys. ```json title="An enabled video clip scaled outside 50–150 %" { "all": [ { "field": "clip.trackType", "operator": "equals", "value": "video" }, { "field": "clip.disabled", "operator": "equals", "value": false }, { "any": [ { "field": "clip.scale", "operator": "lessThan", "value": 50 }, { "field": "clip.scale", "operator": "greaterThan", "value": 150 } ] } ] } ``` ## Unknown values [#unknown-values] Some fields can be **unknown**: their type ends in `?` in the [fields reference](/docs/reference/fields). An audio clip has no scale; a clip without source media has no media path. Every comparison is **false** when its field, or a field it refers to, is unknown, except `exists` and `notExists`. So `clip.scale lessThan 50` does not report audio clips, and neither does `clip.scale notEquals 100`. `not` turns a false comparison into true. `{ "not": { "field": "clip.scale", "operator": "equals", "value": 100 } }` **does** match every audio clip, since their scale is unknown. When a rule needs a known value, say so: * prefer positive comparisons, `lessThan min` or `greaterThan max`, over `not between`; * or add `{ "field": "clip.scale", "operator": "exists" }` to an `all`. ## Conditions shared by every check [#conditions-shared-by-every-check] There is no rule-wide filter. When a rule has [several checks](/docs/guides/checks) and each needs the same conditions (an enabled clip, a known value), repeat them in each check. # Custom rule files (/docs/guides/custom-rules) Where your rule files live, how PPROLint loads them, and how to share and override rules with files. Your own rules live in the **rules folder** of the PPROLint panel. Every `*.rule.json` file in it is loaded next to the built-in rules, without reinstalling anything. Rules made in the [rule editor](/docs/editor) are saved there too. ## Add a rule file [#add-a-rule-file] * **Open rules folder**, in the Rules settings, shows the folder in Finder or Explorer. Save a file there with any text editor, then click **Reload rules**. * **New rule > Import rules…** copies rule files you pick into the folder and reloads the rules. A `.json` file is renamed `.rule.json`; a file never overwrites another one, a number is added to its name instead. PPROLint reads the folder when the panel starts and when you click **Reload rules**. It does not watch the folder: after editing a file by hand, reload. See [The Rules settings](/docs/editor/rules-list). ## Override a built-in rule [#override-a-built-in-rule] A file with the id of a built-in rule **replaces** that rule. The Rules settings mark it *Modified built-in rule*; deleting the file brings the built-in rule back. Every [built-in rule page](/docs/rules) shows the complete file of the rule. Copying it into the rules folder under the same name and editing it is the same as [changing the rule in the editor](/docs/editor/saving#change-a-built-in-rule). If two of your files use the same id, the first one by file name is kept. ## Share rules [#share-rules] A rule depends on nothing but its file. To give your team the same checks, share the files: everyone imports them with **Import rules…** or drops them in their rules folder. A shared folder under version control works too. A rule file may have English texts only; the other languages fall back to them. To translate a rule, see [Messages](/docs/guides/messages#translations) or [Translations](/docs/editor/translations) in the editor. ## When a file has problems [#when-a-file-has-problems] A file that fails to load is listed above the rules with its problems, and it does not run at all. The other rules still run. Each problem names the file and the JSON path of the faulty value. See [Troubleshooting](/docs/guides/troubleshooting). # Data (/docs/guides/data) Attach the measured value and the thresholds to every diagnostic. `data` attaches named values to the diagnostics of a rule. The panel can show them, and tools reading the diagnostics can use them without parsing the message. Include the measured value and the thresholds that caused the report. An entry is a field path, or a constant `{ "literal": value }`: ```json "data": { "scalePercent": "clip.scale", "min": "options.min", "max": "options.max" } ``` A constant is useful to tell which check fired: ```json "data": { "reason": { "literal": "opacity" }, "value": "clip.opacity" } ``` `data` at the top of the rule file applies to every check. A check's own `data` is merged over it. The top-level entries must be valid in the scope of every check. # Labels (/docs/guides/labels) Word a field's value per language, or add an optional part to a sentence. A [placeholder](/docs/guides/messages#placeholders) shows a field's value as it is: `{marker.type}` shows `Comment`, in every language. When a value must be worded per language, declare a **label**: a field, and for each of its values a localized template. `{labels.}` in a message shows the template of the current value. ```json "labels": { "markerType": { "field": "marker.type", "values": { "Comment": { "en_US": "Comment", "fr_FR": "Commentaire" }, "Chapter": { "en_US": "Chapter", "fr_FR": "Chapitre" } } }, "marker": { "field": "marker.named", "values": { "true": { "en_US": "Marker \"{marker.name}\" ({labels.markerType})", "fr_FR": "Marque « {marker.name} » ({labels.markerType})" }, "false": { "en_US": "Unnamed marker ({labels.markerType})", "fr_FR": "Marque sans nom ({labels.markerType})" } } } }, "checks": [ { "condition": { "field": "marker.start", "operator": "greaterThan", "value": { "field": "sequence.end" } }, "message": "{labels.marker} at {marker.startTimecode} is after the end of the sequence." } ] ``` How a label is chosen: * Values are matched as text: a boolean field's values are `"true"` and `"false"`. * A locale with no template falls back to English, and a value with no entry shows the value itself. * Templates may use placeholders, other labels and [plural forms](/docs/guides/messages#plural-forms). A template may be empty. A label then adds an optional part to a sentence: the built-in [Required markers](/docs/rules/required-markers) rule builds `"Chapter" marker named "Start"` from four labels, each empty when the requirement does not set it. # Messages (/docs/guides/messages) Write messages that explain themselves, with placeholders, translations and plural forms. The message is the sentence the editor reads in the panel. A good message names the item and gives the measured value and the threshold, so it explains itself: ```json "message": "Clip \"{clip.name}\" on {clip.track} is scaled to {clip.scale} %, outside the allowed range ({options.min}–{options.max} %)." ``` ## Placeholders [#placeholders] `{field.path}` is replaced by the value of the field for the reported item. Any [field](/docs/reference/fields) of the check's scope works, and so do the rule's options. | Value | Shown as | | :------ | :------------------------------------------------------------------------------------------- | | string | as it is | | number | formatted for the panel's language, at most one decimal (`12.5`, `12,5` in French or German) | | boolean | `true` or `false` | | unknown | `?` | `{field.path:3}` shows at most three decimals. Every placeholder is checked when the rule loads: a misspelled field is an error, not an empty gap in the sentence. To word a value per language, such as a marker type or "named" versus "unnamed", use a [label](/docs/guides/labels). ## Translations [#translations] A plain string is the English message. To translate it, give an object keyed by locale. `en_US` is required; a missing locale falls back to English. ```json "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is disabled.", "fr_FR": "Élément « {clip.name} » sur {clip.track} est désactivé." } ``` `name` and `description` are translated the same way, with plain text only. The locales are Premiere's interface languages: | Locale | Language | | :------ | :------------------ | | `en_US` | English | | `de_DE` | German | | `es_ES` | Spanish | | `fr_FR` | French | | `it_IT` | Italian | | `ja_JP` | Japanese | | `ko_KR` | Korean | | `pt_BR` | Portuguese (Brazil) | | `ru_RU` | Russian | | `zh_CN` | Simplified Chinese | ## Plural forms [#plural-forms] When a number changes the grammar of the sentence, give the plural forms and the field that picks them in `count`. `other` is required; `one`, `few` and `many` are used where the language has them ([CLDR plural categories](https://cldr.unicode.org/index/cldr-spec/plural-rules)). ```json "message": { "en_US": { "count": "clip.durationFrames", "one": "Clip \"{clip.name}\" on {clip.track} is {clip.durationFrames} frame long (minimum {options.minFrames}).", "other": "Clip \"{clip.name}\" on {clip.track} is {clip.durationFrames} frames long (minimum {options.minFrames})." } } ``` Write the whole sentence in each form. Do not assemble it from translated fragments: word order changes between languages. # Options (/docs/guides/options) Make thresholds and lists configurable, and read them in conditions and messages. Options make one rule reusable with different values. Declare each in `options`, with a type, a default and a description: ```json "options": { "min": { "type": "number", "default": 25, "description": "Lowest allowed scale, in percent." }, "includeAudio": { "type": "boolean", "default": true, "description": "Also check audio clips." }, "allow": { "type": "string[]", "default": ["AE.ADBE Crop"], "description": "Match names allowed to repeat." } } ``` | Type | Holds | | :--------- | :------------------------------------------- | | `number` | a number | | `string` | a string | | `boolean` | `true` or `false` | | `number[]` | a list of numbers | | `string[]` | a list of strings | | `json` | any JSON value, read by computed scopes only | The default must have the declared type. Change an option's value by editing the rule (see [Custom rules](/docs/guides/custom-rules#override-a-built-in-rule)). ## Reading an option [#reading-an-option] An option is the field `options.`. Use it as a value in a condition, as a placeholder in a message, or in `data`: ```json { "condition": { "field": "clip.scale", "operator": "lessThan", "value": { "field": "options.min" } }, "message": "Clip \"{clip.name}\" is scaled to {clip.scale} %, below {options.min} %." } ``` ## List options [#list-options] A list option is the value of `in` or `notIn`, and nothing else: ```json { "field": "effect.matchName", "operator": "notIn", "value": { "field": "options.allow" } } ``` ## A switch for part of a rule [#a-switch-for-part-of-a-rule] A boolean option that turns a part of the rule on or off is an alternative in the condition. The built-in [Tiny clips](/docs/rules/no-tiny-clips) rule checks audio clips only when `includeAudio` is on: ```json { "any": [ { "field": "clip.trackType", "operator": "equals", "value": "video" }, { "field": "options.includeAudio", "operator": "equals", "value": true } ] } ``` Add it to the check's `all` with the other conditions. # Troubleshooting (/docs/guides/troubleshooting) The problems a rule file can have, and how to fix them. A rule file with any problem is **not loaded at all**: it never becomes a rule that silently reports nothing. The panel lists it above the rules, in the Rules settings, with each problem. The other rules still run. Every problem names the file and the JSON path of the faulty value, such as `checks[0].condition.field`. | Kind | Example | Fix | | :--------- | :----------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------- | | JSON | `Invalid JSON: Expected double-quoted property name in JSON at position 22` | The file is not valid JSON. Look for a trailing comma or a missing quote. | | Shape | `severity: Must be one of: "info", "warning", "error".` | A property has the wrong type, a value not allowed, or an unknown name. | | Definition | `checks[0].condition.field: Unknown field "clip.scal". Fields of scope "clip" start with "clip.", "track.", "sequence.", "options."` | A field, an operator on the wrong type, a placeholder or a regular expression is wrong. | | Duplicate | `id: Duplicate rule id "my-rule": already defined by …` | Two of your files use the same id. Rename one. | ## Common mistakes [#common-mistakes] * **An unknown property.** Every property name is checked, so a typo (`"serverity"`) is an error rather than a setting silently ignored. * **A field from another scope.** A `track` rule cannot read `clip.*`. The [fields reference](/docs/reference/fields) lists the scopes of each field. * **Comparing types that differ.** `greaterThan` needs a number field and a number value. Options compared with a field must have the field's type. * **A string where a number is expected.** `"value": "120"` is a string; write `120`. * **A backslash in a regular expression.** JSON strings escape backslashes: `\d` is written `"\\d"`. * **A rule that never reports.** Check for [unknown values](/docs/guides/conditions#unknown-values): a comparison on an unknown value is false. ## Using a built-in id [#using-a-built-in-id] A custom file reusing the id of a built-in rule is not an error: it [replaces the built-in rule](/docs/guides/custom-rules#override-a-built-in-rule). # Your first rule file (/docs/guides/your-first-rule-file) Write a rule as a JSON file in a text editor, load it in Premiere and make it configurable. In this tutorial you write a rule file that reports clips played faster than 200 %, load it in the PPROLint panel and see it report a clip of your sequence. You need Premiere Pro with PPROLint installed and a text editor. Prefer menus to JSON? The same rule is built in the rule editor in [Your first rule](/docs/editor/your-first-rule). ## 1. Create the file [#1-create-the-file] A rule file is named after its id: `.rule.json`. The id is lower-case words joined by hyphens, and it never changes once the rule is in use. Create `max-clip-speed.rule.json`: ```json title="max-clip-speed.rule.json" { "formatVersion": 1, "id": "max-clip-speed", "name": "Fast clips", "description": "Reports clips played faster than 200 %.", "category": "static", "scope": "clip", "severity": "warning", "checks": [ { "condition": { "field": "clip.speed", "operator": "greaterThan", "value": 2 }, "message": "Clip \"{clip.name}\" on {clip.track} plays at {clip.speed}× speed." } ] } ``` What each property does: * `formatVersion` is always `1`. * `name` and `description` are what the panel's Rules settings show. * `category` sorts the rule among the others. `static` means the rule inspects a fact of one item, without comparing it with other clips. * `scope: "clip"` runs the check once for every clip of the sequence. * `severity` is how serious a report is: `info`, `warning` or `error`. * `checks` holds the condition and the message. `clip.speed` is a [field](/docs/reference/fields): 1 is normal speed, so `greaterThan 2` means faster than 200 %. In the message, `{clip.name}`, `{clip.track}` and `{clip.speed}` are replaced by the clip's values. ## 2. Load it in Premiere [#2-load-it-in-premiere] 1. Open the PPROLint panel's settings and choose **Rules**. 2. Click **Open rules folder** and save `max-clip-speed.rule.json` in that folder. 3. Click **Reload rules**. *Fast clips* appears in the list, marked *Custom rule*. To try it, set a clip's speed to 300 % (**Clip > Speed/Duration**) and run a check. The panel reports: ```text Clip "Interview" on V1 plays at 3× speed. ``` If the rule does not appear, the Rules settings list the file with its problems above the rules. Each problem gives the JSON path of the faulty value; see [Troubleshooting](/docs/guides/troubleshooting). ## 3. Leave disabled clips alone [#3-leave-disabled-clips-alone] A disabled clip does not play, so its speed does not matter. Combine two conditions with `all`: every one must hold. ```json "condition": { "all": [ { "field": "clip.disabled", "operator": "equals", "value": false }, { "field": "clip.speed", "operator": "greaterThan", "value": 2 } ] } ``` ## 4. Make the limit an option [#4-make-the-limit-an-option] A fixed `2` suits one project, not every one. Declare an **option** with a default, and refer to it as `options.maxSpeed` in the condition and the message: ```json title="max-clip-speed.rule.json" { "formatVersion": 1, "id": "max-clip-speed", "name": "Fast clips", "description": "Reports clips played faster than the allowed speed.", "category": "static", "scope": "clip", "severity": "warning", "options": { "maxSpeed": { "type": "number", "default": 2, "description": "Highest allowed speed; 1 is 100 %." } }, "checks": [ { "condition": { "all": [ { "field": "clip.disabled", "operator": "equals", "value": false }, { "field": "clip.speed", "operator": "greaterThan", "value": { "field": "options.maxSpeed" } } ] }, "message": "Clip \"{clip.name}\" on {clip.track} plays at {clip.speed}× speed (maximum {options.maxSpeed}×)." } ], "data": { "speed": "clip.speed", "maxSpeed": "options.maxSpeed" } } ``` `{ "field": "options.maxSpeed" }` in place of a literal value compares the speed with the option. The `data` entries attach the measured speed and the limit to every report, so the panel can show them. Save the file and click **Reload rules** again. ## 5. Edit it in the panel [#5-edit-it-in-the-panel] Click the cogwheel next to *Fast clips* in the Rules settings. The [rule editor](/docs/editor) shows every property of your file: change `maxSpeed` to `1.5`, save, and the editor writes the file back. You can switch between the editor and your text editor at any time. ## What you learned [#what-you-learned] * A rule is one JSON file with a stable id, dropped in the rules folder. * The `scope` decides which items the check runs against; [fields](/docs/reference/fields) are the values of those items. * Conditions compare fields with values and combine with `all`, `any` and `not`. * Options make thresholds configurable; messages and `data` explain each report. Next, read [How rules work](/docs/how-rules-work), or browse the [built-in rules](/docs/rules) for complete examples. # How rules work (/docs/how-rules-work) The model behind every rule — snapshot, scope, items, checks, diagnostics. ## From a sequence to diagnostics [#from-a-sequence-to-diagnostics] When PPROLint checks a sequence, it first reads a **snapshot** of it from Premiere: its settings, its video and audio tracks, their clips with their effects, and the sequence markers. Rules only ever see this snapshot. They never read or change your project directly. Each rule then runs on its own: 1. Its **scope** turns the snapshot into **items**: every clip, every track, every marker, the sequence itself… 2. For each item, its **checks** are tried in order. A check is a **condition** and a **message**. 3. When a condition holds, the item gets a **diagnostic**: the rule's severity, the message with its placeholders filled in, the item it points at and a position in the timeline. ```text sequence ──snapshot──▶ items of the scope ──conditions──▶ diagnostics ``` A rule is deterministic: the same sequence, the same rule file and the same settings always give the same diagnostics. ## Scope and items [#scope-and-items] The scope decides what a check is evaluated against, and so which [fields](/docs/reference/fields) it can read: | Scope | One item per | Fields | | :--------- | :-------------------------------- | :-------------------------------------------- | | `sequence` | sequence (once) | `sequence.*` | | `track` | video track, then audio track | `track.*`, `sequence.*` | | `clip` | clip of every track, video first | `clip.*`, `track.*`, `sequence.*` | | `effect` | user-applied effect of every clip | `effect.*`, `clip.*`, `track.*`, `sequence.*` | | `marker` | sequence marker | `marker.*`, `sequence.*` | Every scope also reads the rule's options as `options.`. See [Scopes](/docs/reference/scopes) for what each diagnostic points at. Some built-in rules use a **computed scope**, such as `video-gaps` or `scale-outliers`: PPROLint computes the items for them (a gap between clips, a clip compared with its neighbours) and the rule file keeps the thresholds and messages. You can copy such a built-in rule and change its options, severity and wording; [Computed scopes](/docs/reference/computed-scopes) lists them all with their fields. ## Fields are typed and checked [#fields-are-typed-and-checked] A field is a named, typed value of the current item: `clip.scale` is a number, `clip.name` a string, `clip.disabled` a boolean. Every field path, operator and placeholder is checked when the rule loads. A typo, or a field the scope does not have, makes the file fail to load with a precise message; it never becomes a rule that silently reports nothing. Times are integer **ticks**, 254,016,000,000 per second, unless the field's name says frames, seconds or timecode: `clip.duration` is in ticks, `clip.durationFrames` in frames, `clip.startTimecode` a `HH:MM:SS:FF` string. ## Unknown values [#unknown-values] Some values can be missing from a timeline: an audio clip has no scale, a clip without source media has no media path, an in point may not be set. Such a value is **unknown**. The fields reference marks these fields with a `?` type. Unknown is never replaced by a default. A comparison on an unknown value is **false**, so a rule does not report what it cannot measure. See [Unknown values](/docs/guides/conditions#unknown-values) for the one trap this sets with `not`. ## One rule, one id [#one-rule-one-id] The id of a rule (`no-offline-media`) is how the panel, the settings and every diagnostic refer to it. It never changes once a rule is in use; its display `name` may. Two rules cannot share an id, except on purpose: a custom rule file with the id of a built-in rule **replaces** it. See [Custom rules](/docs/guides/custom-rules). ## What a rule file does not do [#what-a-rule-file-does-not-do] On purpose, the format has: * **No code.** A rule file combines fields and operators PPROLint knows. It cannot compute anything new, read files or reach the network. * **No arithmetic or string functions** in conditions. Values a rule needs are fields of their own, such as `clip.durationFrames` next to `clip.duration`. * **No changes to your project.** Rules report; you decide what to fix. * **One sequence at a time.** There are no checks across sequences. # Introduction (/docs) Install PPROLint and activate it, then learn how its rules work and how to write your own. PPROLint checks a Premiere Pro sequence against a set of **rules** and reports what it finds: an offline clip, a gap of black video, a clip scaled far beyond 100 %. Every rule, built-in or yours, is one small JSON file, a **rule file**. It names the items it looks at, the condition that makes an item a problem and the message to show. ```json title="no-offline-media.rule.json" { "formatVersion": 1, "id": "no-offline-media", "name": "Offline media", "description": "Reports clips whose source media is offline.", "category": "static", "scope": "clip", "severity": "error", "checks": [ { "condition": { "field": "clip.source.offline", "operator": "equals", "value": true }, "message": "Clip \"{clip.name}\" on {clip.track} uses offline media \"{clip.source.name}\"." } ] } ``` Read it as: *for every clip, when its source media is offline, report an error on that clip with this message.* You don't need to write this JSON yourself: the [rule editor](/docs/editor), in the panel's settings, builds rules with menus and fields, and writes the file for you. A rule file holds no code. PPROLint reads it with a fixed set of [fields](/docs/reference/fields) and [operators](/docs/reference/operators), so a rule file you download from someone else can only inspect your timeline, never change it or reach anything else. ## Where to start [#where-to-start] ## How these docs are organized [#how-these-docs-are-organized] * **Using PPROLint**: [installing](/docs/using/install), [activating and managing your license](/docs/using/license) and [uninstalling](/docs/using/uninstall). What changed in each version is in the [changelog](/docs/changelog). * **Rule editor**: [Your first rule](/docs/editor/your-first-rule) walks you through one rule in the editor, from an empty rule to a report in Premiere. The other pages cover each part of the editor, and [Recipes](/docs/editor/recipes) gives complete rules to build. * **Rule files**: the same rules written as JSON in a text editor, for sharing, version control or AI assistants. [Your first rule file](/docs/guides/your-first-rule-file) is the place to start. * [How rules work](/docs/how-rules-work) explains the model behind both. * **Reference** lists everything a rule file can contain: [properties](/docs/reference/rule-file), [scopes](/docs/reference/scopes), [fields](/docs/reference/fields) and [operators](/docs/reference/operators). * **Built-in rules** documents the [rules PPROLint ships with](/docs/rules). Their files are good starting points. Using an AI assistant to write rules? See [AI agents](/docs/ai-agents). A question these pages do not answer? Write to [support@pprolint.com](mailto:support@pprolint.com). # Computed scopes (/docs/reference/computed-scopes) Scopes whose items PPROLint computes: gaps, outliers, pairs of clips, requirements. {/* Generated by scripts/generate-docs.ts. Do not edit. */} Most rules run on the items of the sequence: its clips, tracks, effects or markers. Some checks need items that are not in the timeline as such: a gap between clips, a clip compared with the median of its track, an audio clip paired with the video clip it plays under, a requirement that is not met. PPROLint computes these items, and a rule names the computation as its **scope**: in the editor, the **Analyzers** group of the [Scope](/docs/editor/rule-section#scope) list; in a rule file, `"scope": ""`. What stays in the rule is what you decide: the thresholds, the condition, the message, the severity. The same computed scope can serve several rules. ## How to use one [#how-to-use-one] * **Start from a built-in rule.** Each computed scope below lists the built-in rules using it. Open one in the [editor](/docs/editor/saving#change-a-built-in-rule), or copy its file from its page, and change its thresholds and messages. * **Fields.** Each item has the scope's own fields, under its prefix (`gap.durationFrames`), and the fields of its base scope: a gap has the `sequence.*` fields, an outlier the `clip.*`, `track.*` and `sequence.*` fields of its clip. A field of type `json` can only be copied into [data](/docs/editor/data). * **Options.** A computed scope reads options of the rule, such as the minimum number of clips to compare. The rule must declare each with the type given below; picking the scope in the editor adds them with placeholder defaults. A `json` option holds a structured value, described in the option's description. * **Where reports point.** The computed scope chooses each item's target and position: the gap's start, the outlier clip. ## scale-outliers [#scale-outliers] Video clips compared with the median scale of their track or sequence. | Property | Value | | :------- | :-------------------------------------------------------------------------------------- | | Fields | `outlier.*`, plus the fields of the `clip` scope (see [Fields](/docs/reference/fields)) | | Used by | [Scale outliers](/docs/rules/scale-outlier) | | Field | Type | Description | | :---------------------------- | :------ | :------------------------------------------------------------------- | | `outlier.value` | number | The clip's value. | | `outlier.median` | number | Median of the population. | | `outlier.deviationPercent` | number | Deviation from the median, in percent of the median. Negative below. | | `outlier.absDeviationPercent` | number | Absolute deviation, in percent of the median. | | `outlier.populationKey` | string | "V1", "A2" for a track population, "sequence" otherwise. | | `outlier.populationSize` | number | Clips in the population. | | `outlier.populationIsTrack` | boolean | The population is one track (false: the whole sequence). | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :--------- | :------- | :------------------------------------------------------------------------------------------------------------------ | | `scope` | `string` | "track" compares clips with the other clips on the same track; "sequence" with every eligible clip of the sequence. | | `minClips` | `number` | Populations smaller than this are insufficient data and are not analysed. | ## speed-outliers [#speed-outliers] Clips compared with the median speed of their track or sequence. | Property | Value | | :------- | :-------------------------------------------------------------------------------------- | | Fields | `outlier.*`, plus the fields of the `clip` scope (see [Fields](/docs/reference/fields)) | | Used by | [Speed outliers](/docs/rules/speed-outlier) | | Field | Type | Description | | :---------------------------- | :------ | :------------------------------------------------------------------- | | `outlier.value` | number | The clip's value. | | `outlier.median` | number | Median of the population. | | `outlier.deviationPercent` | number | Deviation from the median, in percent of the median. Negative below. | | `outlier.absDeviationPercent` | number | Absolute deviation, in percent of the median. | | `outlier.populationKey` | string | "V1", "A2" for a track population, "sequence" otherwise. | | `outlier.populationSize` | number | Clips in the population. | | `outlier.populationIsTrack` | boolean | The population is one track (false: the whole sequence). | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :--------- | :------- | :------------------------------------------------------------------------------------------------------------------ | | `scope` | `string` | "track" compares clips with the other clips on the same track; "sequence" with every eligible clip of the sequence. | | `minClips` | `number` | Populations smaller than this are insufficient data and are not analysed. | ## audio-level-outliers [#audio-level-outliers] Audio clips compared with the median volume setting of their track or sequence. | Property | Value | | :------- | :-------------------------------------------------------------------------------------- | | Fields | `outlier.*`, plus the fields of the `clip` scope (see [Fields](/docs/reference/fields)) | | Used by | [Audio level outliers](/docs/rules/audio-level-outlier) | | Field | Type | Description | | :-------------------------- | :------ | :------------------------------------------------------- | | `outlier.value` | number | Volume setting in dB. | | `outlier.median` | number | Median volume of the population, in dB. | | `outlier.deviation` | number | Difference from the median in dB. Negative when quieter. | | `outlier.absDeviation` | number | Absolute difference from the median in dB. | | `outlier.populationKey` | string | "V1", "A2" for a track population, "sequence" otherwise. | | `outlier.populationSize` | number | Clips in the population. | | `outlier.populationIsTrack` | boolean | The population is one track (false: the whole sequence). | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :--------- | :------- | :------------------------------------------------------------------------------------------------------------------ | | `scope` | `string` | "track" compares clips with the other clips on the same track; "sequence" with every eligible clip of the sequence. | | `minClips` | `number` | Populations smaller than this are insufficient data and are not analysed. | ## duration-outliers [#duration-outliers] Clips compared with the typical duration of their track or sequence. | Property | Value | | :------- | :-------------------------------------------------------------------------------------- | | Fields | `outlier.*`, plus the fields of the `clip` scope (see [Fields](/docs/reference/fields)) | | Used by | [Duration outliers](/docs/rules/duration-outlier) | | Field | Type | Description | | :-------------------------- | :------ | :----------------------------------------------------------------------------- | | `outlier.z` | number | Modified z-score of the log duration. Negative when shorter. | | `outlier.absZ` | number | Absolute modified z-score. | | `outlier.durationTicks` | number | Clip duration in ticks. | | `outlier.durationSeconds` | number | Clip duration in seconds. | | `outlier.typicalTicks` | number | Typical duration of the population (exp of the median log duration), in ticks. | | `outlier.typicalSeconds` | number | Typical duration in seconds. | | `outlier.populationKey` | string | "V1", "A2" for a track population, "sequence" otherwise. | | `outlier.populationSize` | number | Clips in the population. | | `outlier.populationIsTrack` | boolean | The population is one track (false: the whole sequence). | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :--------- | :------- | :------------------------------------------------------------------------------------------------------------------ | | `scope` | `string` | "track" compares clips with the other clips on the same track; "sequence" with every eligible clip of the sequence. | | `minClips` | `number` | Populations smaller than this are insufficient data and are not analysed. | ## missing-effects [#missing-effects] Clips lacking an effect that other clips of their track or sequence carry. | Property | Value | | :------- | :-------------------------------------------------------------------------------------- | | Fields | `missing.*`, plus the fields of the `clip` scope (see [Fields](/docs/reference/fields)) | | Used by | [Inconsistent effects](/docs/rules/inconsistent-effects) | | Field | Type | Description | | :-------------------------- | :------ | :------------------------------------------------------- | | `missing.matchName` | string | Match name of the effect the clip lacks. | | `missing.displayName` | string | Display name of that effect, from a clip that has it. | | `missing.withEffect` | number | Clips of the population that carry the effect. | | `missing.prevalence` | number | withEffect / populationSize. | | `missing.populationKey` | string | "V1", "A2" for a track population, "sequence" otherwise. | | `missing.populationSize` | number | Clips in the population. | | `missing.populationIsTrack` | boolean | The population is one track (false: the whole sequence). | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :--------- | :------- | :------------------------------------------------------------------------------------------------------------------ | | `scope` | `string` | "track" compares clips with the other clips on the same track; "sequence" with every eligible clip of the sequence. | | `minClips` | `number` | Populations smaller than this are insufficient data and are not analysed. | ## video-gaps [#video-gaps] Ranges of the work area where no video clip is visible. | Property | Value | | :------- | :-------------------------------------------------------------------------------------- | | Fields | `gap.*`, plus the fields of the `sequence` scope (see [Fields](/docs/reference/fields)) | | Used by | [Video gaps](/docs/rules/no-video-gaps) | | Field | Type | Description | | :-------------------------- | :------ | :--------------------------------------------------------------- | | `gap.start` | number | Gap start (ticks). | | `gap.end` | number | Gap end (ticks). | | `gap.startTimecode` | string | Gap start as timecode. | | `gap.endTimecode` | string | Gap end as timecode. | | `gap.durationTicks` | number | Duration in ticks. | | `gap.durationFrames` | number | Duration in whole frames. | | `gap.durationFramesRounded` | number | Duration in frames, one decimal, for messages. | | `gap.durationSeconds` | number | Duration in seconds. | | `gap.durationIsSeconds` | boolean | At least one second long: word it in seconds rather than frames. | | `gap.kind` | string | "leading" (touches the work area start), "inner" or "trailing". | | `gap.hasBefore` | boolean | A clip ends the coverage before the gap. | | `gap.beforeName` | string | Name of the clip before the gap. | | `gap.beforeTrack` | string | Track of the clip before the gap: "V1", "A2". | | `gap.hasAfter` | boolean | A clip starts the coverage after the gap. | | `gap.afterName` | string | Name of the clip after the gap. | | `gap.afterTrack` | string | Track of the clip after the gap: "V1", "A2". | Reads no options. ## audio-gaps [#audio-gaps] Ranges of the work area where no audio clip is audible. | Property | Value | | :------- | :-------------------------------------------------------------------------------------- | | Fields | `gap.*`, plus the fields of the `sequence` scope (see [Fields](/docs/reference/fields)) | | Used by | [Audio gaps](/docs/rules/no-audio-gaps) | | Field | Type | Description | | :-------------------------- | :------ | :--------------------------------------------------------------- | | `gap.start` | number | Gap start (ticks). | | `gap.end` | number | Gap end (ticks). | | `gap.startTimecode` | string | Gap start as timecode. | | `gap.endTimecode` | string | Gap end as timecode. | | `gap.durationTicks` | number | Duration in ticks. | | `gap.durationFrames` | number | Duration in whole frames. | | `gap.durationFramesRounded` | number | Duration in frames, one decimal, for messages. | | `gap.durationSeconds` | number | Duration in seconds. | | `gap.durationIsSeconds` | boolean | At least one second long: word it in seconds rather than frames. | | `gap.kind` | string | "leading" (touches the work area start), "inner" or "trailing". | | `gap.hasBefore` | boolean | A clip ends the coverage before the gap. | | `gap.beforeName` | string | Name of the clip before the gap. | | `gap.beforeTrack` | string | Track of the clip before the gap: "V1", "A2". | | `gap.hasAfter` | boolean | A clip starts the coverage after the gap. | | `gap.afterName` | string | Name of the clip after the gap. | | `gap.afterTrack` | string | Track of the clip after the gap: "V1", "A2". | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :---------- | :------- | :------------------------------------------------------------------- | | `silenceDb` | `number` | Clips whose static volume is at or below this do not count as audio. | ## av-sync-pairs [#av-sync-pairs] Audio clips paired with the overlapping video clip of the same source, with their drift. | Property | Value | | :------- | :----------------------------------------------------------------------------------- | | Fields | `pair.*`, plus the fields of the `clip` scope (see [Fields](/docs/reference/fields)) | | Used by | [Out-of-sync audio and video](/docs/rules/no-out-of-sync-av) | | Field | Type | Description | | :--------------------------- | :----- | :----------------------------------------------------------------------------------- | | `pair.driftTicks` | number | Audio offset from the video's source mapping, in ticks. Positive: the audio is late. | | `pair.driftFrames` | number | Drift in frames, signed. | | `pair.absDriftFrames` | number | Absolute drift in frames. | | `pair.absDriftFramesRounded` | number | Absolute drift in frames, one decimal, for messages. | | `pair.videoName` | string | Name of the video clip. | | `pair.videoTrack` | string | Track of the video clip: "V1", "A2". | | `pair.projectItemId` | string | Shared project item id. | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :------ | :--------- | :------------------------------- | | `kinds` | `string[]` | Source kinds compared. | ## adjustment-layer-edges [#adjustment-layer-edges] Adjustment layer edges inside a clip below, with the offset to the clip's edge. | Property | Value | | :------- | :------------------------------------------------------------------------------------ | | Fields | `edge.*`, plus the fields of the `clip` scope (see [Fields](/docs/reference/fields)) | | Used by | [Partial adjustment layer coverage](/docs/rules/no-partial-adjustment-layer-coverage) | | Field | Type | Description | | :------------------------- | :----- | :------------------------------------------------------ | | `edge.side` | string | "start" or "end" of the adjustment layer. | | `edge.time` | number | Time of the edge (ticks). | | `edge.timecode` | string | Time of the edge as timecode. | | `edge.offsetTicks` | number | Distance to the clip's own edge on that side, in ticks. | | `edge.offsetFrames` | number | Offset in frames. | | `edge.offsetFramesRounded` | number | Offset in frames, one decimal, for messages. | | `edge.clipName` | string | Name of the clip below. | | `edge.clipTrack` | string | Track of the clip below: "V1", "A2". | Reads no options. ## repeated-footage-pairs [#repeated-footage-pairs] Clips reusing a source range already used by an earlier clip of the same source. | Property | Value | | :------- | :------------------------------------------------------------------------------------ | | Fields | `reuse.*`, plus the fields of the `clip` scope (see [Fields](/docs/reference/fields)) | | Used by | [Repeated footage](/docs/rules/no-repeated-footage) | | Field | Type | Description | | :--------------------------- | :------ | :--------------------------------------------------------------- | | `reuse.overlapTicks` | number | Duration in ticks. | | `reuse.overlapFrames` | number | Duration in whole frames. | | `reuse.overlapFramesRounded` | number | Duration in frames, one decimal, for messages. | | `reuse.overlapSeconds` | number | Duration in seconds. | | `reuse.overlapIsSeconds` | boolean | At least one second long: word it in seconds rather than frames. | | `reuse.earlierName` | string | Name of the earlier clip. | | `reuse.earlierTrack` | string | Track of the earlier clip: "V1", "A2". | | `reuse.earlierStart` | number | Start of the earlier clip (ticks). | | `reuse.earlierTimecode` | string | Start of the earlier clip as timecode. | | `reuse.projectItemId` | string | Shared project item id. | Reads no options. ## required-effects [#required-effects] Clips missing an effect the configuration requires on their track. | Property | Value | | :------- | :------------------------------------------------------------------------------------------ | | Fields | `requirement.*`, plus the fields of the `clip` scope (see [Fields](/docs/reference/fields)) | | Used by | [Required effects](/docs/rules/required-effects) | | Field | Type | Description | | :------------------------ | :------ | :------------------------------------------------------------------------ | | `requirement.matchName` | string | Required match name. | | `requirement.displayName` | string | Display name of the effect, from a clip that has it, else the match name. | | `requirement.explanation` | string | The requirement's message with a leading space, or empty. | | `requirement.tracks` | json | The requirement's track references. | | `requirement.trackType` | string? | The requirement's track type. | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :------------ | :--------- | :---------------------------------------------------------------------------------------------------------------------------- | | `effects` | `json` | Requirements: \{ "matchName", "tracks"?: \["V1"], "trackType"?: "video" \| "audio", "message"? }. Empty: nothing is required. | | `ignoreKinds` | `string[]` | Source kinds exempt from requirements. | ## restricted-effects [#restricted-effects] Clips using an effect the configuration forbids. | Property | Value | | :------- | :----------------------------------------------------------------------------------------- | | Fields | `restricted.*`, plus the fields of the `clip` scope (see [Fields](/docs/reference/fields)) | | Used by | [Restricted effects](/docs/rules/no-restricted-effects) | | Field | Type | Description | | :----------------------- | :----- | :-------------------------------------------------- | | `restricted.matchName` | string | Match name of the restricted effect. | | `restricted.displayName` | string | Display name of the effect on the clip. | | `restricted.explanation` | string | The entry's message with a leading space, or empty. | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :-------- | :----- | :--------------------------------------------------------------------------------------------------- | | `effects` | `json` | Match names, or \{ "matchName", "message"? } to append an explanation. Empty: nothing is restricted. | ## required-markers [#required-markers] Configured marker requirements the sequence does not meet. | Property | Value | | :------- | :---------------------------------------------------------------------------------------------- | | Fields | `requirement.*`, plus the fields of the `sequence` scope (see [Fields](/docs/reference/fields)) | | Used by | [Required markers](/docs/rules/required-markers) | | Field | Type | Description | | :------------------------ | :------ | :--------------------------------------------------------------------------- | | `requirement.found` | number | Matching markers found. | | `requirement.minCount` | number | Markers required. | | `requirement.pluralCount` | number | `found`, or 1 when none was found, so the requirement reads in the singular. | | `requirement.hasType` | boolean | The requirement names a marker type. | | `requirement.type` | string? | Required marker type. | | `requirement.hasName` | boolean | The requirement names a marker name. | | `requirement.name` | string? | Required name. | | `requirement.hasPattern` | boolean | The requirement has a name pattern. | | `requirement.namePattern` | string? | Required name pattern (regular expression source). | | `requirement.hasColor` | boolean | The requirement has a color index. | | `requirement.colorIndex` | number? | Required color index. | | `requirement.explanation` | string | The requirement's message with a leading space, or empty. | | `requirement.requirement` | json | The requirement as configured. | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :-------- | :----- | :------------------------------------------------------------------------------------------------------------------------------------------------------ | | `markers` | `json` | Requirements: \{ "type"?, "name"?, "namePattern"?, "colorIndex"?, "minCount"? (1), "message"? }; criteria combine with AND. Empty: nothing is required. | ## required-tracks [#required-tracks] Ways the track layout misses the configured requirements. | Property | Value | | :------- | :-------------------------------------------------------------------------------------------- | | Fields | `violation.*`, plus the fields of the `sequence` scope (see [Fields](/docs/reference/fields)) | | Used by | [Required tracks](/docs/rules/required-tracks) | | Field | Type | Description | | :---------------------- | :------ | :------------------------------------------------------------------------------------------------------ | | `violation.kind` | string | "minVideo", "minAudio", "missingVideoName", "missingAudioName", "missingTrack", "wrongName" or "empty". | | `violation.count` | number? | Tracks found (count requirements). | | `violation.min` | number? | Tracks required (count requirements). | | `violation.name` | string? | Required name, or the name found for a wrong name. | | `violation.expected` | string? | Expected name (wrong name). | | `violation.trackRef` | string? | Track concerned: "V1", "A2". | | `violation.trackName` | string? | Name of the track concerned. | | `violation.requirement` | json | The requirement as configured. | | `violation.found` | json | What was found, when it is not the requirement itself. | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :---------------- | :--------- | :----------------------------------------------------------------- | | `minVideoTracks` | `number` | Minimum number of video tracks. 0: not checked. | | `minAudioTracks` | `number` | Minimum number of audio tracks. 0: not checked. | | `videoTrackNames` | `string[]` | Names that must exist among video tracks. | | `audioTrackNames` | `string[]` | Names that must exist among audio tracks. | | `tracks` | `json` | Per-position requirements: \{ "ref": "V1", "name"?, "nonEmpty"? }. | ## sequence-settings [#sequence-settings] Sequence settings (frame rate, frame size) outside the allowed values. | Property | Value | | :------- | :------------------------------------------------------------------------------------------ | | Fields | `setting.*`, plus the fields of the `sequence` scope (see [Fields](/docs/reference/fields)) | | Used by | [Sequence settings](/docs/rules/sequence-settings) | | Field | Type | Description | | :----------------------- | :----- | :---------------------------------------- | | `setting.kind` | string | "frameRate" or "frameSize". | | `setting.frameRate` | number | The sequence frame rate. | | `setting.frameSizeText` | string | The sequence frame size: "1920×1080". | | `setting.frameSizesText` | string | The allowed frame sizes, comma separated. | | `setting.frameRates` | json | Allowed frame rates. | | `setting.frameSize` | json | The sequence frame size. | | `setting.frameSizes` | json | Allowed frame sizes. | Options it reads, which the rule must declare with these types: | Option | Type | Description in the built-in rule | | :----------- | :--------- | :---------------------------------------------------------------------------------------- | | `frameRates` | `number[]` | Allowed frame rates. 23.976, 29.97… stand for 24000/1001, 30000/1001… Empty: not checked. | | `frameSizes` | `json` | Allowed frame sizes: \{ "width", "height" }. Empty: not checked. | # Fields (/docs/reference/fields) Every value a rule can read, by scope. {/* Generated by scripts/generate-docs.ts. Do not edit. */} Fields are the only data a rule can see. A condition, a message placeholder or a `data` entry names a field by its path, and the path is checked when the rule loads: a field that its scope does not expose is an error. Times are integer **ticks** (254,016,000,000 per second) unless the name says frames, seconds or timecode. A type ending in `?` means the value can be **unknown**: the timeline did not have it (no source media, the scale of an audio clip, an in point that is not set). See [Unknown values](/docs/guides/conditions#unknown-values). Besides these, every rule reads its own options as `options.` (see [Options](/docs/guides/options)). ## sequence [#sequence] Available in every scope. | Field | Type | Description | | :----------------------------- | :------ | :--------------------------------------------------------------------------------------------------- | | `sequence.id` | string | Sequence GUID. | | `sequence.name` | string | Sequence name. | | `sequence.fps` | number | Frame rate (frames per second). | | `sequence.frameDuration` | number | Ticks per frame. | | `sequence.frameWidth` | number | Frame width in pixels. | | `sequence.frameHeight` | number | Frame height in pixels. | | `sequence.end` | number | End of the last clip (ticks). | | `sequence.endTimecode` | string | End of the last clip as timecode. | | `sequence.durationSeconds` | number | End of the last clip in seconds. | | `sequence.inPoint` | number? | Sequence in point (ticks), unknown when not set. | | `sequence.outPoint` | number? | Sequence out point (ticks), unknown when not set. | | `sequence.inPointTimecode` | string? | Sequence in point as timecode, unknown when not set. | | `sequence.outPointTimecode` | string? | Sequence out point as timecode, unknown when not set. | | `sequence.inPointFrameOffset` | number? | Ticks between the in point and the frame boundary before it (0 = on a frame); unknown when not set. | | `sequence.outPointFrameOffset` | number? | Ticks between the out point and the frame boundary before it (0 = on a frame); unknown when not set. | | `sequence.videoTrackCount` | number | Number of video tracks. | | `sequence.audioTrackCount` | number | Number of audio tracks. | | `sequence.clipCount` | number | Number of clips on all tracks. | | `sequence.markerCount` | number | Number of sequence markers. | ## track [#track] Available in the `track`, `clip`, `effect` scopes. | Field | Type | Description | | :----------------------- | :------ | :------------------------------------------------------------------ | | `track.ref` | string | Track as shown in Premiere: "V1", "A2". | | `track.type` | string | "video" or "audio". | | `track.index` | number | Zero-based index among tracks of its type. | | `track.name` | string | Track name. | | `track.muted` | boolean | Track is muted. | | `track.clipCount` | number | Number of clips on the track. | | `track.audibleClipCount` | number | Clips that would play: enabled, and for audio not silenced (-∞ dB). | | `track.firstClipStart` | number? | Start of the first clip (ticks); unknown on an empty track. | | `track.beyondLastUsed` | boolean | No track of the same type with a higher index carries clips. | ## clip [#clip] Available in the `clip`, `effect` scopes. | Field | Type | Description | | :-------------------------- | :------- | :------------------------------------------------------------------------------------------------------ | | `clip.id` | string | Clip id: "V1:\". | | `clip.name` | string | Clip name. | | `clip.track` | string | Clip track as shown in Premiere: "V1", "A2". | | `clip.trackType` | string | "video" or "audio". | | `clip.trackIndex` | number | Zero-based index of the clip's track. | | `clip.start` | number | Start in sequence time (ticks). | | `clip.end` | number | End in sequence time (ticks). | | `clip.startFrameOffset` | number | Ticks between the start and the frame boundary before it (0 = on a frame). | | `clip.endFrameOffset` | number | Ticks between the end and the frame boundary before it (0 = on a frame). | | `clip.startTimecode` | string | Start as timecode. | | `clip.endTimecode` | string | End as timecode. | | `clip.duration` | number | Duration in ticks (end - start). | | `clip.durationFrames` | number | Duration in whole frames of the sequence. | | `clip.durationSeconds` | number | Duration in seconds. | | `clip.inPoint` | number | Source in point (ticks). | | `clip.outPoint` | number | Source out point (ticks). | | `clip.speed` | number | Playback speed, 1 = 100 %. | | `clip.reversed` | boolean | Plays in reverse. | | `clip.disabled` | boolean | Clip is disabled. | | `clip.effectCount` | number | Number of user-applied effects. | | `clip.source.projectItemId` | string? | Project item id; unknown without a source. | | `clip.source.name` | string? | Project item name; unknown without a source. | | `clip.source.kind` | string? | "media", "sequence", "multicam" or "merged"; unknown without a source. | | `clip.source.mediaPath` | string? | Media file path; unknown when empty or without a source. | | `clip.source.offline` | boolean? | Source media is offline; unknown without a source. | | `clip.source.extension` | string? | Lower-case extension of the media path without the dot ("mov"); unknown without a path or an extension. | | `clip.adjustmentLayer` | boolean | Clip is an adjustment layer (false for audio clips). | | `clip.scale` | number? | Motion scale in percent at clip start (video, uniform scale only). | | `clip.scaleAnimated` | boolean? | Scale is keyframed (video). | | `clip.rotation` | number? | Rotation in degrees at clip start (video). | | `clip.rotationAnimated` | boolean? | Rotation is keyframed (video). | | `clip.opacity` | number? | Opacity in percent at clip start (video). | | `clip.opacityAnimated` | boolean? | Opacity is keyframed (video). | | `clip.volume` | number? | Volume setting in dB at clip start (audio). | | `clip.volumeAnimated` | boolean? | Volume is keyframed (audio). | ## effect [#effect] Available in the `effect` scope. | Field | Type | Description | | :------------------- | :------ | :--------------------------------------------------------------- | | `effect.index` | number | Position in the clip's effect chain, from 0. | | `effect.matchName` | string | Premiere match name, stable across languages: "AE.ADBE Lumetri". | | `effect.displayName` | string | Name shown in Premiere, in its UI language. | | `effect.count` | number | Effects with this match name on the clip. | | `effect.firstOfKind` | boolean | No earlier effect of the clip has this match name. | ## marker [#marker] Available in the `marker` scope. | Field | Type | Description | | :--------------------- | :------ | :---------------------------------------- | | `marker.id` | string | Marker id. | | `marker.name` | string | Marker name. | | `marker.named` | boolean | The name is not blank. | | `marker.type` | string | "Comment", "Chapter", "WebLink", … | | `marker.comments` | string | Marker comment. | | `marker.colorIndex` | number | Color index. | | `marker.start` | number | Start in sequence time (ticks). | | `marker.startTimecode` | string | Start as timecode. | | `marker.duration` | number | Duration in ticks (0 for a point marker). | # Operators (/docs/reference/operators) Every comparison operator, the types it accepts and when it holds. A comparison is `{ "field": , "operator": , "value": }`. Types are checked when the rule loads. | Operator | Field type | Value | Holds when | | :------------------- | :--------------- | :---------------------------------------- | :------------------------------------------- | | `equals` | any | same type as the field | the values are equal | | `notEquals` | any | same type as the field | the values differ | | `greaterThan` | number | number | `field > value` | | `greaterThanOrEqual` | number | number | `field ≥ value` | | `lessThan` | number | number | `field < value` | | `lessThanOrEqual` | number | number | `field ≤ value` | | `between` | number | `[min, max]` | `min ≤ field ≤ max`, bounds included | | `in` | number or string | a list, or a list option | the field is one of the list | | `notIn` | number or string | a list, or a list option | the field is none of the list | | `contains` | string | string | the field contains the value, case-sensitive | | `notContains` | string | string | the field does not contain the value | | `matches` | string | a regular expression, as a literal string | the pattern matches somewhere in the field | | `exists` | any | none | the field is known | | `notExists` | any | none | the field is unknown | Every operator except `exists` and `notExists` is **false when the field or the value is unknown**. See [Unknown values](/docs/guides/conditions#unknown-values). ## Values [#values] * A **literal**: `120`, `"video"`, `true`, a list `["mov", "mxf"]` for `in` / `notIn`, a pair `[50, 150]` for `between`. * A **field reference**: `{ "field": "options.max" }` or `{ "field": "sequence.inPoint" }`, compared with the field's value for the same item. * **Infinity**: JSON has none; write the strings `"Infinity"` and `"-Infinity"` where a number is expected. ## Regular expressions [#regular-expressions] `matches` takes a [JavaScript regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions) with the `u` flag, as a literal string; it cannot refer to a field. It matches anywhere in the value: anchor it with `^` and `$` to match the whole value. Backslashes are doubled in JSON: `"^Chapter \\d+$"`. # Rule file (/docs/reference/rule-file) Every property of a rule file. A rule file is a JSON object saved as `.rule.json`. Unknown properties are errors, so a typo never silently disables part of a rule. ## Rule [#rule] | Property | Required | Type | Meaning | | :-------------- | :------- | :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------- | | `formatVersion` | yes | `1` | Version of the format. Always `1`. | | `id` | yes | string | Stable identifier: lower-case letters and digits in words joined by hyphens (`^[a-z0-9]+(-[a-z0-9]+)*$`). Never changes once the rule is in use. | | `name` | yes | [text](#texts) | Short title, shown in the Rules settings. | | `description` | yes | [text](#texts) | One sentence: what the rule reports. | | `category` | yes | string | `static`, `local-consistency`, `global-consistency` or `project`. See [Categories](#categories). | | `scope` | yes | string | What the checks run against: `sequence`, `track`, `clip`, `effect` or `marker`. See [Scopes](/docs/reference/scopes). | | `severity` | yes | string | `info`, `warning` or `error`. | | `options` | no | object | Configurable values, by name. See [Option](#option). | | `checks` | yes | array | At least one [check](#check). | | `matching` | no | string | `first` (default): an item gets the diagnostic of the first check that holds. `all`: one diagnostic per check that holds. | | `labels` | no | object | Wording chosen by a field's value, by name. See [Label](#label). | | `data` | no | object | [Data](#data-entry) attached to every diagnostic of the rule. | ## Check [#check] | Property | Required | Type | Meaning | | :---------- | :------- | :---------------------- | :--------------------------------------------------- | | `condition` | yes | [condition](#condition) | When to report. | | `message` | yes | [message](#messages) | What to say. | | `data` | no | object | [Data](#data-entry) merged over the rule's `data`. | | `scope` | no | string | Runs this check on another scope than the rule's. | | `location` | no | field path | A number field, in ticks: the diagnostic's position. | Guide: [Checks](/docs/guides/checks). ## Condition [#condition] One of: | Shape | Holds when | | :---------------------------------- | :------------------------------------------------------------------ | | `{ "field", "operator", "value"? }` | The comparison is true. See [Operators](/docs/reference/operators). | | `{ "all": [condition, …] }` | Every condition holds. | | `{ "any": [condition, …] }` | At least one condition holds. | | `{ "not": condition }` | The condition does not hold. | A `value` is a literal (number, string, boolean, or a list for `in` / `notIn`, a pair for `between`) or a field reference `{ "field": "options.max" }`. Guide: [Conditions](/docs/guides/conditions). ## Option [#option] | Property | Required | Meaning | | :------------ | :------- | :--------------------------------------------------------------- | | `type` | yes | `number`, `string`, `boolean`, `number[]`, `string[]` or `json`. | | `default` | yes | A value of that type. | | `description` | no | What the option changes. | Read as the field `options.`. Guide: [Options](/docs/guides/options). ## Label [#label] | Property | Required | Meaning | | :------- | :------- | :------------------------------------------------------------------------------------- | | `field` | yes | The field whose value picks the wording. | | `values` | yes | A [message](#messages) per value, keyed by the value as text (`"true"` for a boolean). | Used as `{labels.}` in messages. Guide: [Labels](/docs/guides/labels). ## Data entry [#data-entry] A field path (`"clip.scale"`), or a constant `{ "literal": value }`. Guide: [Data](/docs/guides/data). ## Texts [#texts] `name` and `description` are a string (English), or an object keyed by [locale](/docs/guides/messages#translations) where `en_US` is required. ## Messages [#messages] A message is a template with `{field.path}` placeholders, as a string (English) or an object keyed by locale with `en_US` required. Each template is a string, or plural forms: `{ "count": "", "one"?, "few"?, "many"?, "other" }`. Guide: [Messages](/docs/guides/messages). ## Categories [#categories] | Category | The rule… | | :------------------- | :-------------------------------------------------------------------------------------------------- | | `static` | inspects facts of one item: an offline clip, a disabled clip, a gap. | | `local-consistency` | compares a clip with nearby clips. | | `global-consistency` | compares a clip with a broader population of the sequence. | | `project` | checks requirements for the whole sequence: required tracks, markers or effects, sequence settings. | Rules are listed by category, then id. # Scopes (/docs/reference/scopes) The items each scope produces, and what their diagnostics point at. The `scope` of a rule, or of one of its checks, decides the items the condition runs against, the [fields](/docs/reference/fields) it can read and where each diagnostic points. | `scope` | Evaluated against | Diagnostic points at | Timeline position | | :--------- | :------------------------------------------------------ | :------------------- | :----------------- | | `sequence` | the sequence, once | the sequence | none | | `track` | every video track, then every audio track | the track | none | | `clip` | every clip of every track, video tracks first | the clip | the clip's start | | `effect` | every user-applied effect of every clip, in chain order | the effect's clip | the clip's start | | `marker` | every sequence marker | the marker | the marker's start | A check's `location` replaces the timeline position: see [Checks](/docs/guides/checks#where-the-diagnostic-points). ## Fields by scope [#fields-by-scope] | `scope` | Field prefixes | | :--------- | :---------------------------------------------------- | | `sequence` | `sequence.`, `options.` | | `track` | `track.`, `sequence.`, `options.` | | `clip` | `clip.`, `track.`, `sequence.`, `options.` | | `effect` | `effect.`, `clip.`, `track.`, `sequence.`, `options.` | | `marker` | `marker.`, `sequence.`, `options.` | In the `clip` and `effect` scopes, `track.*` is the clip's own track. ## Computed scopes [#computed-scopes] Some [built-in rules](/docs/rules) name a computed scope instead, such as `video-gaps` or `scale-outliers`. PPROLint computes their items: a gap between clips, a clip compared with the other clips of its track or sequence. A custom rule may use them too. [Computed scopes](/docs/reference/computed-scopes) lists each with its fields, the options it reads and the built-in rules that use it. # Audio level outliers (/docs/rules/audio-level-outlier) Reports audio clips whose volume setting is unusual compared with other clips. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :---------------------------------------------------------------------------------------------- | | Id | `audio-level-outlier` | | Category | Local consistency | | Default severity | info | | Scope | [`audio-level-outliers`](/docs/reference/computed-scopes#audio-level-outliers) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :--------------- | :------- | :-------- | :------------------------------------------------------------------------------------------------------------------ | | `maxDeviationDb` | `number` | `6` | Report clips whose volume differs from the median by more than this many dB. Equal is not reported. | | `minClips` | `number` | `4` | Populations smaller than this are insufficient data and are not analysed. | | `scope` | `string` | `"track"` | "track" compares clips with the other clips on the same track; "sequence" with every eligible clip of the sequence. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `audio-level-outlier.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="audio-level-outlier.rule.json" { "formatVersion": 1, "id": "audio-level-outlier", "name": { "en_US": "Audio level outliers", "de_DE": "Abweichende Audiopegel", "es_ES": "Niveles de audio atípicos", "fr_FR": "Niveaux audio atypiques", "it_IT": "Livelli audio anomali", "ja_JP": "オーディオレベルの外れ値", "ko_KR": "오디오 레벨 이상값", "pt_BR": "Níveis de áudio atípicos", "ru_RU": "Нетипичная громкость", "zh_CN": "音频电平异常" }, "description": { "en_US": "Reports audio clips whose volume setting is unusual compared with other clips.", "de_DE": "Meldet Audioclips, deren Lautstärke im Vergleich zu anderen Clips ungewöhnlich ist.", "es_ES": "Detecta clips de audio cuyo ajuste de volumen es inusual en comparación con otros clips.", "fr_FR": "Signale les éléments audio dont le volume est inhabituel par rapport aux autres éléments.", "it_IT": "Segnala le clip audio con un volume insolito rispetto alle altre clip.", "ja_JP": "ボリューム設定が他のクリップと比べて極端なオーディオクリップを報告します。", "ko_KR": "볼륨 설정이 다른 클립과 비교해 이례적인 오디오 클립을 보고합니다.", "pt_BR": "Relata clipes de áudio cuja configuração de volume é incomum em relação aos outros clipes.", "ru_RU": "Сообщает об аудиоклипах с громкостью, нетипичной по сравнению с другими клипами.", "zh_CN": "报告音量设置与其他剪辑相比异常的音频剪辑。" }, "category": "local-consistency", "scope": "audio-level-outliers", "severity": "info", "options": { "maxDeviationDb": { "type": "number", "default": 6, "description": "Report clips whose volume differs from the median by more than this many dB. Equal is not reported." }, "minClips": { "type": "number", "default": 4, "description": "Populations smaller than this are insufficient data and are not analysed." }, "scope": { "type": "string", "default": "track", "description": "\"track\" compares clips with the other clips on the same track; \"sequence\" with every eligible clip of the sequence." } }, "checks": [ { "condition": { "field": "outlier.deviation", "operator": "greaterThan", "value": { "field": "options.maxDeviationDb" } }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is set to {outlier.value} dB, {outlier.absDeviation} dB louder than the median ({outlier.median} dB) of {labels.population}.", "de_DE": "Clip „{clip.name}“ auf {clip.track} ist auf {outlier.value} dB eingestellt, {outlier.absDeviation} dB lauter als der Median ({outlier.median} dB) von {labels.population}.", "es_ES": "Clip \"{clip.name}\" en {clip.track} está a {outlier.value} dB, {outlier.absDeviation} dB por encima de la mediana ({outlier.median} dB) de {labels.population}.", "fr_FR": "Élément « {clip.name} » sur {clip.track} est réglé sur {outlier.value} dB, soit {outlier.absDeviation} dB de plus que la médiane ({outlier.median} dB) de {labels.population}.", "it_IT": "Clip \"{clip.name}\" su {clip.track} è impostata a {outlier.value} dB, {outlier.absDeviation} dB più alta della mediana ({outlier.median} dB) di {labels.population}.", "ja_JP": "クリップ「{clip.name}」({clip.track})は{outlier.value} dBに設定されており、{labels.population}の中央値({outlier.median} dB)より{outlier.absDeviation} dB大きくなっています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 볼륨({outlier.value} dB)이 {labels.population}의 중앙값({outlier.median} dB)보다 {outlier.absDeviation} dB 큽니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está em {outlier.value} dB, {outlier.absDeviation} dB mais alto que a mediana ({outlier.median} dB) de {labels.population}.", "ru_RU": "Клип «{clip.name}» на {clip.track}: громкость {outlier.value} dB, на {outlier.absDeviation} dB громче медианы ({outlier.median} dB) для {labels.population}.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 设置为 {outlier.value} dB,比{labels.population}的中位数({outlier.median} dB)高 {outlier.absDeviation} dB。" } }, { "condition": { "all": [ { "field": "outlier.absDeviation", "operator": "greaterThan", "value": { "field": "options.maxDeviationDb" } }, { "field": "outlier.deviation", "operator": "lessThan", "value": 0 } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is set to {outlier.value} dB, {outlier.absDeviation} dB quieter than the median ({outlier.median} dB) of {labels.population}.", "de_DE": "Clip „{clip.name}“ auf {clip.track} ist auf {outlier.value} dB eingestellt, {outlier.absDeviation} dB leiser als der Median ({outlier.median} dB) von {labels.population}.", "es_ES": "Clip \"{clip.name}\" en {clip.track} está a {outlier.value} dB, {outlier.absDeviation} dB por debajo de la mediana ({outlier.median} dB) de {labels.population}.", "fr_FR": "Élément « {clip.name} » sur {clip.track} est réglé sur {outlier.value} dB, soit {outlier.absDeviation} dB de moins que la médiane ({outlier.median} dB) de {labels.population}.", "it_IT": "Clip \"{clip.name}\" su {clip.track} è impostata a {outlier.value} dB, {outlier.absDeviation} dB più bassa della mediana ({outlier.median} dB) di {labels.population}.", "ja_JP": "クリップ「{clip.name}」({clip.track})は{outlier.value} dBに設定されており、{labels.population}の中央値({outlier.median} dB)より{outlier.absDeviation} dB小さくなっています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 볼륨({outlier.value} dB)이 {labels.population}의 중앙값({outlier.median} dB)보다 {outlier.absDeviation} dB 작습니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está em {outlier.value} dB, {outlier.absDeviation} dB mais baixo que a mediana ({outlier.median} dB) de {labels.population}.", "ru_RU": "Клип «{clip.name}» на {clip.track}: громкость {outlier.value} dB, на {outlier.absDeviation} dB тише медианы ({outlier.median} dB) для {labels.population}.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 设置为 {outlier.value} dB,比{labels.population}的中位数({outlier.median} dB)低 {outlier.absDeviation} dB。" } } ], "labels": { "population": { "field": "outlier.populationIsTrack", "values": { "true": { "en_US": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip on {outlier.populationKey}", "other": "{outlier.populationSize} clips on {outlier.populationKey}" }, "de_DE": { "count": "outlier.populationSize", "one": "{outlier.populationSize} Clip auf {outlier.populationKey}", "other": "{outlier.populationSize} Clips auf {outlier.populationKey}" }, "es_ES": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip en {outlier.populationKey}", "other": "los {outlier.populationSize} clips en {outlier.populationKey}" }, "fr_FR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} élément sur {outlier.populationKey}", "other": "{outlier.populationSize} éléments sur {outlier.populationKey}" }, "it_IT": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip su {outlier.populationKey}", "other": "{outlier.populationSize} clip su {outlier.populationKey}" }, "ja_JP": "{outlier.populationKey}の{outlier.populationSize}個のクリップ", "ko_KR": "{outlier.populationKey}의 클립 {outlier.populationSize}개", "pt_BR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clipe em {outlier.populationKey}", "other": "{outlier.populationSize} clipes em {outlier.populationKey}" }, "ru_RU": { "count": "outlier.populationSize", "one": "{outlier.populationSize} клипа на {outlier.populationKey}", "few": "{outlier.populationSize} клипов на {outlier.populationKey}", "many": "{outlier.populationSize} клипов на {outlier.populationKey}", "other": "{outlier.populationSize} клипа на {outlier.populationKey}" }, "zh_CN": "{outlier.populationKey} 上的 {outlier.populationSize} 个剪辑" }, "false": { "en_US": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip in the sequence", "other": "{outlier.populationSize} clips in the sequence" }, "de_DE": { "count": "outlier.populationSize", "one": "{outlier.populationSize} Clip in der Sequenz", "other": "{outlier.populationSize} Clips in der Sequenz" }, "es_ES": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip de la secuencia", "other": "los {outlier.populationSize} clips de la secuencia" }, "fr_FR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} élément de la séquence", "other": "{outlier.populationSize} éléments de la séquence" }, "it_IT": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip nella sequenza", "other": "{outlier.populationSize} clip nella sequenza" }, "ja_JP": "シーケンス内の{outlier.populationSize}個のクリップ", "ko_KR": "시퀀스의 클립 {outlier.populationSize}개", "pt_BR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clipe na sequência", "other": "{outlier.populationSize} clipes na sequência" }, "ru_RU": { "count": "outlier.populationSize", "one": "{outlier.populationSize} клипа в эпизоде", "few": "{outlier.populationSize} клипов в эпизоде", "many": "{outlier.populationSize} клипов в эпизоде", "other": "{outlier.populationSize} клипа в эпизоде" }, "zh_CN": "序列中的 {outlier.populationSize} 个剪辑" } } } }, "data": { "volumeDb": "outlier.value", "medianDb": "outlier.median", "deviationDb": "outlier.deviation", "maxDeviationDb": "options.maxDeviationDb", "population": "outlier.populationKey", "populationSize": "outlier.populationSize" } } ``` # Duration outliers (/docs/rules/duration-outlier) Reports clips far longer or shorter than the other clips. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :---------------------------------------------------------------------------------------- | | Id | `duration-outlier` | | Category | Global consistency | | Default severity | info | | Scope | [`duration-outliers`](/docs/reference/computed-scopes#duration-outliers) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :--------- | :------- | :-------- | :------------------------------------------------------------------------------------------------------------------ | | `maxZ` | `number` | `3.5` | Modified z-score of the log duration above which a clip is reported. | | `minClips` | `number` | `8` | Populations smaller than this are insufficient data and are not analysed. | | `scope` | `string` | `"track"` | "track" compares clips with the other clips on the same track; "sequence" with every eligible clip of the sequence. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `duration-outlier.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="duration-outlier.rule.json" { "formatVersion": 1, "id": "duration-outlier", "name": { "en_US": "Duration outliers", "de_DE": "Abweichende Dauer", "es_ES": "Duraciones atípicas", "fr_FR": "Durées atypiques", "it_IT": "Durate anomale", "ja_JP": "デュレーションの外れ値", "ko_KR": "지속 시간 이상값", "pt_BR": "Durações atípicas", "ru_RU": "Нетипичная длительность", "zh_CN": "持续时间异常" }, "description": { "en_US": "Reports clips far longer or shorter than the other clips.", "de_DE": "Meldet Clips, die deutlich länger oder kürzer als die anderen Clips sind.", "es_ES": "Detecta clips mucho más largos o más cortos que los demás.", "fr_FR": "Signale les éléments bien plus longs ou plus courts que les autres éléments.", "it_IT": "Segnala le clip molto più lunghe o più corte delle altre clip.", "ja_JP": "他のクリップよりはるかに長いクリップまたは短いクリップを報告します。", "ko_KR": "다른 클립보다 훨씬 길거나 짧은 클립을 보고합니다.", "pt_BR": "Relata clipes muito mais longos ou mais curtos que os outros clipes.", "ru_RU": "Сообщает о клипах, намного более длинных или коротких, чем остальные клипы.", "zh_CN": "报告远长于或远短于其他剪辑的剪辑。" }, "category": "global-consistency", "scope": "duration-outliers", "severity": "info", "options": { "maxZ": { "type": "number", "default": 3.5, "description": "Modified z-score of the log duration above which a clip is reported." }, "minClips": { "type": "number", "default": 8, "description": "Populations smaller than this are insufficient data and are not analysed." }, "scope": { "type": "string", "default": "track", "description": "\"track\" compares clips with the other clips on the same track; \"sequence\" with every eligible clip of the sequence." } }, "checks": [ { "condition": { "field": "outlier.z", "operator": "greaterThan", "value": { "field": "options.maxZ" } }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} lasts {outlier.durationSeconds} s, far longer than the typical {outlier.typicalSeconds} s of {labels.population}.", "de_DE": "Clip „{clip.name}“ auf {clip.track} dauert {outlier.durationSeconds} s, deutlich länger als der typische Wert ({outlier.typicalSeconds} s) von {labels.population}.", "es_ES": "Clip \"{clip.name}\" en {clip.track} dura {outlier.durationSeconds} s, mucho más que la duración típica ({outlier.typicalSeconds} s) de {labels.population}.", "fr_FR": "Élément « {clip.name} » sur {clip.track} dure {outlier.durationSeconds} s, bien plus que la durée typique ({outlier.typicalSeconds} s) de {labels.population}.", "it_IT": "Clip \"{clip.name}\" su {clip.track} dura {outlier.durationSeconds} s, molto più della durata tipica di {outlier.typicalSeconds} s di {labels.population}.", "ja_JP": "クリップ「{clip.name}」({clip.track})の長さは{outlier.durationSeconds} sで、{labels.population}の標準的な長さ({outlier.typicalSeconds} s)よりはるかに長くなっています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 길이({outlier.durationSeconds} s)가 {labels.population}의 일반적인 길이({outlier.typicalSeconds} s)보다 훨씬 깁니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} dura {outlier.durationSeconds} s, muito mais que a duração típica de {outlier.typicalSeconds} s de {labels.population}.", "ru_RU": "Клип «{clip.name}» на {clip.track} длится {outlier.durationSeconds} с, намного дольше типичной длительности {outlier.typicalSeconds} с для {labels.population}.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 时长为 {outlier.durationSeconds} s,远长于{labels.population}的典型时长 {outlier.typicalSeconds} s。" } }, { "condition": { "all": [ { "field": "outlier.absZ", "operator": "greaterThan", "value": { "field": "options.maxZ" } }, { "field": "outlier.z", "operator": "lessThan", "value": 0 } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} lasts {outlier.durationSeconds} s, far shorter than the typical {outlier.typicalSeconds} s of {labels.population}.", "de_DE": "Clip „{clip.name}“ auf {clip.track} dauert {outlier.durationSeconds} s, deutlich kürzer als der typische Wert ({outlier.typicalSeconds} s) von {labels.population}.", "es_ES": "Clip \"{clip.name}\" en {clip.track} dura {outlier.durationSeconds} s, mucho menos que la duración típica ({outlier.typicalSeconds} s) de {labels.population}.", "fr_FR": "Élément « {clip.name} » sur {clip.track} dure {outlier.durationSeconds} s, bien moins que la durée typique ({outlier.typicalSeconds} s) de {labels.population}.", "it_IT": "Clip \"{clip.name}\" su {clip.track} dura {outlier.durationSeconds} s, molto meno della durata tipica di {outlier.typicalSeconds} s di {labels.population}.", "ja_JP": "クリップ「{clip.name}」({clip.track})の長さは{outlier.durationSeconds} sで、{labels.population}の標準的な長さ({outlier.typicalSeconds} s)よりはるかに短くなっています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 길이({outlier.durationSeconds} s)가 {labels.population}의 일반적인 길이({outlier.typicalSeconds} s)보다 훨씬 짧습니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} dura {outlier.durationSeconds} s, muito menos que a duração típica de {outlier.typicalSeconds} s de {labels.population}.", "ru_RU": "Клип «{clip.name}» на {clip.track} длится {outlier.durationSeconds} с, намного короче типичной длительности {outlier.typicalSeconds} с для {labels.population}.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 时长为 {outlier.durationSeconds} s,远短于{labels.population}的典型时长 {outlier.typicalSeconds} s。" } } ], "labels": { "population": { "field": "outlier.populationIsTrack", "values": { "true": { "en_US": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip on {outlier.populationKey}", "other": "{outlier.populationSize} clips on {outlier.populationKey}" }, "de_DE": { "count": "outlier.populationSize", "one": "{outlier.populationSize} Clip auf {outlier.populationKey}", "other": "{outlier.populationSize} Clips auf {outlier.populationKey}" }, "es_ES": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip en {outlier.populationKey}", "other": "los {outlier.populationSize} clips en {outlier.populationKey}" }, "fr_FR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} élément sur {outlier.populationKey}", "other": "{outlier.populationSize} éléments sur {outlier.populationKey}" }, "it_IT": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip su {outlier.populationKey}", "other": "{outlier.populationSize} clip su {outlier.populationKey}" }, "ja_JP": "{outlier.populationKey}の{outlier.populationSize}個のクリップ", "ko_KR": "{outlier.populationKey}의 클립 {outlier.populationSize}개", "pt_BR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clipe em {outlier.populationKey}", "other": "{outlier.populationSize} clipes em {outlier.populationKey}" }, "ru_RU": { "count": "outlier.populationSize", "one": "{outlier.populationSize} клипа на {outlier.populationKey}", "few": "{outlier.populationSize} клипов на {outlier.populationKey}", "many": "{outlier.populationSize} клипов на {outlier.populationKey}", "other": "{outlier.populationSize} клипа на {outlier.populationKey}" }, "zh_CN": "{outlier.populationKey} 上的 {outlier.populationSize} 个剪辑" }, "false": { "en_US": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip in the sequence", "other": "{outlier.populationSize} clips in the sequence" }, "de_DE": { "count": "outlier.populationSize", "one": "{outlier.populationSize} Clip in der Sequenz", "other": "{outlier.populationSize} Clips in der Sequenz" }, "es_ES": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip de la secuencia", "other": "los {outlier.populationSize} clips de la secuencia" }, "fr_FR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} élément de la séquence", "other": "{outlier.populationSize} éléments de la séquence" }, "it_IT": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip nella sequenza", "other": "{outlier.populationSize} clip nella sequenza" }, "ja_JP": "シーケンス内の{outlier.populationSize}個のクリップ", "ko_KR": "시퀀스의 클립 {outlier.populationSize}개", "pt_BR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clipe na sequência", "other": "{outlier.populationSize} clipes na sequência" }, "ru_RU": { "count": "outlier.populationSize", "one": "{outlier.populationSize} клипа в эпизоде", "few": "{outlier.populationSize} клипов в эпизоде", "many": "{outlier.populationSize} клипов в эпизоде", "other": "{outlier.populationSize} клипа в эпизоде" }, "zh_CN": "序列中的 {outlier.populationSize} 个剪辑" } } } }, "data": { "durationTicks": "outlier.durationTicks", "typicalTicks": "outlier.typicalTicks", "z": "outlier.z", "maxZ": "options.maxZ", "population": "outlier.populationKey", "populationSize": "outlier.populationSize" } } ``` # Inconsistent effects (/docs/rules/inconsistent-effects) Reports clips missing an effect that most comparable clips have. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :------------------------------------------------------------------------------------ | | Id | `inconsistent-effects` | | Category | Local consistency | | Default severity | info | | Scope | [`missing-effects`](/docs/reference/computed-scopes#missing-effects) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :-------------- | :--------- | :-------- | :------------------------------------------------------------------------------------------------------------------ | | `minPrevalence` | `number` | `0.75` | An effect on at least this fraction of the population is expected on all of it. | | `minClips` | `number` | `4` | Populations smaller than this are insufficient data and are not analysed. | | `scope` | `string` | `"track"` | "track" compares clips with the other clips on the same track; "sequence" with every eligible clip of the sequence. | | `ignore` | `string[]` | `[]` | Match names never reported. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `inconsistent-effects.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="inconsistent-effects.rule.json" { "formatVersion": 1, "id": "inconsistent-effects", "name": { "en_US": "Inconsistent effects", "de_DE": "Uneinheitliche Effekte", "es_ES": "Efectos incoherentes", "fr_FR": "Effets incohérents", "it_IT": "Effetti incoerenti", "ja_JP": "一貫性のないエフェクト", "ko_KR": "일관되지 않은 효과", "pt_BR": "Efeitos inconsistentes", "ru_RU": "Несогласованные эффекты", "zh_CN": "效果不一致" }, "description": { "en_US": "Reports clips missing an effect that most comparable clips have.", "de_DE": "Meldet Clips, denen ein Effekt fehlt, den die meisten vergleichbaren Clips haben.", "es_ES": "Detecta clips a los que les falta un efecto que tienen la mayoría de clips comparables.", "fr_FR": "Signale les éléments auxquels il manque un effet présent sur la plupart des éléments comparables.", "it_IT": "Segnala le clip prive di un effetto presente nella maggior parte delle clip simili.", "ja_JP": "同等のクリップの大半に適用されているエフェクトがないクリップを報告します。", "ko_KR": "비교 가능한 대부분의 클립에 있는 효과가 없는 클립을 보고합니다.", "pt_BR": "Relata clipes sem um efeito que a maioria dos clipes comparáveis tem.", "ru_RU": "Сообщает о клипах без эффекта, который есть у большинства сопоставимых клипов.", "zh_CN": "报告缺少大多数同类剪辑都具有的某个效果的剪辑。" }, "category": "local-consistency", "scope": "missing-effects", "severity": "info", "options": { "minPrevalence": { "type": "number", "default": 0.75, "description": "An effect on at least this fraction of the population is expected on all of it." }, "minClips": { "type": "number", "default": 4, "description": "Populations smaller than this are insufficient data and are not analysed." }, "scope": { "type": "string", "default": "track", "description": "\"track\" compares clips with the other clips on the same track; \"sequence\" with every eligible clip of the sequence." }, "ignore": { "type": "string[]", "default": [], "description": "Match names never reported." } }, "checks": [ { "condition": { "all": [ { "field": "missing.prevalence", "operator": "greaterThanOrEqual", "value": { "field": "options.minPrevalence" } }, { "field": "missing.matchName", "operator": "notIn", "value": { "field": "options.ignore" } } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} has no \"{missing.displayName}\", which {missing.withEffect} of {labels.population} have.", "de_DE": { "count": "missing.withEffect", "one": "Bei Clip „{clip.name}“ auf {clip.track} fehlt der Effekt „{missing.displayName}“, den {missing.withEffect} von {labels.population} hat.", "other": "Bei Clip „{clip.name}“ auf {clip.track} fehlt der Effekt „{missing.displayName}“, den {missing.withEffect} von {labels.population} haben." }, "es_ES": "Clip \"{clip.name}\" en {clip.track} no tiene \"{missing.displayName}\", que sí tienen {missing.withEffect} de {labels.population}.", "fr_FR": "Élément « {clip.name} » sur {clip.track} n'a pas l'effet « {missing.displayName} », présent sur {missing.withEffect} parmi {labels.population}.", "it_IT": "Clip \"{clip.name}\" su {clip.track} non ha l'effetto \"{missing.displayName}\", presente in {missing.withEffect} di {labels.population}.", "ja_JP": "クリップ「{clip.name}」({clip.track})には「{missing.displayName}」がありません({labels.population}のうち{missing.withEffect}個に適用されています)。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"에 \"{missing.displayName}\" 효과가 없습니다. {labels.population} 중 {missing.withEffect}개에는 이 효과가 있습니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} não tem \"{missing.displayName}\", presente em {missing.withEffect} de {labels.population}.", "ru_RU": "Клип «{clip.name}» на {clip.track} не содержит эффект «{missing.displayName}», который есть у {missing.withEffect} из {labels.population}.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 没有“{missing.displayName}”,而{labels.population}中有 {missing.withEffect} 个剪辑应用了该效果。" } } ], "labels": { "population": { "field": "missing.populationIsTrack", "values": { "true": { "en_US": { "count": "missing.populationSize", "one": "{missing.populationSize} clip on {missing.populationKey}", "other": "{missing.populationSize} clips on {missing.populationKey}" }, "de_DE": { "count": "missing.populationSize", "one": "{missing.populationSize} Clip auf {missing.populationKey}", "other": "{missing.populationSize} Clips auf {missing.populationKey}" }, "es_ES": { "count": "missing.populationSize", "one": "{missing.populationSize} clip en {missing.populationKey}", "other": "los {missing.populationSize} clips en {missing.populationKey}" }, "fr_FR": { "count": "missing.populationSize", "one": "{missing.populationSize} élément sur {missing.populationKey}", "other": "{missing.populationSize} éléments sur {missing.populationKey}" }, "it_IT": { "count": "missing.populationSize", "one": "{missing.populationSize} clip su {missing.populationKey}", "other": "{missing.populationSize} clip su {missing.populationKey}" }, "ja_JP": "{missing.populationKey}の{missing.populationSize}個のクリップ", "ko_KR": "{missing.populationKey}의 클립 {missing.populationSize}개", "pt_BR": { "count": "missing.populationSize", "one": "{missing.populationSize} clipe em {missing.populationKey}", "other": "{missing.populationSize} clipes em {missing.populationKey}" }, "ru_RU": { "count": "missing.populationSize", "one": "{missing.populationSize} клипа на {missing.populationKey}", "few": "{missing.populationSize} клипов на {missing.populationKey}", "many": "{missing.populationSize} клипов на {missing.populationKey}", "other": "{missing.populationSize} клипа на {missing.populationKey}" }, "zh_CN": "{missing.populationKey} 上的 {missing.populationSize} 个剪辑" }, "false": { "en_US": { "count": "missing.populationSize", "one": "{missing.populationSize} clip in the sequence", "other": "{missing.populationSize} clips in the sequence" }, "de_DE": { "count": "missing.populationSize", "one": "{missing.populationSize} Clip in der Sequenz", "other": "{missing.populationSize} Clips in der Sequenz" }, "es_ES": { "count": "missing.populationSize", "one": "{missing.populationSize} clip de la secuencia", "other": "los {missing.populationSize} clips de la secuencia" }, "fr_FR": { "count": "missing.populationSize", "one": "{missing.populationSize} élément de la séquence", "other": "{missing.populationSize} éléments de la séquence" }, "it_IT": { "count": "missing.populationSize", "one": "{missing.populationSize} clip nella sequenza", "other": "{missing.populationSize} clip nella sequenza" }, "ja_JP": "シーケンス内の{missing.populationSize}個のクリップ", "ko_KR": "시퀀스의 클립 {missing.populationSize}개", "pt_BR": { "count": "missing.populationSize", "one": "{missing.populationSize} clipe na sequência", "other": "{missing.populationSize} clipes na sequência" }, "ru_RU": { "count": "missing.populationSize", "one": "{missing.populationSize} клипа в эпизоде", "few": "{missing.populationSize} клипов в эпизоде", "many": "{missing.populationSize} клипов в эпизоде", "other": "{missing.populationSize} клипа в эпизоде" }, "zh_CN": "序列中的 {missing.populationSize} 个剪辑" } } } }, "data": { "matchName": "missing.matchName", "displayName": "missing.displayName", "withEffect": "missing.withEffect", "populationSize": "missing.populationSize", "prevalence": "missing.prevalence", "minPrevalence": "options.minPrevalence", "population": "missing.populationKey" } } ``` # Built-in rules (/docs/rules) Every rule PPROLint ships with, and its rule file. {/* Generated by scripts/generate-docs.ts. Do not edit. */} PPROLint ships with 29 rules. Each is a rule file like the ones you write: open one to see its options and the complete file, a good starting point for your own rule. ## Static [#static] | Rule | Id | Severity | Reports | | :------------------------------------------------------------------------------------ | :------------------------------------- | :------- | :--------------------------------------------------------------------------------- | | [Audio gaps](/docs/rules/no-audio-gaps) | `no-audio-gaps` | info | Reports ranges of the work area where no audio clip is audible. | | [Clips outside the work area](/docs/rules/no-clips-outside-work-area) | `no-clips-outside-work-area` | warning | Reports clips entirely before the sequence in point or after its out point. | | [Disabled clips](/docs/rules/no-disabled-clips) | `no-disabled-clips` | warning | Reports disabled clips, which are skipped on playback and export. | | [Duplicate effects](/docs/rules/no-duplicate-effects) | `no-duplicate-effects` | info | Reports clips with the same effect applied more than once. | | [Empty markers](/docs/rules/no-empty-markers) | `no-empty-markers` | info | Reports markers with neither a name nor a comment. | | [Empty tracks](/docs/rules/no-empty-tracks) | `no-empty-tracks` | info | Reports tracks without clips. | | [Invisible video clips](/docs/rules/no-invisible-video-clips) | `no-invisible-video-clips` | warning | Reports video clips at 0 % opacity or 0 % scale, which render nothing. | | [Markers outside the work area](/docs/rules/no-markers-outside-work-area) | `no-markers-outside-work-area` | warning | Reports markers after the last clip or outside the sequence in/out range. | | [Muted tracks](/docs/rules/no-muted-tracks) | `no-muted-tracks` | warning | Reports muted tracks that carry clips, which are left out of the export. | | [Offline media](/docs/rules/no-offline-media) | `no-offline-media` | error | Reports clips whose source media is offline. | | [Out-of-sync audio and video](/docs/rules/no-out-of-sync-av) | `no-out-of-sync-av` | warning | Reports audio clips offset from the video clip of the same source they play under. | | [Partial adjustment layer coverage](/docs/rules/no-partial-adjustment-layer-coverage) | `no-partial-adjustment-layer-coverage` | info | Reports adjustment layers whose start or end falls inside a clip below them. | | [Silent audio clips](/docs/rules/no-silent-audio-clips) | `no-silent-audio-clips` | warning | Reports audio clips whose volume is set to silence. | | [Subframe video edits](/docs/rules/no-subframe-video-edits) | `no-subframe-video-edits` | warning | Reports clip edges and sequence in/out points that are not on a frame boundary. | | [Tiny clips](/docs/rules/no-tiny-clips) | `no-tiny-clips` | warning | Reports clips only a few frames long, usually leftovers of a trim. | | [Video gaps](/docs/rules/no-video-gaps) | `no-video-gaps` | warning | Reports ranges of the work area where no video clip is visible (black frames). | | [Zero-duration clips](/docs/rules/no-zero-duration-clips) | `no-zero-duration-clips` | error | Reports clips whose end is not after their start. | | [Scale range](/docs/rules/scale-range) | `scale-range` | info | Reports video clips scaled outside the allowed range. | ## Local consistency [#local-consistency] | Rule | Id | Severity | Reports | | :------------------------------------------------------- | :--------------------- | :------- | :----------------------------------------------------------------------------- | | [Audio level outliers](/docs/rules/audio-level-outlier) | `audio-level-outlier` | info | Reports audio clips whose volume setting is unusual compared with other clips. | | [Inconsistent effects](/docs/rules/inconsistent-effects) | `inconsistent-effects` | info | Reports clips missing an effect that most comparable clips have. | | [Scale outliers](/docs/rules/scale-outlier) | `scale-outlier` | info | Reports video clips whose scale is unusual compared with other clips. | | [Speed outliers](/docs/rules/speed-outlier) | `speed-outlier` | info | Reports clips whose speed is unusual compared with other clips. | ## Global consistency [#global-consistency] | Rule | Id | Severity | Reports | | :-------------------------------------------------- | :-------------------- | :------- | :------------------------------------------------------------------------------ | | [Duration outliers](/docs/rules/duration-outlier) | `duration-outlier` | info | Reports clips far longer or shorter than the other clips. | | [Repeated footage](/docs/rules/no-repeated-footage) | `no-repeated-footage` | info | Reports clips that reuse a source range already used elsewhere in the sequence. | ## Project [#project] | Rule | Id | Severity | Reports | | :------------------------------------------------------ | :---------------------- | :------- | :----------------------------------------------------------------------- | | [Restricted effects](/docs/rules/no-restricted-effects) | `no-restricted-effects` | warning | Reports clips using a configured forbidden effect. | | [Required effects](/docs/rules/required-effects) | `required-effects` | warning | Reports clips missing a configured effect. | | [Required markers](/docs/rules/required-markers) | `required-markers` | warning | Reports configured sequence markers that are missing. | | [Required tracks](/docs/rules/required-tracks) | `required-tracks` | warning | Reports a track layout that does not match the configured requirements. | | [Sequence settings](/docs/rules/sequence-settings) | `sequence-settings` | warning | Reports a sequence whose frame rate or frame size is not an allowed one. | # Audio gaps (/docs/rules/no-audio-gaps) Reports ranges of the work area where no audio clip is audible. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :-------------------------------------------------------------------------- | | Id | `no-audio-gaps` | | Category | Static | | Default severity | info | | Scope | [`audio-gaps`](/docs/reference/computed-scopes#audio-gaps) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :----------- | :-------- | :------ | :------------------------------------------------------------------- | | `minSeconds` | `number` | `1` | Silences shorter than this are not reported. | | `silenceDb` | `number` | `-60` | Clips whose static volume is at or below this do not count as audio. | | `leading` | `boolean` | `true` | Report silence at the start of the work area. | | `trailing` | `boolean` | `true` | Report silence at the end of the work area. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-audio-gaps.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-audio-gaps.rule.json" { "formatVersion": 1, "id": "no-audio-gaps", "name": { "en_US": "Audio gaps", "de_DE": "Audiolücken", "es_ES": "Huecos de audio", "fr_FR": "Blancs audio", "it_IT": "Vuoti audio", "ja_JP": "オーディオの欠落", "ko_KR": "오디오 간격", "pt_BR": "Lacunas de áudio", "ru_RU": "Пропуски звука", "zh_CN": "音频间隙" }, "description": { "en_US": "Reports ranges of the work area where no audio clip is audible.", "de_DE": "Meldet Bereiche des Arbeitsbereichs, in denen kein Audioclip hörbar ist.", "es_ES": "Detecta intervalos del área de trabajo en los que no se oye ningún clip de audio.", "fr_FR": "Signale les plages de la zone de travail où aucun élément audio n'est audible.", "it_IT": "Segnala gli intervalli dell'area di lavoro in cui nessuna clip audio è udibile.", "ja_JP": "ワークエリア内で、聞こえるオーディオクリップがない範囲を報告します。", "ko_KR": "작업 영역에서 들리는 오디오 클립이 없는 구간을 보고합니다.", "pt_BR": "Relata intervalos da área de trabalho em que nenhum clipe de áudio é audível.", "ru_RU": "Сообщает об участках рабочей области, где не слышно ни одного аудиоклипа.", "zh_CN": "报告工作区域中没有可听见的音频剪辑的范围。" }, "category": "static", "scope": "audio-gaps", "severity": "info", "options": { "minSeconds": { "type": "number", "default": 1, "description": "Silences shorter than this are not reported." }, "silenceDb": { "type": "number", "default": -60, "description": "Clips whose static volume is at or below this do not count as audio." }, "leading": { "type": "boolean", "default": true, "description": "Report silence at the start of the work area." }, "trailing": { "type": "boolean", "default": true, "description": "Report silence at the end of the work area." } }, "checks": [ { "condition": { "all": [ { "field": "gap.durationSeconds", "operator": "greaterThanOrEqual", "value": { "field": "options.minSeconds" } }, { "any": [ { "field": "gap.kind", "operator": "equals", "value": "inner" }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "leading" }, { "field": "options.leading", "operator": "equals", "value": true } ] }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "trailing" }, { "field": "options.trailing", "operator": "equals", "value": true } ] } ] }, { "all": [ { "field": "gap.hasBefore", "operator": "equals", "value": true }, { "field": "gap.hasAfter", "operator": "equals", "value": true } ] } ] }, "message": { "en_US": "No audio for {gap.durationSeconds} s ({gap.startTimecode} to {gap.endTimecode}) between \"{gap.beforeName}\" on {gap.beforeTrack} and \"{gap.afterName}\" on {gap.afterTrack}.", "de_DE": "Kein Audio für {gap.durationSeconds} s ({gap.startTimecode} bis {gap.endTimecode}) zwischen „{gap.beforeName}“ auf {gap.beforeTrack} und „{gap.afterName}“ auf {gap.afterTrack}.", "es_ES": "Sin audio durante {gap.durationSeconds} s (de {gap.startTimecode} a {gap.endTimecode}) entre \"{gap.beforeName}\" en {gap.beforeTrack} y \"{gap.afterName}\" en {gap.afterTrack}.", "fr_FR": "Aucun audio pendant {gap.durationSeconds} s ({gap.startTimecode} à {gap.endTimecode}) entre « {gap.beforeName} » sur {gap.beforeTrack} et « {gap.afterName} » sur {gap.afterTrack}.", "it_IT": "Nessun audio per {gap.durationSeconds} s (da {gap.startTimecode} a {gap.endTimecode}) tra \"{gap.beforeName}\" su {gap.beforeTrack} e \"{gap.afterName}\" su {gap.afterTrack}.", "ja_JP": "「{gap.beforeName}」({gap.beforeTrack})と「{gap.afterName}」({gap.afterTrack})の間に{gap.durationSeconds} sのオーディオの欠落があります({gap.startTimecode}~{gap.endTimecode})。", "ko_KR": "{gap.durationSeconds} s 동안 오디오 없음({gap.startTimecode}~{gap.endTimecode}): {gap.beforeTrack}의 \"{gap.beforeName}\" 뒤, {gap.afterTrack}의 \"{gap.afterName}\" 앞.", "pt_BR": "Sem áudio por {gap.durationSeconds} s ({gap.startTimecode} a {gap.endTimecode}) entre \"{gap.beforeName}\" em {gap.beforeTrack} e \"{gap.afterName}\" em {gap.afterTrack}.", "ru_RU": "Нет звука в течение {gap.durationSeconds} с (с {gap.startTimecode} по {gap.endTimecode}) между «{gap.beforeName}» на {gap.beforeTrack} и «{gap.afterName}» на {gap.afterTrack}.", "zh_CN": "{gap.durationSeconds} s 无音频({gap.startTimecode} 至 {gap.endTimecode}),位于 {gap.beforeTrack} 上的“{gap.beforeName}” 和 {gap.afterTrack} 上的“{gap.afterName}” 之间。" } }, { "condition": { "all": [ { "field": "gap.durationSeconds", "operator": "greaterThanOrEqual", "value": { "field": "options.minSeconds" } }, { "any": [ { "field": "gap.kind", "operator": "equals", "value": "inner" }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "leading" }, { "field": "options.leading", "operator": "equals", "value": true } ] }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "trailing" }, { "field": "options.trailing", "operator": "equals", "value": true } ] } ] }, { "all": [ { "field": "gap.hasBefore", "operator": "equals", "value": false }, { "field": "gap.hasAfter", "operator": "equals", "value": true } ] } ] }, "message": { "en_US": "No audio for {gap.durationSeconds} s ({gap.startTimecode} to {gap.endTimecode}) before \"{gap.afterName}\" on {gap.afterTrack}.", "de_DE": "Kein Audio für {gap.durationSeconds} s ({gap.startTimecode} bis {gap.endTimecode}) vor „{gap.afterName}“ auf {gap.afterTrack}.", "es_ES": "Sin audio durante {gap.durationSeconds} s (de {gap.startTimecode} a {gap.endTimecode}) antes de \"{gap.afterName}\" en {gap.afterTrack}.", "fr_FR": "Aucun audio pendant {gap.durationSeconds} s ({gap.startTimecode} à {gap.endTimecode}) avant « {gap.afterName} » sur {gap.afterTrack}.", "it_IT": "Nessun audio per {gap.durationSeconds} s (da {gap.startTimecode} a {gap.endTimecode}) prima di \"{gap.afterName}\" su {gap.afterTrack}.", "ja_JP": "「{gap.afterName}」({gap.afterTrack})の前に{gap.durationSeconds} sのオーディオの欠落があります({gap.startTimecode}~{gap.endTimecode})。", "ko_KR": "{gap.durationSeconds} s 동안 오디오 없음({gap.startTimecode}~{gap.endTimecode}): {gap.afterTrack}의 \"{gap.afterName}\" 앞.", "pt_BR": "Sem áudio por {gap.durationSeconds} s ({gap.startTimecode} a {gap.endTimecode}) antes de \"{gap.afterName}\" em {gap.afterTrack}.", "ru_RU": "Нет звука в течение {gap.durationSeconds} с (с {gap.startTimecode} по {gap.endTimecode}) перед «{gap.afterName}» на {gap.afterTrack}.", "zh_CN": "{gap.durationSeconds} s 无音频({gap.startTimecode} 至 {gap.endTimecode}),位于 {gap.afterTrack} 上的“{gap.afterName}” 之前。" } }, { "condition": { "all": [ { "field": "gap.durationSeconds", "operator": "greaterThanOrEqual", "value": { "field": "options.minSeconds" } }, { "any": [ { "field": "gap.kind", "operator": "equals", "value": "inner" }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "leading" }, { "field": "options.leading", "operator": "equals", "value": true } ] }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "trailing" }, { "field": "options.trailing", "operator": "equals", "value": true } ] } ] }, { "all": [ { "field": "gap.hasBefore", "operator": "equals", "value": true }, { "field": "gap.hasAfter", "operator": "equals", "value": false } ] } ] }, "message": { "en_US": "No audio for {gap.durationSeconds} s ({gap.startTimecode} to {gap.endTimecode}) after \"{gap.beforeName}\" on {gap.beforeTrack}.", "de_DE": "Kein Audio für {gap.durationSeconds} s ({gap.startTimecode} bis {gap.endTimecode}) nach „{gap.beforeName}“ auf {gap.beforeTrack}.", "es_ES": "Sin audio durante {gap.durationSeconds} s (de {gap.startTimecode} a {gap.endTimecode}) después de \"{gap.beforeName}\" en {gap.beforeTrack}.", "fr_FR": "Aucun audio pendant {gap.durationSeconds} s ({gap.startTimecode} à {gap.endTimecode}) après « {gap.beforeName} » sur {gap.beforeTrack}.", "it_IT": "Nessun audio per {gap.durationSeconds} s (da {gap.startTimecode} a {gap.endTimecode}) dopo \"{gap.beforeName}\" su {gap.beforeTrack}.", "ja_JP": "「{gap.beforeName}」({gap.beforeTrack})の後に{gap.durationSeconds} sのオーディオの欠落があります({gap.startTimecode}~{gap.endTimecode})。", "ko_KR": "{gap.durationSeconds} s 동안 오디오 없음({gap.startTimecode}~{gap.endTimecode}): {gap.beforeTrack}의 \"{gap.beforeName}\" 뒤.", "pt_BR": "Sem áudio por {gap.durationSeconds} s ({gap.startTimecode} a {gap.endTimecode}) depois de \"{gap.beforeName}\" em {gap.beforeTrack}.", "ru_RU": "Нет звука в течение {gap.durationSeconds} с (с {gap.startTimecode} по {gap.endTimecode}) после «{gap.beforeName}» на {gap.beforeTrack}.", "zh_CN": "{gap.durationSeconds} s 无音频({gap.startTimecode} 至 {gap.endTimecode}),位于 {gap.beforeTrack} 上的“{gap.beforeName}” 之后。" } }, { "condition": { "all": [ { "field": "gap.durationSeconds", "operator": "greaterThanOrEqual", "value": { "field": "options.minSeconds" } }, { "any": [ { "field": "gap.kind", "operator": "equals", "value": "inner" }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "leading" }, { "field": "options.leading", "operator": "equals", "value": true } ] }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "trailing" }, { "field": "options.trailing", "operator": "equals", "value": true } ] } ] }, { "all": [ { "field": "gap.hasBefore", "operator": "equals", "value": false }, { "field": "gap.hasAfter", "operator": "equals", "value": false } ] } ] }, "message": { "en_US": "No audio for {gap.durationSeconds} s ({gap.startTimecode} to {gap.endTimecode}).", "de_DE": "Kein Audio für {gap.durationSeconds} s ({gap.startTimecode} bis {gap.endTimecode}).", "es_ES": "Sin audio durante {gap.durationSeconds} s (de {gap.startTimecode} a {gap.endTimecode}).", "fr_FR": "Aucun audio pendant {gap.durationSeconds} s ({gap.startTimecode} à {gap.endTimecode}).", "it_IT": "Nessun audio per {gap.durationSeconds} s (da {gap.startTimecode} a {gap.endTimecode}).", "ja_JP": "{gap.durationSeconds} sのオーディオの欠落があります({gap.startTimecode}~{gap.endTimecode})。", "ko_KR": "{gap.durationSeconds} s 동안 오디오 없음({gap.startTimecode}~{gap.endTimecode}).", "pt_BR": "Sem áudio por {gap.durationSeconds} s ({gap.startTimecode} a {gap.endTimecode}).", "ru_RU": "Нет звука в течение {gap.durationSeconds} с (с {gap.startTimecode} по {gap.endTimecode}).", "zh_CN": "{gap.durationSeconds} s 无音频({gap.startTimecode} 至 {gap.endTimecode})。" } } ], "data": { "gapStart": "gap.start", "gapEnd": "gap.end", "gapTicks": "gap.durationTicks", "kind": "gap.kind", "gapSeconds": "gap.durationSeconds", "minSeconds": "options.minSeconds" } } ``` # Clips outside the work area (/docs/rules/no-clips-outside-work-area) Reports clips entirely before the sequence in point or after its out point. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :--------------------------- | | Id | `no-clips-outside-work-area` | | Category | Static | | Default severity | warning | | Scope | `clip` | ## Options [#options] | Option | Type | Default | Description | | :---------------- | :-------- | :------ | :-------------------------- | | `includeDisabled` | `boolean` | `true` | Also report disabled clips. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-clips-outside-work-area.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-clips-outside-work-area.rule.json" { "formatVersion": 1, "id": "no-clips-outside-work-area", "name": { "en_US": "Clips outside the work area", "de_DE": "Clips außerhalb des Arbeitsbereichs", "es_ES": "Clips fuera del área de trabajo", "fr_FR": "Éléments hors de la zone de travail", "it_IT": "Clip fuori dall'area di lavoro", "ja_JP": "ワークエリア外のクリップ", "ko_KR": "작업 영역 밖의 클립", "pt_BR": "Clipes fora da área de trabalho", "ru_RU": "Клипы вне рабочей области", "zh_CN": "工作区域外的剪辑" }, "description": { "en_US": "Reports clips entirely before the sequence in point or after its out point.", "de_DE": "Meldet Clips, die vollständig vor dem In-Point oder nach dem Out-Point der Sequenz liegen.", "es_ES": "Detecta clips situados completamente antes del punto de entrada de la secuencia o después de su punto de salida.", "fr_FR": "Signale les éléments situés entièrement avant le point d'entrée ou après le point de sortie de la séquence.", "it_IT": "Segnala le clip interamente prima del punto di attacco della sequenza o dopo il punto di stacco.", "ja_JP": "全体がシーケンスのインポイントより前、またはアウトポイントより後にあるクリップを報告します。", "ko_KR": "시퀀스 시작 지점보다 완전히 앞에 있거나 종료 지점보다 완전히 뒤에 있는 클립을 보고합니다.", "pt_BR": "Relata clipes totalmente antes do ponto de entrada da sequência ou depois do ponto de saída.", "ru_RU": "Сообщает о клипах, целиком находящихся до точки входа эпизода или после его точки выхода.", "zh_CN": "报告完全位于序列入点之前或出点之后的剪辑。" }, "category": "static", "scope": "clip", "severity": "warning", "options": { "includeDisabled": { "type": "boolean", "default": true, "description": "Also report disabled clips." } }, "checks": [ { "condition": { "all": [ { "any": [ { "field": "clip.disabled", "operator": "equals", "value": false }, { "field": "options.includeDisabled", "operator": "equals", "value": true } ] }, { "field": "clip.end", "operator": "lessThanOrEqual", "value": { "field": "sequence.inPoint" } } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} lies entirely before the sequence in point ({sequence.inPointTimecode}).", "de_DE": "Clip „{clip.name}“ auf {clip.track} liegt vollständig vor dem In-Point der Sequenz ({sequence.inPointTimecode}).", "es_ES": "Clip \"{clip.name}\" en {clip.track} está completamente antes del punto de entrada de la secuencia ({sequence.inPointTimecode}).", "fr_FR": "Élément « {clip.name} » sur {clip.track} se trouve entièrement avant le point d'entrée de la séquence ({sequence.inPointTimecode}).", "it_IT": "Clip \"{clip.name}\" su {clip.track} si trova interamente prima del punto di attacco della sequenza ({sequence.inPointTimecode}).", "ja_JP": "クリップ「{clip.name}」({clip.track})は全体がシーケンスのインポイント({sequence.inPointTimecode})より前にあります。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) 시퀀스 시작 지점({sequence.inPointTimecode})보다 완전히 앞에 있습니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está totalmente antes do ponto de entrada da sequência ({sequence.inPointTimecode}).", "ru_RU": "Клип «{clip.name}» на {clip.track} целиком находится до точки входа эпизода ({sequence.inPointTimecode}).", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 完全位于序列入点({sequence.inPointTimecode})之前。" }, "data": { "side": { "literal": "before" } } }, { "condition": { "all": [ { "any": [ { "field": "clip.disabled", "operator": "equals", "value": false }, { "field": "options.includeDisabled", "operator": "equals", "value": true } ] }, { "field": "clip.start", "operator": "greaterThanOrEqual", "value": { "field": "sequence.outPoint" } } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} lies entirely after the sequence out point ({sequence.outPointTimecode}).", "de_DE": "Clip „{clip.name}“ auf {clip.track} liegt vollständig nach dem Out-Point der Sequenz ({sequence.outPointTimecode}).", "es_ES": "Clip \"{clip.name}\" en {clip.track} está completamente después del punto de salida de la secuencia ({sequence.outPointTimecode}).", "fr_FR": "Élément « {clip.name} » sur {clip.track} se trouve entièrement après le point de sortie de la séquence ({sequence.outPointTimecode}).", "it_IT": "Clip \"{clip.name}\" su {clip.track} si trova interamente dopo il punto di stacco della sequenza ({sequence.outPointTimecode}).", "ja_JP": "クリップ「{clip.name}」({clip.track})は全体がシーケンスのアウトポイント({sequence.outPointTimecode})より後にあります。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) 시퀀스 종료 지점({sequence.outPointTimecode})보다 완전히 뒤에 있습니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está totalmente depois do ponto de saída da sequência ({sequence.outPointTimecode}).", "ru_RU": "Клип «{clip.name}» на {clip.track} целиком находится после точки выхода эпизода ({sequence.outPointTimecode}).", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 完全位于序列出点({sequence.outPointTimecode})之后。" }, "data": { "side": { "literal": "after" } } } ], "data": { "inPoint": "sequence.inPoint", "outPoint": "sequence.outPoint" } } ``` # Disabled clips (/docs/rules/no-disabled-clips) Reports disabled clips, which are skipped on playback and export. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :------------------ | | Id | `no-disabled-clips` | | Category | Static | | Default severity | warning | | Scope | `clip` | ## Options [#options] This rule has no options. ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-disabled-clips.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-disabled-clips.rule.json" { "formatVersion": 1, "id": "no-disabled-clips", "name": { "en_US": "Disabled clips", "de_DE": "Deaktivierte Clips", "es_ES": "Clips desactivados", "fr_FR": "Éléments désactivés", "it_IT": "Clip disabilitate", "ja_JP": "無効なクリップ", "ko_KR": "비활성화된 클립", "pt_BR": "Clipes desativados", "ru_RU": "Отключенные клипы", "zh_CN": "已禁用的剪辑" }, "description": { "en_US": "Reports disabled clips, which are skipped on playback and export.", "de_DE": "Meldet deaktivierte Clips, die bei Wiedergabe und Export übersprungen werden.", "es_ES": "Detecta clips desactivados, que se omiten en la reproducción y la exportación.", "fr_FR": "Signale les éléments désactivés, qui sont ignorés à la lecture et à l'exportation.", "it_IT": "Segnala le clip disabilitate, che vengono ignorate in riproduzione ed esportazione.", "ja_JP": "再生時と書き出し時にスキップされる、無効なクリップを報告します。", "ko_KR": "재생 및 내보내기에서 건너뛰는 비활성화된 클립을 보고합니다.", "pt_BR": "Relata clipes desativados, que são ignorados na reprodução e na exportação.", "ru_RU": "Сообщает об отключенных клипах, которые пропускаются при воспроизведении и экспорте.", "zh_CN": "报告已禁用的剪辑,这些剪辑在播放和导出时会被跳过。" }, "category": "static", "scope": "clip", "severity": "warning", "checks": [ { "condition": { "field": "clip.disabled", "operator": "equals", "value": true }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is disabled.", "de_DE": "Clip „{clip.name}“ auf {clip.track} ist deaktiviert.", "es_ES": "Clip \"{clip.name}\" en {clip.track} está desactivado.", "fr_FR": "Élément « {clip.name} » sur {clip.track} est désactivé.", "it_IT": "Clip \"{clip.name}\" su {clip.track} è disabilitata.", "ja_JP": "クリップ「{clip.name}」({clip.track})は無効になっています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) 비활성화되어 있습니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está desativado.", "ru_RU": "Клип «{clip.name}» на {clip.track} отключен.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 已禁用。" } } ] } ``` # Duplicate effects (/docs/rules/no-duplicate-effects) Reports clips with the same effect applied more than once. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :--------------------- | | Id | `no-duplicate-effects` | | Category | Static | | Default severity | info | | Scope | `effect` | ## Options [#options] | Option | Type | Default | Description | | :------ | :--------- | :------------------------------------- | :------------------------------------------------------------------------------------- | | `allow` | `string[]` | `["AE.ADBE Crop","AE.ADBE Geometry2"]` | Match names allowed to appear several times on a clip (Crop and Transform by default). | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-duplicate-effects.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-duplicate-effects.rule.json" { "formatVersion": 1, "id": "no-duplicate-effects", "name": { "en_US": "Duplicate effects", "de_DE": "Doppelte Effekte", "es_ES": "Efectos duplicados", "fr_FR": "Effets en double", "it_IT": "Effetti duplicati", "ja_JP": "重複したエフェクト", "ko_KR": "중복 효과", "pt_BR": "Efeitos duplicados", "ru_RU": "Повторяющиеся эффекты", "zh_CN": "重复效果" }, "description": { "en_US": "Reports clips with the same effect applied more than once.", "de_DE": "Meldet Clips, auf die derselbe Effekt mehrmals angewendet wurde.", "es_ES": "Detecta clips con el mismo efecto aplicado más de una vez.", "fr_FR": "Signale les éléments auxquels le même effet est appliqué plusieurs fois.", "it_IT": "Segnala le clip a cui lo stesso effetto è applicato più volte.", "ja_JP": "同じエフェクトが複数回適用されているクリップを報告します。", "ko_KR": "같은 효과가 두 번 이상 적용된 클립을 보고합니다.", "pt_BR": "Relata clipes com o mesmo efeito aplicado mais de uma vez.", "ru_RU": "Сообщает о клипах, к которым один и тот же эффект применен несколько раз.", "zh_CN": "报告多次应用同一效果的剪辑。" }, "category": "static", "scope": "effect", "severity": "info", "options": { "allow": { "type": "string[]", "default": [ "AE.ADBE Crop", "AE.ADBE Geometry2" ], "description": "Match names allowed to appear several times on a clip (Crop and Transform by default)." } }, "checks": [ { "condition": { "all": [ { "field": "effect.count", "operator": "greaterThanOrEqual", "value": 2 }, { "field": "effect.firstOfKind", "operator": "equals", "value": true }, { "field": "effect.matchName", "operator": "notIn", "value": { "field": "options.allow" } } ] }, "message": { "en_US": { "count": "effect.count", "one": "Clip \"{clip.name}\" on {clip.track} has {effect.count} instance of \"{effect.displayName}\".", "other": "Clip \"{clip.name}\" on {clip.track} has {effect.count} instances of \"{effect.displayName}\"." }, "de_DE": { "count": "effect.count", "one": "Clip „{clip.name}“ auf {clip.track} enthält {effect.count} Instanz von „{effect.displayName}“.", "other": "Clip „{clip.name}“ auf {clip.track} enthält {effect.count} Instanzen von „{effect.displayName}“." }, "es_ES": { "count": "effect.count", "one": "Clip \"{clip.name}\" en {clip.track} tiene {effect.count} instancia de \"{effect.displayName}\".", "other": "Clip \"{clip.name}\" en {clip.track} tiene {effect.count} instancias de \"{effect.displayName}\"." }, "fr_FR": { "count": "effect.count", "one": "Élément « {clip.name} » sur {clip.track} comporte {effect.count} occurrence de l'effet « {effect.displayName} ».", "other": "Élément « {clip.name} » sur {clip.track} comporte {effect.count} occurrences de l'effet « {effect.displayName} »." }, "it_IT": { "count": "effect.count", "one": "Clip \"{clip.name}\" su {clip.track} ha {effect.count} istanza di \"{effect.displayName}\".", "other": "Clip \"{clip.name}\" su {clip.track} ha {effect.count} istanze di \"{effect.displayName}\"." }, "ja_JP": "クリップ「{clip.name}」({clip.track})に「{effect.displayName}」が{effect.count}個適用されています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"에 \"{effect.displayName}\" 효과가 {effect.count}개 적용되어 있습니다.", "pt_BR": { "count": "effect.count", "one": "Clipe \"{clip.name}\" em {clip.track} tem {effect.count} instância de \"{effect.displayName}\".", "other": "Clipe \"{clip.name}\" em {clip.track} tem {effect.count} instâncias de \"{effect.displayName}\"." }, "ru_RU": { "count": "effect.count", "one": "Клип «{clip.name}» на {clip.track} содержит {effect.count} экземпляр эффекта «{effect.displayName}».", "few": "Клип «{clip.name}» на {clip.track} содержит {effect.count} экземпляра эффекта «{effect.displayName}».", "many": "Клип «{clip.name}» на {clip.track} содержит {effect.count} экземпляров эффекта «{effect.displayName}».", "other": "Клип «{clip.name}» на {clip.track} содержит {effect.count} экземпляра эффекта «{effect.displayName}»." }, "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 应用了 {effect.count} 个“{effect.displayName}”实例。" } } ], "data": { "matchName": "effect.matchName", "displayName": "effect.displayName", "count": "effect.count" } } ``` # Empty markers (/docs/rules/no-empty-markers) Reports markers with neither a name nor a comment. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :----------------- | | Id | `no-empty-markers` | | Category | Static | | Default severity | info | | Scope | `marker` | ## Options [#options] | Option | Type | Default | Description | | :------------ | :--------- | :------ | :---------------------------------------------------------- | | `ignoreTypes` | `string[]` | `[]` | Marker types allowed to be empty. | | `requireName` | `boolean` | `false` | Report markers without a name even when they have comments. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-empty-markers.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-empty-markers.rule.json" { "formatVersion": 1, "id": "no-empty-markers", "name": { "en_US": "Empty markers", "de_DE": "Leere Marken", "es_ES": "Marcadores vacíos", "fr_FR": "Marques vides", "it_IT": "Marcatori vuoti", "ja_JP": "空のマーカー", "ko_KR": "빈 마커", "pt_BR": "Marcadores vazios", "ru_RU": "Пустые маркеры", "zh_CN": "空标记" }, "description": { "en_US": "Reports markers with neither a name nor a comment.", "de_DE": "Meldet Marken ohne Namen und ohne Kommentar.", "es_ES": "Detecta marcadores sin nombre ni comentario.", "fr_FR": "Signale les marques sans nom ni commentaire.", "it_IT": "Segnala i marcatori senza nome e senza commento.", "ja_JP": "名前もコメントもないマーカーを報告します。", "ko_KR": "이름과 주석이 모두 없는 마커를 보고합니다.", "pt_BR": "Relata marcadores sem nome e sem comentário.", "ru_RU": "Сообщает о маркерах без имени и без комментария.", "zh_CN": "报告既没有名称也没有注释的标记。" }, "category": "static", "scope": "marker", "severity": "info", "options": { "ignoreTypes": { "type": "string[]", "default": [], "description": "Marker types allowed to be empty." }, "requireName": { "type": "boolean", "default": false, "description": "Report markers without a name even when they have comments." } }, "checks": [ { "condition": { "all": [ { "field": "marker.type", "operator": "notIn", "value": { "field": "options.ignoreTypes" } }, { "field": "marker.name", "operator": "matches", "value": "^\\s*$" }, { "field": "marker.comments", "operator": "matches", "value": "^\\s*$" } ] }, "message": { "en_US": "{labels.markerType} marker at {marker.startTimecode} has no name and no comment.", "de_DE": "{labels.markerType}-Marke bei {marker.startTimecode} hat weder Namen noch Kommentar.", "es_ES": "El marcador de tipo {labels.markerType} en {marker.startTimecode} no tiene nombre ni comentario.", "fr_FR": "La marque de type {labels.markerType} à {marker.startTimecode} n'a ni nom ni commentaire.", "it_IT": "Il marcatore di tipo {labels.markerType} a {marker.startTimecode} non ha né un nome né un commento.", "ja_JP": "{marker.startTimecode}の{labels.markerType}マーカーに名前もコメントもありません。", "ko_KR": "{marker.startTimecode}의 {labels.markerType} 마커에 이름과 주석이 없습니다.", "pt_BR": "O marcador de {labels.markerType} em {marker.startTimecode} não tem nome nem comentário.", "ru_RU": "Маркер ({labels.markerType}) в позиции {marker.startTimecode} не имеет ни имени, ни комментария.", "zh_CN": "位于 {marker.startTimecode} 的{labels.markerType}标记没有名称和注释。" } }, { "condition": { "all": [ { "field": "marker.type", "operator": "notIn", "value": { "field": "options.ignoreTypes" } }, { "field": "marker.name", "operator": "matches", "value": "^\\s*$" }, { "field": "options.requireName", "operator": "equals", "value": true } ] }, "message": { "en_US": "{labels.markerType} marker at {marker.startTimecode} has no name.", "de_DE": "{labels.markerType}-Marke bei {marker.startTimecode} hat keinen Namen.", "es_ES": "El marcador de tipo {labels.markerType} en {marker.startTimecode} no tiene nombre.", "fr_FR": "La marque de type {labels.markerType} à {marker.startTimecode} n'a pas de nom.", "it_IT": "Il marcatore di tipo {labels.markerType} a {marker.startTimecode} non ha un nome.", "ja_JP": "{marker.startTimecode}の{labels.markerType}マーカーに名前がありません。", "ko_KR": "{marker.startTimecode}의 {labels.markerType} 마커에 이름이 없습니다.", "pt_BR": "O marcador de {labels.markerType} em {marker.startTimecode} não tem nome.", "ru_RU": "Маркер ({labels.markerType}) в позиции {marker.startTimecode} не имеет имени.", "zh_CN": "位于 {marker.startTimecode} 的{labels.markerType}标记没有名称。" } } ], "labels": { "markerType": { "field": "marker.type", "values": { "Comment": { "en_US": "Comment", "de_DE": "Kommentar", "es_ES": "Comentario", "fr_FR": "Commentaire", "it_IT": "Commento", "ja_JP": "コメント", "ko_KR": "주석", "pt_BR": "Comentário", "ru_RU": "Комментарий", "zh_CN": "注释" }, "Chapter": { "en_US": "Chapter", "de_DE": "Kapitel", "es_ES": "Capítulo", "fr_FR": "Chapitre", "it_IT": "Capitolo", "ja_JP": "チャプター", "ko_KR": "챕터", "pt_BR": "Capítulo", "ru_RU": "Глава", "zh_CN": "章节" }, "WebLink": { "en_US": "Web Link", "de_DE": "Weblink", "es_ES": "Vínculo web", "fr_FR": "Lien Web", "it_IT": "Collegamento Web", "ja_JP": "Web リンク", "ko_KR": "웹 링크", "pt_BR": "Link da Web", "ru_RU": "Веб-ссылка", "zh_CN": "Web 链接" }, "FLVCuePoint": { "en_US": "Flash Cue Point", "de_DE": "Flash-Cue-Point", "es_ES": "Punto de referencia de Flash", "fr_FR": "Point de repère Flash", "it_IT": "Cue point Flash", "ja_JP": "Flash キューポイント", "ko_KR": "Flash 큐 포인트", "pt_BR": "Ponto de sinalização do Flash", "ru_RU": "Ключевая точка Flash", "zh_CN": "Flash 提示点" }, "Segmentation": { "en_US": "Segmentation", "de_DE": "Segmentierung", "es_ES": "Segmentación", "fr_FR": "Segmentation", "it_IT": "Segmentazione", "ja_JP": "セグメンテーション", "ko_KR": "세그먼트화", "pt_BR": "Segmentação", "ru_RU": "Сегментация", "zh_CN": "分段" } } } }, "data": { "type": "marker.type", "colorIndex": "marker.colorIndex" } } ``` # Empty tracks (/docs/rules/no-empty-tracks) Reports tracks without clips. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :---------------- | | Id | `no-empty-tracks` | | Category | Static | | Default severity | info | | Scope | `track` | ## Options [#options] | Option | Type | Default | Description | | :-------------- | :-------- | :------ | :--------------------------------------------------------------------------------------- | | `ignoreTopmost` | `boolean` | `true` | Ignore empty tracks above the last used video track and below the last used audio track. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-empty-tracks.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-empty-tracks.rule.json" { "formatVersion": 1, "id": "no-empty-tracks", "name": { "en_US": "Empty tracks", "de_DE": "Leere Spuren", "es_ES": "Pistas vacías", "fr_FR": "Pistes vides", "it_IT": "Tracce vuote", "ja_JP": "空のトラック", "ko_KR": "빈 트랙", "pt_BR": "Trilhas vazias", "ru_RU": "Пустые дорожки", "zh_CN": "空轨道" }, "description": { "en_US": "Reports tracks without clips.", "de_DE": "Meldet Spuren ohne Clips.", "es_ES": "Detecta pistas sin clips.", "fr_FR": "Signale les pistes sans élément.", "it_IT": "Segnala le tracce senza clip.", "ja_JP": "クリップのないトラックを報告します。", "ko_KR": "클립이 없는 트랙을 보고합니다.", "pt_BR": "Relata trilhas sem clipes.", "ru_RU": "Сообщает о дорожках без клипов.", "zh_CN": "报告不包含剪辑的轨道。" }, "category": "static", "scope": "track", "severity": "info", "options": { "ignoreTopmost": { "type": "boolean", "default": true, "description": "Ignore empty tracks above the last used video track and below the last used audio track." } }, "checks": [ { "condition": { "all": [ { "field": "sequence.clipCount", "operator": "greaterThan", "value": 0 }, { "field": "track.clipCount", "operator": "equals", "value": 0 }, { "any": [ { "field": "options.ignoreTopmost", "operator": "equals", "value": false }, { "field": "track.beyondLastUsed", "operator": "equals", "value": false } ] } ] }, "message": { "en_US": "Track {track.ref} (\"{track.name}\") is empty.", "de_DE": "Spur {track.ref} („{track.name}“) ist leer.", "es_ES": "Pista {track.ref} (\"{track.name}\") está vacía.", "fr_FR": "Piste {track.ref} (« {track.name} ») est vide.", "it_IT": "Traccia {track.ref} (\"{track.name}\") è vuota.", "ja_JP": "トラック {track.ref}(「{track.name}」)は空です。", "ko_KR": "트랙 {track.ref}(\"{track.name}\")이(가) 비어 있습니다.", "pt_BR": "Trilha {track.ref} (\"{track.name}\") está vazia.", "ru_RU": "Дорожка {track.ref} («{track.name}») не содержит клипов.", "zh_CN": "轨道 {track.ref}(“{track.name}”) 为空。" } } ], "data": { "trackName": "track.name" } } ``` # Invisible video clips (/docs/rules/no-invisible-video-clips) Reports video clips at 0 % opacity or 0 % scale, which render nothing. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :------------------------- | | Id | `no-invisible-video-clips` | | Category | Static | | Default severity | warning | | Scope | `clip` | ## Options [#options] This rule has no options. ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-invisible-video-clips.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-invisible-video-clips.rule.json" { "formatVersion": 1, "id": "no-invisible-video-clips", "name": { "en_US": "Invisible video clips", "de_DE": "Unsichtbare Videoclips", "es_ES": "Clips de vídeo invisibles", "fr_FR": "Éléments vidéo invisibles", "it_IT": "Clip video invisibili", "ja_JP": "表示されないビデオクリップ", "ko_KR": "보이지 않는 비디오 클립", "pt_BR": "Clipes de vídeo invisíveis", "ru_RU": "Невидимые видеоклипы", "zh_CN": "不可见的视频剪辑" }, "description": { "en_US": "Reports video clips at 0 % opacity or 0 % scale, which render nothing.", "de_DE": "Meldet Videoclips mit 0 % Deckkraft oder 0 % Skalierung, die nichts anzeigen.", "es_ES": "Detecta clips de vídeo con una opacidad del 0 % o una escala del 0 %, que no muestran nada.", "fr_FR": "Signale les éléments vidéo à 0 % d'opacité ou à 0 % d'échelle, qui n'affichent rien.", "it_IT": "Segnala le clip video con opacità 0 % o scala 0 %, che non mostrano nulla.", "ja_JP": "不透明度 0 % またはスケール 0 % で、何も描画されないビデオクリップを報告します。", "ko_KR": "불투명도 0 % 또는 비율 0 %로 아무것도 렌더링되지 않는 비디오 클립을 보고합니다.", "pt_BR": "Relata clipes de vídeo com opacidade de 0 % ou escala de 0 %, que não renderizam nada.", "ru_RU": "Сообщает о видеоклипах с непрозрачностью 0 % или масштабом 0 %, которые ничего не отображают.", "zh_CN": "报告不透明度为 0 % 或缩放为 0 % 的视频剪辑,这些剪辑不会渲染任何内容。" }, "category": "static", "scope": "clip", "severity": "warning", "checks": [ { "condition": { "all": [ { "field": "clip.disabled", "operator": "equals", "value": false }, { "field": "clip.opacityAnimated", "operator": "equals", "value": false }, { "field": "clip.opacity", "operator": "lessThanOrEqual", "value": 0 } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is invisible: opacity is {clip.opacity} %.", "de_DE": "Clip „{clip.name}“ auf {clip.track} ist unsichtbar: Deckkraft beträgt {clip.opacity} %.", "es_ES": "Clip \"{clip.name}\" en {clip.track} es invisible: la opacidad es del {clip.opacity} %.", "fr_FR": "Élément « {clip.name} » sur {clip.track} est invisible : l'opacité est de {clip.opacity} %.", "it_IT": "Clip \"{clip.name}\" su {clip.track} è invisibile: l'opacità è {clip.opacity} %.", "ja_JP": "クリップ「{clip.name}」({clip.track})は表示されません(不透明度 {clip.opacity} %)。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) 보이지 않습니다. 불투명도가 {clip.opacity} %입니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está invisível: a opacidade é {clip.opacity} %.", "ru_RU": "Клип «{clip.name}» на {clip.track} невидим: непрозрачность {clip.opacity} %.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 不可见:不透明度为 {clip.opacity} %。" }, "data": { "reason": { "literal": "opacity" }, "value": "clip.opacity" } }, { "condition": { "all": [ { "field": "clip.disabled", "operator": "equals", "value": false }, { "field": "clip.scaleAnimated", "operator": "equals", "value": false }, { "field": "clip.scale", "operator": "lessThanOrEqual", "value": 0 } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is invisible: scale is {clip.scale} %.", "de_DE": "Clip „{clip.name}“ auf {clip.track} ist unsichtbar: Skalierung beträgt {clip.scale} %.", "es_ES": "Clip \"{clip.name}\" en {clip.track} es invisible: la escala es del {clip.scale} %.", "fr_FR": "Élément « {clip.name} » sur {clip.track} est invisible : l'échelle est de {clip.scale} %.", "it_IT": "Clip \"{clip.name}\" su {clip.track} è invisibile: la scala è {clip.scale} %.", "ja_JP": "クリップ「{clip.name}」({clip.track})は表示されません(スケール {clip.scale} %)。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) 보이지 않습니다. 비율 조정이 {clip.scale} %입니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está invisível: a escala é {clip.scale} %.", "ru_RU": "Клип «{clip.name}» на {clip.track} невидим: масштаб {clip.scale} %.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 不可见:缩放为 {clip.scale} %。" }, "data": { "reason": { "literal": "scale" }, "value": "clip.scale" } } ] } ``` # Markers outside the work area (/docs/rules/no-markers-outside-work-area) Reports markers after the last clip or outside the sequence in/out range. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :----------------------------- | | Id | `no-markers-outside-work-area` | | Category | Static | | Default severity | warning | | Scope | `marker` | ## Options [#options] | Option | Type | Default | Description | | :------------- | :--------- | :------ | :----------------------------------------------------- | | `respectInOut` | `boolean` | `true` | Also report markers outside the sequence in/out range. | | `ignoreTypes` | `string[]` | `[]` | Marker types never reported. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-markers-outside-work-area.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-markers-outside-work-area.rule.json" { "formatVersion": 1, "id": "no-markers-outside-work-area", "name": { "en_US": "Markers outside the work area", "de_DE": "Marken außerhalb des Arbeitsbereichs", "es_ES": "Marcadores fuera del área de trabajo", "fr_FR": "Marques hors de la zone de travail", "it_IT": "Marcatori fuori dall'area di lavoro", "ja_JP": "ワークエリア外のマーカー", "ko_KR": "작업 영역 밖의 마커", "pt_BR": "Marcadores fora da área de trabalho", "ru_RU": "Маркеры вне рабочей области", "zh_CN": "工作区域外的标记" }, "description": { "en_US": "Reports markers after the last clip or outside the sequence in/out range.", "de_DE": "Meldet Marken nach dem letzten Clip oder außerhalb des In/Out-Bereichs der Sequenz.", "es_ES": "Detecta marcadores situados después del último clip o fuera del intervalo de entrada/salida de la secuencia.", "fr_FR": "Signale les marques situées après le dernier élément ou en dehors des points d'entrée et de sortie de la séquence.", "it_IT": "Segnala i marcatori dopo l'ultima clip o fuori dall'intervallo di attacco/stacco della sequenza.", "ja_JP": "最後のクリップより後、またはシーケンスのイン/アウトの範囲外にあるマーカーを報告します。", "ko_KR": "마지막 클립 뒤나 시퀀스 시작/종료 범위 밖에 있는 마커를 보고합니다.", "pt_BR": "Relata marcadores depois do último clipe ou fora do intervalo de entrada/saída da sequência.", "ru_RU": "Сообщает о маркерах после последнего клипа или вне диапазона точек входа и выхода эпизода.", "zh_CN": "报告位于最后一个剪辑之后或序列入点/出点范围之外的标记。" }, "category": "static", "scope": "marker", "severity": "warning", "options": { "respectInOut": { "type": "boolean", "default": true, "description": "Also report markers outside the sequence in/out range." }, "ignoreTypes": { "type": "string[]", "default": [], "description": "Marker types never reported." } }, "checks": [ { "condition": { "all": [ { "field": "marker.type", "operator": "notIn", "value": { "field": "options.ignoreTypes" } }, { "field": "marker.start", "operator": "greaterThanOrEqual", "value": { "field": "sequence.end" } } ] }, "message": { "en_US": "{labels.marker} at {marker.startTimecode} is after the end of the sequence ({sequence.endTimecode}).", "de_DE": "{labels.marker} bei {marker.startTimecode} liegt nach dem Ende der Sequenz ({sequence.endTimecode}).", "es_ES": "{labels.marker} en {marker.startTimecode} está después del final de la secuencia ({sequence.endTimecode}).", "fr_FR": "{labels.marker} à {marker.startTimecode} se trouve après la fin de la séquence ({sequence.endTimecode}).", "it_IT": "{labels.marker} a {marker.startTimecode} si trova dopo la fine della sequenza ({sequence.endTimecode}).", "ja_JP": "{marker.startTimecode}の{labels.marker}はシーケンスの終わり({sequence.endTimecode})より後にあります。", "ko_KR": "{marker.startTimecode}의 {labels.marker}이(가) 시퀀스 끝({sequence.endTimecode})보다 뒤에 있습니다.", "pt_BR": "{labels.marker} em {marker.startTimecode} está depois do fim da sequência ({sequence.endTimecode}).", "ru_RU": "{labels.marker} в позиции {marker.startTimecode} находится после конца эпизода ({sequence.endTimecode}).", "zh_CN": "位于 {marker.startTimecode} 的{labels.marker}在序列结尾({sequence.endTimecode})之后。" }, "data": { "reason": { "literal": "after-end" } } }, { "condition": { "all": [ { "field": "marker.type", "operator": "notIn", "value": { "field": "options.ignoreTypes" } }, { "field": "options.respectInOut", "operator": "equals", "value": true }, { "field": "marker.start", "operator": "lessThan", "value": { "field": "sequence.inPoint" } } ] }, "message": { "en_US": "{labels.marker} at {marker.startTimecode} is before the sequence in point ({sequence.inPointTimecode}).", "de_DE": "{labels.marker} bei {marker.startTimecode} liegt vor dem In-Point der Sequenz ({sequence.inPointTimecode}).", "es_ES": "{labels.marker} en {marker.startTimecode} está antes del punto de entrada de la secuencia ({sequence.inPointTimecode}).", "fr_FR": "{labels.marker} à {marker.startTimecode} se trouve avant le point d'entrée de la séquence ({sequence.inPointTimecode}).", "it_IT": "{labels.marker} a {marker.startTimecode} si trova prima del punto di attacco della sequenza ({sequence.inPointTimecode}).", "ja_JP": "{marker.startTimecode}の{labels.marker}はシーケンスのインポイント({sequence.inPointTimecode})より前にあります。", "ko_KR": "{marker.startTimecode}의 {labels.marker}이(가) 시퀀스 시작 지점({sequence.inPointTimecode})보다 앞에 있습니다.", "pt_BR": "{labels.marker} em {marker.startTimecode} está antes do ponto de entrada da sequência ({sequence.inPointTimecode}).", "ru_RU": "{labels.marker} в позиции {marker.startTimecode} находится до точки входа эпизода ({sequence.inPointTimecode}).", "zh_CN": "位于 {marker.startTimecode} 的{labels.marker}在序列入点({sequence.inPointTimecode})之前。" }, "data": { "reason": { "literal": "before-in" } } }, { "condition": { "all": [ { "field": "marker.type", "operator": "notIn", "value": { "field": "options.ignoreTypes" } }, { "field": "options.respectInOut", "operator": "equals", "value": true }, { "field": "marker.start", "operator": "greaterThanOrEqual", "value": { "field": "sequence.outPoint" } } ] }, "message": { "en_US": "{labels.marker} at {marker.startTimecode} is after the sequence out point ({sequence.outPointTimecode}).", "de_DE": "{labels.marker} bei {marker.startTimecode} liegt nach dem Out-Point der Sequenz ({sequence.outPointTimecode}).", "es_ES": "{labels.marker} en {marker.startTimecode} está después del punto de salida de la secuencia ({sequence.outPointTimecode}).", "fr_FR": "{labels.marker} à {marker.startTimecode} se trouve après le point de sortie de la séquence ({sequence.outPointTimecode}).", "it_IT": "{labels.marker} a {marker.startTimecode} si trova dopo il punto di stacco della sequenza ({sequence.outPointTimecode}).", "ja_JP": "{marker.startTimecode}の{labels.marker}はシーケンスのアウトポイント({sequence.outPointTimecode})より後にあります。", "ko_KR": "{marker.startTimecode}의 {labels.marker}이(가) 시퀀스 종료 지점({sequence.outPointTimecode})보다 뒤에 있습니다.", "pt_BR": "{labels.marker} em {marker.startTimecode} está depois do ponto de saída da sequência ({sequence.outPointTimecode}).", "ru_RU": "{labels.marker} в позиции {marker.startTimecode} находится после точки выхода эпизода ({sequence.outPointTimecode}).", "zh_CN": "位于 {marker.startTimecode} 的{labels.marker}在序列出点({sequence.outPointTimecode})之后。" }, "data": { "reason": { "literal": "after-out" } } } ], "labels": { "markerType": { "field": "marker.type", "values": { "Comment": { "en_US": "Comment", "de_DE": "Kommentar", "es_ES": "Comentario", "fr_FR": "Commentaire", "it_IT": "Commento", "ja_JP": "コメント", "ko_KR": "주석", "pt_BR": "Comentário", "ru_RU": "Комментарий", "zh_CN": "注释" }, "Chapter": { "en_US": "Chapter", "de_DE": "Kapitel", "es_ES": "Capítulo", "fr_FR": "Chapitre", "it_IT": "Capitolo", "ja_JP": "チャプター", "ko_KR": "챕터", "pt_BR": "Capítulo", "ru_RU": "Глава", "zh_CN": "章节" }, "WebLink": { "en_US": "Web Link", "de_DE": "Weblink", "es_ES": "Vínculo web", "fr_FR": "Lien Web", "it_IT": "Collegamento Web", "ja_JP": "Web リンク", "ko_KR": "웹 링크", "pt_BR": "Link da Web", "ru_RU": "Веб-ссылка", "zh_CN": "Web 链接" }, "FLVCuePoint": { "en_US": "Flash Cue Point", "de_DE": "Flash-Cue-Point", "es_ES": "Punto de referencia de Flash", "fr_FR": "Point de repère Flash", "it_IT": "Cue point Flash", "ja_JP": "Flash キューポイント", "ko_KR": "Flash 큐 포인트", "pt_BR": "Ponto de sinalização do Flash", "ru_RU": "Ключевая точка Flash", "zh_CN": "Flash 提示点" }, "Segmentation": { "en_US": "Segmentation", "de_DE": "Segmentierung", "es_ES": "Segmentación", "fr_FR": "Segmentation", "it_IT": "Segmentazione", "ja_JP": "セグメンテーション", "ko_KR": "세그먼트화", "pt_BR": "Segmentação", "ru_RU": "Сегментация", "zh_CN": "分段" } } }, "marker": { "field": "marker.named", "values": { "true": { "en_US": "Marker \"{marker.name}\" ({labels.markerType})", "de_DE": "Marke „{marker.name}“ ({labels.markerType})", "es_ES": "Marcador \"{marker.name}\" ({labels.markerType})", "fr_FR": "Marque « {marker.name} » ({labels.markerType})", "it_IT": "Marcatore \"{marker.name}\" ({labels.markerType})", "ja_JP": "マーカー「{marker.name}」({labels.markerType})", "ko_KR": "마커 \"{marker.name}\"({labels.markerType})", "pt_BR": "Marcador \"{marker.name}\" ({labels.markerType})", "ru_RU": "Маркер «{marker.name}» ({labels.markerType})", "zh_CN": "标记“{marker.name}”({labels.markerType})" }, "false": { "en_US": "Unnamed marker ({labels.markerType})", "de_DE": "Unbenannte Marke ({labels.markerType})", "es_ES": "Marcador sin nombre ({labels.markerType})", "fr_FR": "Marque sans nom ({labels.markerType})", "it_IT": "Marcatore senza nome ({labels.markerType})", "ja_JP": "名前のないマーカー({labels.markerType})", "ko_KR": "이름 없는 마커({labels.markerType})", "pt_BR": "Marcador sem nome ({labels.markerType})", "ru_RU": "Маркер без имени ({labels.markerType})", "zh_CN": "未命名标记({labels.markerType})" } } } }, "data": { "sequenceEnd": "sequence.end", "inPoint": "sequence.inPoint", "outPoint": "sequence.outPoint" } } ``` # Muted tracks (/docs/rules/no-muted-tracks) Reports muted tracks that carry clips, which are left out of the export. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :---------------- | | Id | `no-muted-tracks` | | Category | Static | | Default severity | warning | | Scope | `track` | ## Options [#options] | Option | Type | Default | Description | | :------------- | :-------- | :------ | :-------------------------------------------------------------------------------- | | `includeVideo` | `boolean` | `false` | Also report muted video tracks. Off until isMuted() is verified for video tracks. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-muted-tracks.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-muted-tracks.rule.json" { "formatVersion": 1, "id": "no-muted-tracks", "name": { "en_US": "Muted tracks", "de_DE": "Stummgeschaltete Spuren", "es_ES": "Pistas silenciadas", "fr_FR": "Pistes muettes", "it_IT": "Tracce con audio disattivato", "ja_JP": "ミュートされたトラック", "ko_KR": "음소거된 트랙", "pt_BR": "Trilhas sem áudio", "ru_RU": "Дорожки с отключенным звуком", "zh_CN": "静音轨道" }, "description": { "en_US": "Reports muted tracks that carry clips, which are left out of the export.", "de_DE": "Meldet stummgeschaltete Spuren mit Clips, die beim Export fehlen.", "es_ES": "Detecta pistas silenciadas que contienen clips, que quedan fuera de la exportación.", "fr_FR": "Signale les pistes muettes qui contiennent des éléments, lesquels sont exclus de l'exportation.", "it_IT": "Segnala le tracce con audio disattivato che contengono clip, escluse dall'esportazione.", "ja_JP": "クリップがあるのにミュートされ、書き出しから除外されるトラックを報告します。", "ko_KR": "클립이 있으나 음소거되어 내보내기에서 제외되는 트랙을 보고합니다.", "pt_BR": "Relata trilhas sem áudio que contêm clipes, que ficam de fora da exportação.", "ru_RU": "Сообщает о дорожках с отключенным звуком, содержащих клипы, которые не попадут в экспорт.", "zh_CN": "报告包含剪辑的静音轨道,这些轨道不会包含在导出中。" }, "category": "static", "scope": "track", "severity": "warning", "options": { "includeVideo": { "type": "boolean", "default": false, "description": "Also report muted video tracks. Off until isMuted() is verified for video tracks." } }, "checks": [ { "condition": { "all": [ { "field": "track.muted", "operator": "equals", "value": true }, { "field": "track.audibleClipCount", "operator": "greaterThan", "value": 0 }, { "any": [ { "field": "track.type", "operator": "equals", "value": "audio" }, { "field": "options.includeVideo", "operator": "equals", "value": true } ] } ] }, "message": { "en_US": { "count": "track.audibleClipCount", "one": "Track {track.ref} (\"{track.name}\") is muted and carries {track.audibleClipCount} clip.", "other": "Track {track.ref} (\"{track.name}\") is muted and carries {track.audibleClipCount} clips." }, "de_DE": { "count": "track.audibleClipCount", "one": "Spur {track.ref} („{track.name}“) ist stummgeschaltet und enthält {track.audibleClipCount} Clip.", "other": "Spur {track.ref} („{track.name}“) ist stummgeschaltet und enthält {track.audibleClipCount} Clips." }, "es_ES": { "count": "track.audibleClipCount", "one": "Pista {track.ref} (\"{track.name}\") está silenciada y contiene {track.audibleClipCount} clip.", "other": "Pista {track.ref} (\"{track.name}\") está silenciada y contiene {track.audibleClipCount} clips." }, "fr_FR": { "count": "track.audibleClipCount", "one": "Piste {track.ref} (« {track.name} ») est muette et contient {track.audibleClipCount} élément.", "other": "Piste {track.ref} (« {track.name} ») est muette et contient {track.audibleClipCount} éléments." }, "it_IT": { "count": "track.audibleClipCount", "one": "Traccia {track.ref} (\"{track.name}\") ha l'audio disattivato e contiene {track.audibleClipCount} clip.", "other": "Traccia {track.ref} (\"{track.name}\") ha l'audio disattivato e contiene {track.audibleClipCount} clip." }, "ja_JP": "トラック {track.ref}(「{track.name}」)はミュートされていますが、{track.audibleClipCount}個のクリップがあります。", "ko_KR": "트랙 {track.ref}(\"{track.name}\")이(가) 음소거되어 있으며 클립 {track.audibleClipCount}개가 있습니다.", "pt_BR": { "count": "track.audibleClipCount", "one": "Trilha {track.ref} (\"{track.name}\") está sem áudio e contém {track.audibleClipCount} clipe.", "other": "Trilha {track.ref} (\"{track.name}\") está sem áudio e contém {track.audibleClipCount} clipes." }, "ru_RU": { "count": "track.audibleClipCount", "one": "Дорожка {track.ref} («{track.name}»): звук отключен, но дорожка содержит {track.audibleClipCount} клип.", "few": "Дорожка {track.ref} («{track.name}»): звук отключен, но дорожка содержит {track.audibleClipCount} клипа.", "many": "Дорожка {track.ref} («{track.name}»): звук отключен, но дорожка содержит {track.audibleClipCount} клипов.", "other": "Дорожка {track.ref} («{track.name}»): звук отключен, но дорожка содержит {track.audibleClipCount} клипа." }, "zh_CN": "轨道 {track.ref}(“{track.name}”) 已静音,其中包含 {track.audibleClipCount} 个剪辑。" }, "location": "track.firstClipStart" } ], "data": { "clipCount": "track.audibleClipCount", "trackName": "track.name" } } ``` # Offline media (/docs/rules/no-offline-media) Reports clips whose source media is offline. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :----------------- | | Id | `no-offline-media` | | Category | Static | | Default severity | error | | Scope | `clip` | ## Options [#options] This rule has no options. ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-offline-media.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-offline-media.rule.json" { "formatVersion": 1, "id": "no-offline-media", "name": { "en_US": "Offline media", "de_DE": "Offline-Medien", "es_ES": "Medios sin conexión", "fr_FR": "Médias hors ligne", "it_IT": "Media non in linea", "ja_JP": "オフラインメディア", "ko_KR": "오프라인 미디어", "pt_BR": "Mídia offline", "ru_RU": "Автономные медиафайлы", "zh_CN": "脱机媒体" }, "description": { "en_US": "Reports clips whose source media is offline.", "de_DE": "Meldet Clips, deren Quellmedien offline sind.", "es_ES": "Detecta clips cuyos medios de origen están sin conexión.", "fr_FR": "Signale les éléments dont le média source est hors ligne.", "it_IT": "Segnala le clip il cui media sorgente non è in linea.", "ja_JP": "ソースメディアがオフラインのクリップを報告します。", "ko_KR": "소스 미디어가 오프라인인 클립을 보고합니다.", "pt_BR": "Relata clipes cuja mídia de origem está offline.", "ru_RU": "Сообщает о клипах, исходные медиафайлы которых находятся в автономном режиме.", "zh_CN": "报告源媒体处于脱机状态的剪辑。" }, "category": "static", "scope": "clip", "severity": "error", "checks": [ { "condition": { "field": "clip.source.offline", "operator": "equals", "value": true }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} uses offline media \"{clip.source.name}\".", "de_DE": "Clip „{clip.name}“ auf {clip.track} verwendet Offline-Medien „{clip.source.name}“.", "es_ES": "Clip \"{clip.name}\" en {clip.track} usa medios sin conexión \"{clip.source.name}\".", "fr_FR": "Élément « {clip.name} » sur {clip.track} utilise le média hors ligne « {clip.source.name} ».", "it_IT": "Clip \"{clip.name}\" su {clip.track} usa il media non in linea \"{clip.source.name}\".", "ja_JP": "クリップ「{clip.name}」({clip.track})はオフラインメディア「{clip.source.name}」を使用しています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) 오프라인 미디어 \"{clip.source.name}\"을(를) 사용합니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} usa a mídia offline \"{clip.source.name}\".", "ru_RU": "Клип «{clip.name}» на {clip.track} использует автономный медиафайл «{clip.source.name}».", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 使用了脱机媒体“{clip.source.name}”。" } } ], "data": { "projectItemId": "clip.source.projectItemId", "sourceName": "clip.source.name", "mediaPath": "clip.source.mediaPath" } } ``` # Out-of-sync audio and video (/docs/rules/no-out-of-sync-av) Reports audio clips offset from the video clip of the same source they play under. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :-------------------------------------------------------------------------------- | | Id | `no-out-of-sync-av` | | Category | Static | | Default severity | warning | | Scope | [`av-sync-pairs`](/docs/reference/computed-scopes#av-sync-pairs) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :--------------- | :--------- | :----------------------------------------- | :----------------------------------------- | | `minDriftFrames` | `number` | `1` | Drift below this many frames is tolerated. | | `kinds` | `string[]` | `["media","multicam","merged","sequence"]` | Source kinds compared. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-out-of-sync-av.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-out-of-sync-av.rule.json" { "formatVersion": 1, "id": "no-out-of-sync-av", "name": { "en_US": "Out-of-sync audio and video", "de_DE": "Asynchrones Audio und Video", "es_ES": "Audio y vídeo desincronizados", "fr_FR": "Audio et vidéo désynchronisés", "it_IT": "Audio e video non sincronizzati", "ja_JP": "オーディオとビデオの同期ずれ", "ko_KR": "동기화되지 않은 오디오 및 비디오", "pt_BR": "Áudio e vídeo fora de sincronia", "ru_RU": "Рассинхронизация аудио и видео", "zh_CN": "音视频不同步" }, "description": { "en_US": "Reports audio clips offset from the video clip of the same source they play under.", "de_DE": "Meldet Audioclips, die gegenüber dem darüberliegenden Videoclip derselben Quelle versetzt sind.", "es_ES": "Detecta clips de audio desplazados respecto al clip de vídeo del mismo origen con el que se reproducen.", "fr_FR": "Signale les éléments audio décalés par rapport à l'élément vidéo de la même source sous lequel ils sont lus.", "it_IT": "Segnala le clip audio sfasate rispetto alla clip video della stessa sorgente sotto cui vengono riprodotte.", "ja_JP": "重なっている同じソースのビデオクリップに対してずれているオーディオクリップを報告します。", "ko_KR": "함께 재생되는 같은 소스의 비디오 클립과 어긋난 오디오 클립을 보고합니다.", "pt_BR": "Relata clipes de áudio deslocados em relação ao clipe de vídeo da mesma origem sob o qual são reproduzidos.", "ru_RU": "Сообщает об аудиоклипах, смещенных относительно видеоклипа из того же источника, под которым они воспроизводятся.", "zh_CN": "报告与其下方播放的同一源视频剪辑存在偏移的音频剪辑。" }, "category": "static", "scope": "av-sync-pairs", "severity": "warning", "options": { "minDriftFrames": { "type": "number", "default": 1, "description": "Drift below this many frames is tolerated." }, "kinds": { "type": "string[]", "default": [ "media", "multicam", "merged", "sequence" ], "description": "Source kinds compared." } }, "checks": [ { "condition": { "all": [ { "field": "pair.absDriftFrames", "operator": "greaterThanOrEqual", "value": { "field": "options.minDriftFrames" } }, { "field": "pair.driftTicks", "operator": "greaterThan", "value": 0 } ] }, "message": { "en_US": { "count": "pair.absDriftFramesRounded", "one": "Audio \"{clip.name}\" on {clip.track} is {pair.absDriftFramesRounded} frame late compared with video \"{pair.videoName}\" on {pair.videoTrack} from the same source.", "other": "Audio \"{clip.name}\" on {clip.track} is {pair.absDriftFramesRounded} frames late compared with video \"{pair.videoName}\" on {pair.videoTrack} from the same source." }, "de_DE": { "count": "pair.absDriftFramesRounded", "one": "Audio „{clip.name}“ auf {clip.track} liegt {pair.absDriftFramesRounded} Frame hinter Video „{pair.videoName}“ auf {pair.videoTrack} aus derselben Quelle.", "other": "Audio „{clip.name}“ auf {clip.track} liegt {pair.absDriftFramesRounded} Frames hinter Video „{pair.videoName}“ auf {pair.videoTrack} aus derselben Quelle." }, "es_ES": { "count": "pair.absDriftFramesRounded", "one": "El audio \"{clip.name}\" en {clip.track} está retrasado {pair.absDriftFramesRounded} fotograma respecto al vídeo \"{pair.videoName}\" en {pair.videoTrack} del mismo origen.", "other": "El audio \"{clip.name}\" en {clip.track} está retrasado {pair.absDriftFramesRounded} fotogramas respecto al vídeo \"{pair.videoName}\" en {pair.videoTrack} del mismo origen." }, "fr_FR": { "count": "pair.absDriftFramesRounded", "one": "L'audio « {clip.name} » sur {clip.track} est en retard de {pair.absDriftFramesRounded} image par rapport à la vidéo « {pair.videoName} » sur {pair.videoTrack} issue de la même source.", "other": "L'audio « {clip.name} » sur {clip.track} est en retard de {pair.absDriftFramesRounded} images par rapport à la vidéo « {pair.videoName} » sur {pair.videoTrack} issue de la même source." }, "it_IT": { "count": "pair.absDriftFramesRounded", "one": "L'audio \"{clip.name}\" su {clip.track} è in ritardo di {pair.absDriftFramesRounded} fotogramma rispetto al video \"{pair.videoName}\" su {pair.videoTrack} della stessa sorgente.", "other": "L'audio \"{clip.name}\" su {clip.track} è in ritardo di {pair.absDriftFramesRounded} fotogrammi rispetto al video \"{pair.videoName}\" su {pair.videoTrack} della stessa sorgente." }, "ja_JP": "オーディオ「{clip.name}」({clip.track})は、同じソースのビデオ「{pair.videoName}」({pair.videoTrack})より{pair.absDriftFramesRounded}フレーム遅れています。", "ko_KR": "오디오 {clip.track}의 \"{clip.name}\"이(가) 같은 소스의 비디오 {pair.videoTrack}의 \"{pair.videoName}\"보다 {pair.absDriftFramesRounded}프레임 늦습니다.", "pt_BR": { "count": "pair.absDriftFramesRounded", "one": "O áudio \"{clip.name}\" em {clip.track} está {pair.absDriftFramesRounded} quadro atrasado em relação ao vídeo \"{pair.videoName}\" em {pair.videoTrack} da mesma origem.", "other": "O áudio \"{clip.name}\" em {clip.track} está {pair.absDriftFramesRounded} quadros atrasado em relação ao vídeo \"{pair.videoName}\" em {pair.videoTrack} da mesma origem." }, "ru_RU": { "count": "pair.absDriftFramesRounded", "one": "Аудио «{clip.name}» на {clip.track} отстает на {pair.absDriftFramesRounded} кадр от видео «{pair.videoName}» на {pair.videoTrack} из того же источника.", "few": "Аудио «{clip.name}» на {clip.track} отстает на {pair.absDriftFramesRounded} кадра от видео «{pair.videoName}» на {pair.videoTrack} из того же источника.", "many": "Аудио «{clip.name}» на {clip.track} отстает на {pair.absDriftFramesRounded} кадров от видео «{pair.videoName}» на {pair.videoTrack} из того же источника.", "other": "Аудио «{clip.name}» на {clip.track} отстает на {pair.absDriftFramesRounded} кадра от видео «{pair.videoName}» на {pair.videoTrack} из того же источника." }, "zh_CN": "音频 {clip.track} 上的“{clip.name}” 比同一源的视频 {pair.videoTrack} 上的“{pair.videoName}” 晚 {pair.absDriftFramesRounded} 帧。" } }, { "condition": { "all": [ { "field": "pair.absDriftFrames", "operator": "greaterThanOrEqual", "value": { "field": "options.minDriftFrames" } }, { "field": "pair.driftTicks", "operator": "lessThan", "value": 0 } ] }, "message": { "en_US": { "count": "pair.absDriftFramesRounded", "one": "Audio \"{clip.name}\" on {clip.track} is {pair.absDriftFramesRounded} frame early compared with video \"{pair.videoName}\" on {pair.videoTrack} from the same source.", "other": "Audio \"{clip.name}\" on {clip.track} is {pair.absDriftFramesRounded} frames early compared with video \"{pair.videoName}\" on {pair.videoTrack} from the same source." }, "de_DE": { "count": "pair.absDriftFramesRounded", "one": "Audio „{clip.name}“ auf {clip.track} liegt {pair.absDriftFramesRounded} Frame vor Video „{pair.videoName}“ auf {pair.videoTrack} aus derselben Quelle.", "other": "Audio „{clip.name}“ auf {clip.track} liegt {pair.absDriftFramesRounded} Frames vor Video „{pair.videoName}“ auf {pair.videoTrack} aus derselben Quelle." }, "es_ES": { "count": "pair.absDriftFramesRounded", "one": "El audio \"{clip.name}\" en {clip.track} está adelantado {pair.absDriftFramesRounded} fotograma respecto al vídeo \"{pair.videoName}\" en {pair.videoTrack} del mismo origen.", "other": "El audio \"{clip.name}\" en {clip.track} está adelantado {pair.absDriftFramesRounded} fotogramas respecto al vídeo \"{pair.videoName}\" en {pair.videoTrack} del mismo origen." }, "fr_FR": { "count": "pair.absDriftFramesRounded", "one": "L'audio « {clip.name} » sur {clip.track} est en avance de {pair.absDriftFramesRounded} image par rapport à la vidéo « {pair.videoName} » sur {pair.videoTrack} issue de la même source.", "other": "L'audio « {clip.name} » sur {clip.track} est en avance de {pair.absDriftFramesRounded} images par rapport à la vidéo « {pair.videoName} » sur {pair.videoTrack} issue de la même source." }, "it_IT": { "count": "pair.absDriftFramesRounded", "one": "L'audio \"{clip.name}\" su {clip.track} è in anticipo di {pair.absDriftFramesRounded} fotogramma rispetto al video \"{pair.videoName}\" su {pair.videoTrack} della stessa sorgente.", "other": "L'audio \"{clip.name}\" su {clip.track} è in anticipo di {pair.absDriftFramesRounded} fotogrammi rispetto al video \"{pair.videoName}\" su {pair.videoTrack} della stessa sorgente." }, "ja_JP": "オーディオ「{clip.name}」({clip.track})は、同じソースのビデオ「{pair.videoName}」({pair.videoTrack})より{pair.absDriftFramesRounded}フレーム進んでいます。", "ko_KR": "오디오 {clip.track}의 \"{clip.name}\"이(가) 같은 소스의 비디오 {pair.videoTrack}의 \"{pair.videoName}\"보다 {pair.absDriftFramesRounded}프레임 빠릅니다.", "pt_BR": { "count": "pair.absDriftFramesRounded", "one": "O áudio \"{clip.name}\" em {clip.track} está {pair.absDriftFramesRounded} quadro adiantado em relação ao vídeo \"{pair.videoName}\" em {pair.videoTrack} da mesma origem.", "other": "O áudio \"{clip.name}\" em {clip.track} está {pair.absDriftFramesRounded} quadros adiantado em relação ao vídeo \"{pair.videoName}\" em {pair.videoTrack} da mesma origem." }, "ru_RU": { "count": "pair.absDriftFramesRounded", "one": "Аудио «{clip.name}» на {clip.track} опережает на {pair.absDriftFramesRounded} кадр видео «{pair.videoName}» на {pair.videoTrack} из того же источника.", "few": "Аудио «{clip.name}» на {clip.track} опережает на {pair.absDriftFramesRounded} кадра видео «{pair.videoName}» на {pair.videoTrack} из того же источника.", "many": "Аудио «{clip.name}» на {clip.track} опережает на {pair.absDriftFramesRounded} кадров видео «{pair.videoName}» на {pair.videoTrack} из того же источника.", "other": "Аудио «{clip.name}» на {clip.track} опережает на {pair.absDriftFramesRounded} кадра видео «{pair.videoName}» на {pair.videoTrack} из того же источника." }, "zh_CN": "音频 {clip.track} 上的“{clip.name}” 比同一源的视频 {pair.videoTrack} 上的“{pair.videoName}” 早 {pair.absDriftFramesRounded} 帧。" } } ], "data": { "driftTicks": "pair.driftTicks", "driftFrames": "pair.driftFrames", "minDriftFrames": "options.minDriftFrames", "projectItemId": "pair.projectItemId" } } ``` # Partial adjustment layer coverage (/docs/rules/no-partial-adjustment-layer-coverage) Reports adjustment layers whose start or end falls inside a clip below them. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :-------------------------------------------------------------------------------------------------- | | Id | `no-partial-adjustment-layer-coverage` | | Category | Static | | Default severity | info | | Scope | [`adjustment-layer-edges`](/docs/reference/computed-scopes#adjustment-layer-edges) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :---------------- | :------- | :------ | :------------------------------------------------------------------------------- | | `toleranceFrames` | `number` | `0` | An edge within this many frames of the clip edge counts as aligned. | | `minFrames` | `number` | `12` | Adjustment layers shorter than this are deliberate mid-clip effects and skipped. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-partial-adjustment-layer-coverage.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-partial-adjustment-layer-coverage.rule.json" { "formatVersion": 1, "id": "no-partial-adjustment-layer-coverage", "name": { "en_US": "Partial adjustment layer coverage", "de_DE": "Teilweise Abdeckung durch Einstellungsebenen", "es_ES": "Cobertura parcial de capas de ajuste", "fr_FR": "Couverture partielle par un calque d'effets", "it_IT": "Copertura parziale dei livelli di regolazione", "ja_JP": "調整レイヤーの部分的な適用範囲", "ko_KR": "조정 레이어의 부분 적용", "pt_BR": "Cobertura parcial de camada de ajuste", "ru_RU": "Частичное покрытие корректирующим слоем", "zh_CN": "调整图层部分覆盖" }, "description": { "en_US": "Reports adjustment layers whose start or end falls inside a clip below them.", "de_DE": "Meldet Einstellungsebenen, deren Anfang oder Ende innerhalb eines darunterliegenden Clips liegt.", "es_ES": "Detecta capas de ajuste cuyo inicio o final cae dentro de un clip situado debajo.", "fr_FR": "Signale les calques d'effets dont le début ou la fin tombe à l'intérieur d'un élément situé en dessous.", "it_IT": "Segnala i livelli di regolazione il cui inizio o fine cade all'interno di una clip sottostante.", "ja_JP": "開始または終了が下のクリップの途中にある調整レイヤーを報告します。", "ko_KR": "시작 또는 끝이 아래쪽 클립 내부에 있는 조정 레이어를 보고합니다.", "pt_BR": "Relata camadas de ajuste cujo início ou fim cai dentro de um clipe abaixo delas.", "ru_RU": "Сообщает о корректирующих слоях, начало или конец которых приходится на середину клипа под ними.", "zh_CN": "报告开头或结尾落在其下方剪辑内部的调整图层。" }, "category": "static", "scope": "adjustment-layer-edges", "severity": "info", "options": { "toleranceFrames": { "type": "number", "default": 0, "description": "An edge within this many frames of the clip edge counts as aligned." }, "minFrames": { "type": "number", "default": 12, "description": "Adjustment layers shorter than this are deliberate mid-clip effects and skipped." } }, "checks": [ { "condition": { "all": [ { "field": "clip.durationFrames", "operator": "greaterThanOrEqual", "value": { "field": "options.minFrames" } }, { "field": "edge.offsetFrames", "operator": "greaterThan", "value": { "field": "options.toleranceFrames" } }, { "field": "edge.side", "operator": "equals", "value": "start" } ] }, "message": { "en_US": { "count": "edge.offsetFramesRounded", "one": "Adjustment layer \"{clip.name}\" on {clip.track} starts inside clip \"{edge.clipName}\" on {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} frame after its start.", "other": "Adjustment layer \"{clip.name}\" on {clip.track} starts inside clip \"{edge.clipName}\" on {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} frames after its start." }, "de_DE": { "count": "edge.offsetFramesRounded", "one": "Einstellungsebene „{clip.name}“ auf {clip.track} beginnt innerhalb von Clip „{edge.clipName}“ auf {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} Frame nach dessen Beginn.", "other": "Einstellungsebene „{clip.name}“ auf {clip.track} beginnt innerhalb von Clip „{edge.clipName}“ auf {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} Frames nach dessen Beginn." }, "es_ES": { "count": "edge.offsetFramesRounded", "one": "La capa de ajuste \"{clip.name}\" en {clip.track} empieza dentro del clip \"{edge.clipName}\" en {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} fotograma después de su inicio.", "other": "La capa de ajuste \"{clip.name}\" en {clip.track} empieza dentro del clip \"{edge.clipName}\" en {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} fotogramas después de su inicio." }, "fr_FR": { "count": "edge.offsetFramesRounded", "one": "Le calque d'effets « {clip.name} » sur {clip.track} commence à l'intérieur de l'élément « {edge.clipName} » sur {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} image après son début.", "other": "Le calque d'effets « {clip.name} » sur {clip.track} commence à l'intérieur de l'élément « {edge.clipName} » sur {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} images après son début." }, "it_IT": { "count": "edge.offsetFramesRounded", "one": "Il livello di regolazione \"{clip.name}\" su {clip.track} inizia all'interno della clip \"{edge.clipName}\" su {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} fotogramma dopo il suo inizio.", "other": "Il livello di regolazione \"{clip.name}\" su {clip.track} inizia all'interno della clip \"{edge.clipName}\" su {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} fotogrammi dopo il suo inizio." }, "ja_JP": "調整レイヤー「{clip.name}」({clip.track})がクリップ「{edge.clipName}」({edge.clipTrack})の途中({edge.timecode}、クリップの開始から{edge.offsetFramesRounded}フレーム後)で始まっています。", "ko_KR": "조정 레이어 {clip.track}의 \"{clip.name}\"이(가) 클립 {edge.clipTrack}의 \"{edge.clipName}\" 내부({edge.timecode})에서 시작합니다. 클립 시작 후 {edge.offsetFramesRounded}프레임 지점입니다.", "pt_BR": { "count": "edge.offsetFramesRounded", "one": "A camada de ajuste \"{clip.name}\" em {clip.track} começa dentro do clipe \"{edge.clipName}\" em {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} quadro após o início dele.", "other": "A camada de ajuste \"{clip.name}\" em {clip.track} começa dentro do clipe \"{edge.clipName}\" em {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} quadros após o início dele." }, "ru_RU": { "count": "edge.offsetFramesRounded", "one": "Корректирующий слой «{clip.name}» на {clip.track} начинается внутри клипа «{edge.clipName}» на {edge.clipTrack} ({edge.timecode}), через {edge.offsetFramesRounded} кадр после его начала.", "few": "Корректирующий слой «{clip.name}» на {clip.track} начинается внутри клипа «{edge.clipName}» на {edge.clipTrack} ({edge.timecode}), через {edge.offsetFramesRounded} кадра после его начала.", "many": "Корректирующий слой «{clip.name}» на {clip.track} начинается внутри клипа «{edge.clipName}» на {edge.clipTrack} ({edge.timecode}), через {edge.offsetFramesRounded} кадров после его начала.", "other": "Корректирующий слой «{clip.name}» на {clip.track} начинается внутри клипа «{edge.clipName}» на {edge.clipTrack} ({edge.timecode}), через {edge.offsetFramesRounded} кадра после его начала." }, "zh_CN": "调整图层 {clip.track} 上的“{clip.name}” 的开头位于剪辑 {edge.clipTrack} 上的“{edge.clipName}” 内部({edge.timecode}),距该剪辑开头 {edge.offsetFramesRounded} 帧。" } }, { "condition": { "all": [ { "field": "clip.durationFrames", "operator": "greaterThanOrEqual", "value": { "field": "options.minFrames" } }, { "field": "edge.offsetFrames", "operator": "greaterThan", "value": { "field": "options.toleranceFrames" } }, { "field": "edge.side", "operator": "equals", "value": "end" } ] }, "message": { "en_US": { "count": "edge.offsetFramesRounded", "one": "Adjustment layer \"{clip.name}\" on {clip.track} ends inside clip \"{edge.clipName}\" on {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} frame before its end.", "other": "Adjustment layer \"{clip.name}\" on {clip.track} ends inside clip \"{edge.clipName}\" on {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} frames before its end." }, "de_DE": { "count": "edge.offsetFramesRounded", "one": "Einstellungsebene „{clip.name}“ auf {clip.track} endet innerhalb von Clip „{edge.clipName}“ auf {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} Frame vor dessen Ende.", "other": "Einstellungsebene „{clip.name}“ auf {clip.track} endet innerhalb von Clip „{edge.clipName}“ auf {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} Frames vor dessen Ende." }, "es_ES": { "count": "edge.offsetFramesRounded", "one": "La capa de ajuste \"{clip.name}\" en {clip.track} termina dentro del clip \"{edge.clipName}\" en {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} fotograma antes de su final.", "other": "La capa de ajuste \"{clip.name}\" en {clip.track} termina dentro del clip \"{edge.clipName}\" en {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} fotogramas antes de su final." }, "fr_FR": { "count": "edge.offsetFramesRounded", "one": "Le calque d'effets « {clip.name} » sur {clip.track} se termine à l'intérieur de l'élément « {edge.clipName} » sur {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} image avant sa fin.", "other": "Le calque d'effets « {clip.name} » sur {clip.track} se termine à l'intérieur de l'élément « {edge.clipName} » sur {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} images avant sa fin." }, "it_IT": { "count": "edge.offsetFramesRounded", "one": "Il livello di regolazione \"{clip.name}\" su {clip.track} termina all'interno della clip \"{edge.clipName}\" su {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} fotogramma prima della sua fine.", "other": "Il livello di regolazione \"{clip.name}\" su {clip.track} termina all'interno della clip \"{edge.clipName}\" su {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} fotogrammi prima della sua fine." }, "ja_JP": "調整レイヤー「{clip.name}」({clip.track})がクリップ「{edge.clipName}」({edge.clipTrack})の途中({edge.timecode}、クリップの終了の{edge.offsetFramesRounded}フレーム前)で終わっています。", "ko_KR": "조정 레이어 {clip.track}의 \"{clip.name}\"이(가) 클립 {edge.clipTrack}의 \"{edge.clipName}\" 내부({edge.timecode})에서 끝납니다. 클립 끝 {edge.offsetFramesRounded}프레임 전 지점입니다.", "pt_BR": { "count": "edge.offsetFramesRounded", "one": "A camada de ajuste \"{clip.name}\" em {clip.track} termina dentro do clipe \"{edge.clipName}\" em {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} quadro antes do fim dele.", "other": "A camada de ajuste \"{clip.name}\" em {clip.track} termina dentro do clipe \"{edge.clipName}\" em {edge.clipTrack} ({edge.timecode}), {edge.offsetFramesRounded} quadros antes do fim dele." }, "ru_RU": { "count": "edge.offsetFramesRounded", "one": "Корректирующий слой «{clip.name}» на {clip.track} заканчивается внутри клипа «{edge.clipName}» на {edge.clipTrack} ({edge.timecode}), за {edge.offsetFramesRounded} кадр до его конца.", "few": "Корректирующий слой «{clip.name}» на {clip.track} заканчивается внутри клипа «{edge.clipName}» на {edge.clipTrack} ({edge.timecode}), за {edge.offsetFramesRounded} кадра до его конца.", "many": "Корректирующий слой «{clip.name}» на {clip.track} заканчивается внутри клипа «{edge.clipName}» на {edge.clipTrack} ({edge.timecode}), за {edge.offsetFramesRounded} кадров до его конца.", "other": "Корректирующий слой «{clip.name}» на {clip.track} заканчивается внутри клипа «{edge.clipName}» на {edge.clipTrack} ({edge.timecode}), за {edge.offsetFramesRounded} кадра до его конца." }, "zh_CN": "调整图层 {clip.track} 上的“{clip.name}” 的结尾位于剪辑 {edge.clipTrack} 上的“{edge.clipName}” 内部({edge.timecode}),距该剪辑结尾 {edge.offsetFramesRounded} 帧。" } } ], "matching": "all", "data": { "edge": "edge.side", "offsetTicks": "edge.offsetTicks", "offsetFrames": "edge.offsetFrames", "toleranceFrames": "options.toleranceFrames" } } ``` # Repeated footage (/docs/rules/no-repeated-footage) Reports clips that reuse a source range already used elsewhere in the sequence. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :-------------------------------------------------------------------------------------------------- | | Id | `no-repeated-footage` | | Category | Global consistency | | Default severity | info | | Scope | [`repeated-footage-pairs`](/docs/reference/computed-scopes#repeated-footage-pairs) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :----------------- | :--------- | :------------------------------ | :------------------------------------------------------------ | | `minOverlapFrames` | `number` | `12` | Source overlap shorter than this many frames is not reported. | | `includeAudio` | `boolean` | `false` | Also compare audio clips. | | `kinds` | `string[]` | `["media","multicam","merged"]` | Source kinds compared. | | `ignoreExtensions` | `string[]` | see the rule file | Lower-case file extensions (stills, graphics) never compared. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-repeated-footage.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-repeated-footage.rule.json" { "formatVersion": 1, "id": "no-repeated-footage", "name": { "en_US": "Repeated footage", "de_DE": "Wiederholtes Material", "es_ES": "Metraje repetido", "fr_FR": "Métrage répété", "it_IT": "Metraggio ripetuto", "ja_JP": "繰り返し使用された素材", "ko_KR": "반복된 푸티지", "pt_BR": "Gravações repetidas", "ru_RU": "Повторяющийся материал", "zh_CN": "重复素材" }, "description": { "en_US": "Reports clips that reuse a source range already used elsewhere in the sequence.", "de_DE": "Meldet Clips, die einen Quellbereich verwenden, der bereits an anderer Stelle in der Sequenz verwendet wird.", "es_ES": "Detecta clips que reutilizan un intervalo de origen ya usado en otra parte de la secuencia.", "fr_FR": "Signale les éléments qui réutilisent une plage de source déjà utilisée ailleurs dans la séquence.", "it_IT": "Segnala le clip che riutilizzano un intervallo di sorgente già usato altrove nella sequenza.", "ja_JP": "シーケンス内の別の場所で使用済みのソース範囲を再使用しているクリップを報告します。", "ko_KR": "시퀀스의 다른 곳에서 이미 사용한 소스 범위를 다시 사용하는 클립을 보고합니다.", "pt_BR": "Relata clipes que reutilizam um trecho da origem já usado em outro ponto da sequência.", "ru_RU": "Сообщает о клипах, повторно использующих фрагмент источника, уже использованный в другом месте эпизода.", "zh_CN": "报告重复使用了序列中其他位置已使用过的源范围的剪辑。" }, "category": "global-consistency", "scope": "repeated-footage-pairs", "severity": "info", "options": { "minOverlapFrames": { "type": "number", "default": 12, "description": "Source overlap shorter than this many frames is not reported." }, "includeAudio": { "type": "boolean", "default": false, "description": "Also compare audio clips." }, "kinds": { "type": "string[]", "default": [ "media", "multicam", "merged" ], "description": "Source kinds compared." }, "ignoreExtensions": { "type": "string[]", "default": [ "png", "jpg", "jpeg", "gif", "tif", "tiff", "psd", "ai", "svg", "bmp", "webp", "heic" ], "description": "Lower-case file extensions (stills, graphics) never compared." } }, "checks": [ { "condition": { "all": [ { "field": "reuse.overlapFrames", "operator": "greaterThanOrEqual", "value": { "field": "options.minOverlapFrames" } }, { "any": [ { "field": "clip.trackType", "operator": "equals", "value": "video" }, { "field": "options.includeAudio", "operator": "equals", "value": true } ] }, { "field": "clip.source.kind", "operator": "in", "value": { "field": "options.kinds" } }, { "not": { "field": "clip.source.extension", "operator": "in", "value": { "field": "options.ignoreExtensions" } } } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} reuses {labels.duration} of source already used by \"{reuse.earlierName}\" on {reuse.earlierTrack} at {reuse.earlierTimecode}.", "de_DE": "Clip „{clip.name}“ auf {clip.track} verwendet erneut {labels.duration} Quellmaterial, das bereits „{reuse.earlierName}“ auf {reuse.earlierTrack} bei {reuse.earlierTimecode} verwendet.", "es_ES": "Clip \"{clip.name}\" en {clip.track} reutiliza {labels.duration} de un origen que ya usa \"{reuse.earlierName}\" en {reuse.earlierTrack} en {reuse.earlierTimecode}.", "fr_FR": "Élément « {clip.name} » sur {clip.track} réutilise {labels.duration} d'une source déjà utilisée par « {reuse.earlierName} » sur {reuse.earlierTrack} à {reuse.earlierTimecode}.", "it_IT": "Clip \"{clip.name}\" su {clip.track} riutilizza {labels.duration} di sorgente già usata da \"{reuse.earlierName}\" su {reuse.earlierTrack} a {reuse.earlierTimecode}.", "ja_JP": "クリップ「{clip.name}」({clip.track})は、{reuse.earlierTimecode}の「{reuse.earlierName}」({reuse.earlierTrack})で使用済みのソースを{labels.duration}分再使用しています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) {reuse.earlierTimecode}의 {reuse.earlierTrack}의 \"{reuse.earlierName}\"에서 이미 사용한 소스를 {labels.duration} 분량 다시 사용합니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} reutiliza {labels.duration} da origem já usada por \"{reuse.earlierName}\" em {reuse.earlierTrack} em {reuse.earlierTimecode}.", "ru_RU": "Клип «{clip.name}» на {clip.track} повторно использует {labels.duration} источника, уже использованного клипом «{reuse.earlierName}» на {reuse.earlierTrack} в позиции {reuse.earlierTimecode}.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 重复使用了 {labels.duration} 的源素材,该素材已在 {reuse.earlierTimecode} 处被 {reuse.earlierTrack} 上的“{reuse.earlierName}” 使用。" } } ], "labels": { "duration": { "field": "reuse.overlapIsSeconds", "values": { "true": { "en_US": "{reuse.overlapSeconds} s", "de_DE": "{reuse.overlapSeconds} s", "es_ES": "{reuse.overlapSeconds} s", "fr_FR": "{reuse.overlapSeconds} s", "it_IT": "{reuse.overlapSeconds} s", "ja_JP": "{reuse.overlapSeconds} s", "ko_KR": "{reuse.overlapSeconds} s", "pt_BR": "{reuse.overlapSeconds} s", "ru_RU": "{reuse.overlapSeconds} с", "zh_CN": "{reuse.overlapSeconds} s" }, "false": { "en_US": { "count": "reuse.overlapFramesRounded", "one": "{reuse.overlapFramesRounded} frame", "other": "{reuse.overlapFramesRounded} frames" }, "de_DE": { "count": "reuse.overlapFramesRounded", "one": "{reuse.overlapFramesRounded} Frame", "other": "{reuse.overlapFramesRounded} Frames" }, "es_ES": { "count": "reuse.overlapFramesRounded", "one": "{reuse.overlapFramesRounded} fotograma", "other": "{reuse.overlapFramesRounded} fotogramas" }, "fr_FR": { "count": "reuse.overlapFramesRounded", "one": "{reuse.overlapFramesRounded} image", "other": "{reuse.overlapFramesRounded} images" }, "it_IT": { "count": "reuse.overlapFramesRounded", "one": "{reuse.overlapFramesRounded} fotogramma", "other": "{reuse.overlapFramesRounded} fotogrammi" }, "ja_JP": "{reuse.overlapFramesRounded}フレーム", "ko_KR": "{reuse.overlapFramesRounded}프레임", "pt_BR": { "count": "reuse.overlapFramesRounded", "one": "{reuse.overlapFramesRounded} quadro", "other": "{reuse.overlapFramesRounded} quadros" }, "ru_RU": { "count": "reuse.overlapFramesRounded", "one": "{reuse.overlapFramesRounded} кадр", "few": "{reuse.overlapFramesRounded} кадра", "many": "{reuse.overlapFramesRounded} кадров", "other": "{reuse.overlapFramesRounded} кадра" }, "zh_CN": "{reuse.overlapFramesRounded} 帧" } } } }, "data": { "projectItemId": "reuse.projectItemId", "overlapTicks": "reuse.overlapTicks", "overlapFrames": "reuse.overlapFrames", "minOverlapFrames": "options.minOverlapFrames", "earlierStart": "reuse.earlierStart" } } ``` # Restricted effects (/docs/rules/no-restricted-effects) Reports clips using a configured forbidden effect. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :------------------------------------------------------------------------------------------ | | Id | `no-restricted-effects` | | Category | Project | | Default severity | warning | | Scope | [`restricted-effects`](/docs/reference/computed-scopes#restricted-effects) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :-------- | :----- | :------ | :--------------------------------------------------------------------------------------------------- | | `effects` | `json` | `[]` | Match names, or \{ "matchName", "message"? } to append an explanation. Empty: nothing is restricted. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-restricted-effects.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-restricted-effects.rule.json" { "formatVersion": 1, "id": "no-restricted-effects", "name": { "en_US": "Restricted effects", "de_DE": "Unzulässige Effekte", "es_ES": "Efectos restringidos", "fr_FR": "Effets interdits", "it_IT": "Effetti vietati", "ja_JP": "制限されたエフェクト", "ko_KR": "제한된 효과", "pt_BR": "Efeitos restritos", "ru_RU": "Запрещенные эффекты", "zh_CN": "受限效果" }, "description": { "en_US": "Reports clips using a configured forbidden effect.", "de_DE": "Meldet Clips, die einen als verboten konfigurierten Effekt verwenden.", "es_ES": "Detecta clips que usan un efecto prohibido en la configuración.", "fr_FR": "Signale les éléments qui utilisent un effet configuré comme interdit.", "it_IT": "Segnala le clip che usano un effetto configurato come vietato.", "ja_JP": "禁止に設定されたエフェクトを使用しているクリップを報告します。", "ko_KR": "금지로 설정된 효과를 사용하는 클립을 보고합니다.", "pt_BR": "Relata clipes que usam um efeito proibido configurado.", "ru_RU": "Сообщает о клипах, использующих эффект из списка запрещенных.", "zh_CN": "报告使用了已配置的禁用效果的剪辑。" }, "category": "project", "scope": "restricted-effects", "severity": "warning", "options": { "effects": { "type": "json", "default": [], "description": "Match names, or { \"matchName\", \"message\"? } to append an explanation. Empty: nothing is restricted." } }, "checks": [ { "condition": { "field": "restricted.matchName", "operator": "exists" }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} uses restricted effect \"{restricted.displayName}\".{restricted.explanation}", "de_DE": "Clip „{clip.name}“ auf {clip.track} verwendet den unzulässigen Effekt „{restricted.displayName}“.{restricted.explanation}", "es_ES": "Clip \"{clip.name}\" en {clip.track} usa el efecto restringido \"{restricted.displayName}\".{restricted.explanation}", "fr_FR": "Élément « {clip.name} » sur {clip.track} utilise l'effet interdit « {restricted.displayName} ».{restricted.explanation}", "it_IT": "Clip \"{clip.name}\" su {clip.track} usa l'effetto vietato \"{restricted.displayName}\".{restricted.explanation}", "ja_JP": "クリップ「{clip.name}」({clip.track})は制限されたエフェクト「{restricted.displayName}」を使用しています。{restricted.explanation}", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) 제한된 효과 \"{restricted.displayName}\"을(를) 사용합니다.{restricted.explanation}", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} usa o efeito restrito \"{restricted.displayName}\".{restricted.explanation}", "ru_RU": "Клип «{clip.name}» на {clip.track} использует запрещенный эффект «{restricted.displayName}».{restricted.explanation}", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 使用了受限效果“{restricted.displayName}”。{restricted.explanation}" } } ], "data": { "matchName": "restricted.matchName", "displayName": "restricted.displayName" } } ``` # Silent audio clips (/docs/rules/no-silent-audio-clips) Reports audio clips whose volume is set to silence. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :---------------------- | | Id | `no-silent-audio-clips` | | Category | Static | | Default severity | warning | | Scope | `clip` | ## Options [#options] | Option | Type | Default | Description | | :---------- | :------- | :------ | :-------------------------------------------------------- | | `silenceDb` | `number` | `-60` | Clips at or below this static level, in dB, are reported. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-silent-audio-clips.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-silent-audio-clips.rule.json" { "formatVersion": 1, "id": "no-silent-audio-clips", "name": { "en_US": "Silent audio clips", "de_DE": "Stumme Audioclips", "es_ES": "Clips de audio en silencio", "fr_FR": "Éléments audio silencieux", "it_IT": "Clip audio silenziose", "ja_JP": "無音のオーディオクリップ", "ko_KR": "무음 오디오 클립", "pt_BR": "Clipes de áudio silenciosos", "ru_RU": "Беззвучные аудиоклипы", "zh_CN": "无声音频剪辑" }, "description": { "en_US": "Reports audio clips whose volume is set to silence.", "de_DE": "Meldet Audioclips, deren Lautstärke auf Stille eingestellt ist.", "es_ES": "Detecta clips de audio cuyo volumen está ajustado a silencio.", "fr_FR": "Signale les éléments audio dont le volume est réglé sur le silence.", "it_IT": "Segnala le clip audio con il volume impostato sul silenzio.", "ja_JP": "ボリュームが無音に設定されているオーディオクリップを報告します。", "ko_KR": "볼륨이 무음으로 설정된 오디오 클립을 보고합니다.", "pt_BR": "Relata clipes de áudio cujo volume está configurado para silêncio.", "ru_RU": "Сообщает об аудиоклипах, громкость которых установлена на тишину.", "zh_CN": "报告音量设置为静音的音频剪辑。" }, "category": "static", "scope": "clip", "severity": "warning", "options": { "silenceDb": { "type": "number", "default": -60, "description": "Clips at or below this static level, in dB, are reported." } }, "checks": [ { "condition": { "all": [ { "field": "clip.disabled", "operator": "equals", "value": false }, { "field": "clip.volumeAnimated", "operator": "equals", "value": false }, { "field": "clip.volume", "operator": "equals", "value": "-Infinity" }, { "field": "clip.volume", "operator": "lessThanOrEqual", "value": { "field": "options.silenceDb" } } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is silenced (volume -∞ dB).", "de_DE": "Clip „{clip.name}“ auf {clip.track} ist stumm (Lautstärke -∞ dB).", "es_ES": "Clip \"{clip.name}\" en {clip.track} está silenciado (volumen -∞ dB).", "fr_FR": "Élément « {clip.name} » sur {clip.track} est silencieux (volume -∞ dB).", "it_IT": "Clip \"{clip.name}\" su {clip.track} è silenziata (volume -∞ dB).", "ja_JP": "クリップ「{clip.name}」({clip.track})は無音になっています(ボリューム -∞ dB)。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) 무음 상태입니다(볼륨 -∞ dB).", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está silenciado (volume -∞ dB).", "ru_RU": "Клип «{clip.name}» на {clip.track} заглушен (громкость -∞ dB).", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 已静音(音量 -∞ dB)。" } }, { "condition": { "all": [ { "field": "clip.disabled", "operator": "equals", "value": false }, { "field": "clip.volumeAnimated", "operator": "equals", "value": false }, { "field": "clip.volume", "operator": "lessThanOrEqual", "value": { "field": "options.silenceDb" } } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is set to {clip.volume} dB, at or below the {options.silenceDb} dB silence threshold.", "de_DE": "Clip „{clip.name}“ auf {clip.track} ist auf {clip.volume} dB eingestellt und liegt damit auf oder unter der Stilleschwelle von {options.silenceDb} dB.", "es_ES": "Clip \"{clip.name}\" en {clip.track} está a {clip.volume} dB, igual o por debajo del umbral de silencio de {options.silenceDb} dB.", "fr_FR": "Élément « {clip.name} » sur {clip.track} est réglé sur {clip.volume} dB, au niveau ou en dessous du seuil de silence de {options.silenceDb} dB.", "it_IT": "Clip \"{clip.name}\" su {clip.track} è impostata a {clip.volume} dB, pari o inferiore alla soglia di silenzio di {options.silenceDb} dB.", "ja_JP": "クリップ「{clip.name}」({clip.track})は{clip.volume} dBに設定されており、無音のしきい値({options.silenceDb} dB)以下です。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 볼륨({clip.volume} dB)이 무음 임계값 {options.silenceDb} dB 이하입니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está em {clip.volume} dB, no limite de silêncio de {options.silenceDb} dB ou abaixo dele.", "ru_RU": "Клип «{clip.name}» на {clip.track}: громкость {clip.volume} dB, что не выше порога тишины {options.silenceDb} dB.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 设置为 {clip.volume} dB,达到或低于 {options.silenceDb} dB 的静音阈值。" } } ], "data": { "volumeDb": "clip.volume", "silenceDb": "options.silenceDb" } } ``` # Subframe video edits (/docs/rules/no-subframe-video-edits) Reports clip edges and sequence in/out points that are not on a frame boundary. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :------------------------ | | Id | `no-subframe-video-edits` | | Category | Static | | Default severity | warning | | Scope | `clip` | ## Options [#options] | Option | Type | Default | Description | | :------------- | :-------- | :------ | :------------------------------------------------------------------- | | `includeAudio` | `boolean` | `false` | Also check audio clip edges, which Premiere lets sit between frames. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-subframe-video-edits.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-subframe-video-edits.rule.json" { "formatVersion": 1, "id": "no-subframe-video-edits", "name": { "en_US": "Subframe video edits", "de_DE": "Videoschnitte zwischen Frames", "es_ES": "Ediciones de vídeo entre fotogramas", "fr_FR": "Montages vidéo entre deux images", "it_IT": "Modifiche video tra fotogrammi", "ja_JP": "サブフレームのビデオ編集", "ko_KR": "서브프레임 비디오 편집", "pt_BR": "Edições de vídeo entre quadros", "ru_RU": "Монтаж между кадрами", "zh_CN": "子帧视频编辑" }, "description": { "en_US": "Reports clip edges and sequence in/out points that are not on a frame boundary.", "de_DE": "Meldet Clipkanten und In-/Out-Points der Sequenz, die nicht auf einer Framegrenze liegen.", "es_ES": "Detecta bordes de clips y puntos de entrada/salida de la secuencia que no coinciden con un límite de fotograma.", "fr_FR": "Signale les bords d'éléments et les points d'entrée et de sortie de séquence qui ne tombent pas sur une limite d'image.", "it_IT": "Segnala i bordi delle clip e i punti di attacco/stacco della sequenza non allineati a un fotogramma.", "ja_JP": "フレームの境界上にないクリップの端とシーケンスのイン/アウトポイントを報告します。", "ko_KR": "프레임 경계에 맞지 않는 클립 가장자리와 시퀀스 시작/종료 지점을 보고합니다.", "pt_BR": "Relata bordas de clipes e pontos de entrada/saída da sequência que não estão no limite de um quadro.", "ru_RU": "Сообщает о границах клипов и точках входа и выхода эпизода, не совпадающих с границей кадра.", "zh_CN": "报告未对齐帧边界的剪辑边缘和序列入点/出点。" }, "category": "static", "scope": "clip", "severity": "warning", "options": { "includeAudio": { "type": "boolean", "default": false, "description": "Also check audio clip edges, which Premiere lets sit between frames." } }, "checks": [ { "condition": { "all": [ { "any": [ { "field": "clip.trackType", "operator": "equals", "value": "video" }, { "field": "options.includeAudio", "operator": "equals", "value": true } ] }, { "field": "clip.startFrameOffset", "operator": "greaterThan", "value": 0 }, { "field": "clip.endFrameOffset", "operator": "greaterThan", "value": 0 } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} starts and ends between two frames.", "de_DE": "Clip „{clip.name}“ auf {clip.track} beginnt und endet zwischen zwei Frames.", "es_ES": "Clip \"{clip.name}\" en {clip.track} empieza y termina entre dos fotogramas.", "fr_FR": "Élément « {clip.name} » sur {clip.track} commence et se termine entre deux images.", "it_IT": "Clip \"{clip.name}\" su {clip.track} inizia e termina tra due fotogrammi.", "ja_JP": "クリップ「{clip.name}」({clip.track})の開始位置と終了位置がフレームの間にあります。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) 두 프레임 사이에서 시작하고 끝납니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} começa e termina entre dois quadros.", "ru_RU": "Клип «{clip.name}» на {clip.track} начинается и заканчивается между двумя кадрами.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 的开头和结尾均位于两帧之间。" }, "data": { "startOffsetTicks": "clip.startFrameOffset", "endOffsetTicks": "clip.endFrameOffset" } }, { "condition": { "all": [ { "any": [ { "field": "clip.trackType", "operator": "equals", "value": "video" }, { "field": "options.includeAudio", "operator": "equals", "value": true } ] }, { "field": "clip.startFrameOffset", "operator": "greaterThan", "value": 0 }, { "field": "clip.endFrameOffset", "operator": "equals", "value": 0 } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} starts between two frames.", "de_DE": "Clip „{clip.name}“ auf {clip.track} beginnt zwischen zwei Frames.", "es_ES": "Clip \"{clip.name}\" en {clip.track} empieza entre dos fotogramas.", "fr_FR": "Élément « {clip.name} » sur {clip.track} commence entre deux images.", "it_IT": "Clip \"{clip.name}\" su {clip.track} inizia tra due fotogrammi.", "ja_JP": "クリップ「{clip.name}」({clip.track})の開始位置がフレームの間にあります。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) 두 프레임 사이에서 시작합니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} começa entre dois quadros.", "ru_RU": "Клип «{clip.name}» на {clip.track} начинается между двумя кадрами.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 的开头位于两帧之间。" }, "data": { "startOffsetTicks": "clip.startFrameOffset", "endOffsetTicks": "clip.endFrameOffset" } }, { "condition": { "all": [ { "any": [ { "field": "clip.trackType", "operator": "equals", "value": "video" }, { "field": "options.includeAudio", "operator": "equals", "value": true } ] }, { "field": "clip.startFrameOffset", "operator": "equals", "value": 0 }, { "field": "clip.endFrameOffset", "operator": "greaterThan", "value": 0 } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} ends between two frames.", "de_DE": "Clip „{clip.name}“ auf {clip.track} endet zwischen zwei Frames.", "es_ES": "Clip \"{clip.name}\" en {clip.track} termina entre dos fotogramas.", "fr_FR": "Élément « {clip.name} » sur {clip.track} se termine entre deux images.", "it_IT": "Clip \"{clip.name}\" su {clip.track} termina tra due fotogrammi.", "ja_JP": "クリップ「{clip.name}」({clip.track})の終了位置がフレームの間にあります。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"이(가) 두 프레임 사이에서 끝납니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} termina entre dois quadros.", "ru_RU": "Клип «{clip.name}» на {clip.track} заканчивается между двумя кадрами.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 的结尾位于两帧之间。" }, "data": { "startOffsetTicks": "clip.startFrameOffset", "endOffsetTicks": "clip.endFrameOffset" } }, { "scope": "sequence", "condition": { "field": "sequence.inPointFrameOffset", "operator": "greaterThan", "value": 0 }, "message": { "en_US": "Sequence in point is between two frames.", "de_DE": "Der In-Point der Sequenz liegt zwischen zwei Frames.", "es_ES": "El punto de entrada de la secuencia está entre dos fotogramas.", "fr_FR": "Le point d'entrée de la séquence se trouve entre deux images.", "it_IT": "Il punto di attacco della sequenza è tra due fotogrammi.", "ja_JP": "シーケンスのインポイントがフレームの間にあります。", "ko_KR": "시퀀스 시작 지점이 두 프레임 사이에 있습니다.", "pt_BR": "O ponto de entrada da sequência está entre dois quadros.", "ru_RU": "Точка входа эпизода находится между двумя кадрами.", "zh_CN": "序列入点位于两帧之间。" }, "location": "sequence.inPoint", "data": { "point": { "literal": "in" }, "offsetTicks": "sequence.inPointFrameOffset" } }, { "scope": "sequence", "condition": { "field": "sequence.outPointFrameOffset", "operator": "greaterThan", "value": 0 }, "message": { "en_US": "Sequence out point is between two frames.", "de_DE": "Der Out-Point der Sequenz liegt zwischen zwei Frames.", "es_ES": "El punto de salida de la secuencia está entre dos fotogramas.", "fr_FR": "Le point de sortie de la séquence se trouve entre deux images.", "it_IT": "Il punto di stacco della sequenza è tra due fotogrammi.", "ja_JP": "シーケンスのアウトポイントがフレームの間にあります。", "ko_KR": "시퀀스 종료 지점이 두 프레임 사이에 있습니다.", "pt_BR": "O ponto de saída da sequência está entre dois quadros.", "ru_RU": "Точка выхода эпизода находится между двумя кадрами.", "zh_CN": "序列出点位于两帧之间。" }, "location": "sequence.outPoint", "data": { "point": { "literal": "out" }, "offsetTicks": "sequence.outPointFrameOffset" } } ], "matching": "all", "data": { "frameDuration": "sequence.frameDuration" } } ``` # Tiny clips (/docs/rules/no-tiny-clips) Reports clips only a few frames long, usually leftovers of a trim. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :-------------- | | Id | `no-tiny-clips` | | Category | Static | | Default severity | warning | | Scope | `clip` | ## Options [#options] | Option | Type | Default | Description | | :------------------------ | :-------- | :------ | :--------------------------------------------------------------------------------------- | | `minFrames` | `number` | `3` | Clips shorter than this many whole frames are reported. A clip exactly this long is not. | | `includeAudio` | `boolean` | `true` | Also check audio clips. | | `includeAdjustmentLayers` | `boolean` | `false` | Also check adjustment layers; short ones are often deliberate. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-tiny-clips.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-tiny-clips.rule.json" { "formatVersion": 1, "id": "no-tiny-clips", "name": { "en_US": "Tiny clips", "de_DE": "Winzige Clips", "es_ES": "Clips diminutos", "fr_FR": "Éléments minuscules", "it_IT": "Clip minuscole", "ja_JP": "極端に短いクリップ", "ko_KR": "아주 짧은 클립", "pt_BR": "Clipes minúsculos", "ru_RU": "Слишком короткие клипы", "zh_CN": "极短剪辑" }, "description": { "en_US": "Reports clips only a few frames long, usually leftovers of a trim.", "de_DE": "Meldet Clips, die nur wenige Frames lang sind, meist Reste eines Trimmvorgangs.", "es_ES": "Detecta clips de solo unos pocos fotogramas, normalmente restos de un recorte.", "fr_FR": "Signale les éléments de quelques images seulement, souvent des restes de raccord.", "it_IT": "Segnala le clip lunghe solo pochi fotogrammi, di solito residui di un taglio.", "ja_JP": "数フレームしかない、トリミングの残りと思われるクリップを報告します。", "ko_KR": "몇 프레임 길이밖에 되지 않는 클립(대개 트리밍 후 남은 조각)을 보고합니다.", "pt_BR": "Relata clipes com apenas alguns quadros de duração, geralmente sobras de um corte.", "ru_RU": "Сообщает о клипах длиной всего несколько кадров, обычно оставшихся после обрезки.", "zh_CN": "报告仅有几帧长的剪辑,通常是修剪后的残留。" }, "category": "static", "scope": "clip", "severity": "warning", "options": { "minFrames": { "type": "number", "default": 3, "description": "Clips shorter than this many whole frames are reported. A clip exactly this long is not." }, "includeAudio": { "type": "boolean", "default": true, "description": "Also check audio clips." }, "includeAdjustmentLayers": { "type": "boolean", "default": false, "description": "Also check adjustment layers; short ones are often deliberate." } }, "checks": [ { "condition": { "all": [ { "field": "clip.duration", "operator": "greaterThan", "value": 0 }, { "field": "clip.durationFrames", "operator": "lessThan", "value": { "field": "options.minFrames" } }, { "any": [ { "field": "clip.trackType", "operator": "equals", "value": "video" }, { "field": "options.includeAudio", "operator": "equals", "value": true } ] }, { "any": [ { "field": "clip.adjustmentLayer", "operator": "equals", "value": false }, { "field": "options.includeAdjustmentLayers", "operator": "equals", "value": true } ] } ] }, "message": { "en_US": { "count": "clip.durationFrames", "one": "Clip \"{clip.name}\" on {clip.track} is {clip.durationFrames} frame long (minimum {options.minFrames}).", "other": "Clip \"{clip.name}\" on {clip.track} is {clip.durationFrames} frames long (minimum {options.minFrames})." }, "de_DE": { "count": "clip.durationFrames", "one": "Clip „{clip.name}“ auf {clip.track} ist {clip.durationFrames} Frame lang (mindestens {options.minFrames}).", "other": "Clip „{clip.name}“ auf {clip.track} ist {clip.durationFrames} Frames lang (mindestens {options.minFrames})." }, "es_ES": { "count": "clip.durationFrames", "one": "Clip \"{clip.name}\" en {clip.track} dura {clip.durationFrames} fotograma (mínimo: {options.minFrames}).", "other": "Clip \"{clip.name}\" en {clip.track} dura {clip.durationFrames} fotogramas (mínimo: {options.minFrames})." }, "fr_FR": { "count": "clip.durationFrames", "one": "Élément « {clip.name} » sur {clip.track} dure {clip.durationFrames} image (minimum : {options.minFrames}).", "other": "Élément « {clip.name} » sur {clip.track} dure {clip.durationFrames} images (minimum : {options.minFrames})." }, "it_IT": { "count": "clip.durationFrames", "one": "Clip \"{clip.name}\" su {clip.track} dura {clip.durationFrames} fotogramma (minimo {options.minFrames}).", "other": "Clip \"{clip.name}\" su {clip.track} dura {clip.durationFrames} fotogrammi (minimo {options.minFrames})." }, "ja_JP": "クリップ「{clip.name}」({clip.track})の長さは{clip.durationFrames}フレームです(最小{options.minFrames}フレーム)。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 길이가 {clip.durationFrames}프레임입니다(최소 {options.minFrames}).", "pt_BR": { "count": "clip.durationFrames", "one": "Clipe \"{clip.name}\" em {clip.track} tem {clip.durationFrames} quadro de duração (mínimo {options.minFrames}).", "other": "Clipe \"{clip.name}\" em {clip.track} tem {clip.durationFrames} quadros de duração (mínimo {options.minFrames})." }, "ru_RU": { "count": "clip.durationFrames", "one": "Клип «{clip.name}» на {clip.track} длится {clip.durationFrames} кадр (минимум {options.minFrames}).", "few": "Клип «{clip.name}» на {clip.track} длится {clip.durationFrames} кадра (минимум {options.minFrames}).", "many": "Клип «{clip.name}» на {clip.track} длится {clip.durationFrames} кадров (минимум {options.minFrames}).", "other": "Клип «{clip.name}» на {clip.track} длится {clip.durationFrames} кадра (минимум {options.minFrames})." }, "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 长度为 {clip.durationFrames} 帧(最少 {options.minFrames} 帧)。" } } ], "data": { "durationTicks": "clip.duration", "durationFrames": "clip.durationFrames", "minFrames": "options.minFrames" } } ``` # Video gaps (/docs/rules/no-video-gaps) Reports ranges of the work area where no video clip is visible (black frames). {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :-------------------------------------------------------------------------- | | Id | `no-video-gaps` | | Category | Static | | Default severity | warning | | Scope | [`video-gaps`](/docs/reference/computed-scopes#video-gaps) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :---------- | :-------- | :------ | :--------------------------------------------------- | | `minFrames` | `number` | `1` | Gaps shorter than this many frames are not reported. | | `leading` | `boolean` | `true` | Report a gap at the start of the work area. | | `trailing` | `boolean` | `true` | Report a gap at the end of the work area. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-video-gaps.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-video-gaps.rule.json" { "formatVersion": 1, "id": "no-video-gaps", "name": { "en_US": "Video gaps", "de_DE": "Videolücken", "es_ES": "Huecos de vídeo", "fr_FR": "Blancs vidéo", "it_IT": "Vuoti video", "ja_JP": "ビデオの欠落", "ko_KR": "비디오 간격", "pt_BR": "Lacunas de vídeo", "ru_RU": "Пропуски видео", "zh_CN": "视频间隙" }, "description": { "en_US": "Reports ranges of the work area where no video clip is visible (black frames).", "de_DE": "Meldet Bereiche des Arbeitsbereichs, in denen kein Videoclip sichtbar ist (Schwarzbild).", "es_ES": "Detecta intervalos del área de trabajo en los que no se ve ningún clip de vídeo (fotogramas en negro).", "fr_FR": "Signale les plages de la zone de travail où aucun élément vidéo n'est visible (images noires).", "it_IT": "Segnala gli intervalli dell'area di lavoro in cui nessuna clip video è visibile (fotogrammi neri).", "ja_JP": "ワークエリア内で、表示されるビデオクリップがない範囲(黒いフレーム)を報告します。", "ko_KR": "작업 영역에서 보이는 비디오 클립이 없는 구간(검은 프레임)을 보고합니다.", "pt_BR": "Relata intervalos da área de trabalho em que nenhum clipe de vídeo é visível (quadros pretos).", "ru_RU": "Сообщает об участках рабочей области, где не видно ни одного видеоклипа (черные кадры).", "zh_CN": "报告工作区域中没有可见视频剪辑的范围(黑帧)。" }, "category": "static", "scope": "video-gaps", "severity": "warning", "options": { "minFrames": { "type": "number", "default": 1, "description": "Gaps shorter than this many frames are not reported." }, "leading": { "type": "boolean", "default": true, "description": "Report a gap at the start of the work area." }, "trailing": { "type": "boolean", "default": true, "description": "Report a gap at the end of the work area." } }, "checks": [ { "condition": { "all": [ { "field": "gap.durationFrames", "operator": "greaterThanOrEqual", "value": { "field": "options.minFrames" } }, { "any": [ { "field": "gap.kind", "operator": "equals", "value": "inner" }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "leading" }, { "field": "options.leading", "operator": "equals", "value": true } ] }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "trailing" }, { "field": "options.trailing", "operator": "equals", "value": true } ] } ] }, { "all": [ { "field": "gap.hasBefore", "operator": "equals", "value": true }, { "field": "gap.hasAfter", "operator": "equals", "value": true } ] } ] }, "message": { "en_US": "Black video for {labels.duration} ({gap.startTimecode} to {gap.endTimecode}) between \"{gap.beforeName}\" on {gap.beforeTrack} and \"{gap.afterName}\" on {gap.afterTrack}.", "de_DE": "Schwarzbild für {labels.duration} ({gap.startTimecode} bis {gap.endTimecode}) zwischen „{gap.beforeName}“ auf {gap.beforeTrack} und „{gap.afterName}“ auf {gap.afterTrack}.", "es_ES": "Vídeo en negro durante {labels.duration} (de {gap.startTimecode} a {gap.endTimecode}) entre \"{gap.beforeName}\" en {gap.beforeTrack} y \"{gap.afterName}\" en {gap.afterTrack}.", "fr_FR": "Vidéo noire pendant {labels.duration} ({gap.startTimecode} à {gap.endTimecode}) entre « {gap.beforeName} » sur {gap.beforeTrack} et « {gap.afterName} » sur {gap.afterTrack}.", "it_IT": "Video nero per {labels.duration} (da {gap.startTimecode} a {gap.endTimecode}) tra \"{gap.beforeName}\" su {gap.beforeTrack} e \"{gap.afterName}\" su {gap.afterTrack}.", "ja_JP": "「{gap.beforeName}」({gap.beforeTrack})と「{gap.afterName}」({gap.afterTrack})の間に{labels.duration}の黒いビデオがあります({gap.startTimecode}~{gap.endTimecode})。", "ko_KR": "{labels.duration} 동안 검은 화면({gap.startTimecode}~{gap.endTimecode}): {gap.beforeTrack}의 \"{gap.beforeName}\" 뒤, {gap.afterTrack}의 \"{gap.afterName}\" 앞.", "pt_BR": "Vídeo preto por {labels.duration} ({gap.startTimecode} a {gap.endTimecode}) entre \"{gap.beforeName}\" em {gap.beforeTrack} e \"{gap.afterName}\" em {gap.afterTrack}.", "ru_RU": "Черный экран в течение {labels.duration} (с {gap.startTimecode} по {gap.endTimecode}) между «{gap.beforeName}» на {gap.beforeTrack} и «{gap.afterName}» на {gap.afterTrack}.", "zh_CN": "{labels.duration} 黑场视频({gap.startTimecode} 至 {gap.endTimecode}),位于 {gap.beforeTrack} 上的“{gap.beforeName}” 和 {gap.afterTrack} 上的“{gap.afterName}” 之间。" } }, { "condition": { "all": [ { "field": "gap.durationFrames", "operator": "greaterThanOrEqual", "value": { "field": "options.minFrames" } }, { "any": [ { "field": "gap.kind", "operator": "equals", "value": "inner" }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "leading" }, { "field": "options.leading", "operator": "equals", "value": true } ] }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "trailing" }, { "field": "options.trailing", "operator": "equals", "value": true } ] } ] }, { "all": [ { "field": "gap.hasBefore", "operator": "equals", "value": false }, { "field": "gap.hasAfter", "operator": "equals", "value": true } ] } ] }, "message": { "en_US": "Black video for {labels.duration} ({gap.startTimecode} to {gap.endTimecode}) before \"{gap.afterName}\" on {gap.afterTrack}.", "de_DE": "Schwarzbild für {labels.duration} ({gap.startTimecode} bis {gap.endTimecode}) vor „{gap.afterName}“ auf {gap.afterTrack}.", "es_ES": "Vídeo en negro durante {labels.duration} (de {gap.startTimecode} a {gap.endTimecode}) antes de \"{gap.afterName}\" en {gap.afterTrack}.", "fr_FR": "Vidéo noire pendant {labels.duration} ({gap.startTimecode} à {gap.endTimecode}) avant « {gap.afterName} » sur {gap.afterTrack}.", "it_IT": "Video nero per {labels.duration} (da {gap.startTimecode} a {gap.endTimecode}) prima di \"{gap.afterName}\" su {gap.afterTrack}.", "ja_JP": "「{gap.afterName}」({gap.afterTrack})の前に{labels.duration}の黒いビデオがあります({gap.startTimecode}~{gap.endTimecode})。", "ko_KR": "{labels.duration} 동안 검은 화면({gap.startTimecode}~{gap.endTimecode}): {gap.afterTrack}의 \"{gap.afterName}\" 앞.", "pt_BR": "Vídeo preto por {labels.duration} ({gap.startTimecode} a {gap.endTimecode}) antes de \"{gap.afterName}\" em {gap.afterTrack}.", "ru_RU": "Черный экран в течение {labels.duration} (с {gap.startTimecode} по {gap.endTimecode}) перед «{gap.afterName}» на {gap.afterTrack}.", "zh_CN": "{labels.duration} 黑场视频({gap.startTimecode} 至 {gap.endTimecode}),位于 {gap.afterTrack} 上的“{gap.afterName}” 之前。" } }, { "condition": { "all": [ { "field": "gap.durationFrames", "operator": "greaterThanOrEqual", "value": { "field": "options.minFrames" } }, { "any": [ { "field": "gap.kind", "operator": "equals", "value": "inner" }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "leading" }, { "field": "options.leading", "operator": "equals", "value": true } ] }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "trailing" }, { "field": "options.trailing", "operator": "equals", "value": true } ] } ] }, { "all": [ { "field": "gap.hasBefore", "operator": "equals", "value": true }, { "field": "gap.hasAfter", "operator": "equals", "value": false } ] } ] }, "message": { "en_US": "Black video for {labels.duration} ({gap.startTimecode} to {gap.endTimecode}) after \"{gap.beforeName}\" on {gap.beforeTrack}.", "de_DE": "Schwarzbild für {labels.duration} ({gap.startTimecode} bis {gap.endTimecode}) nach „{gap.beforeName}“ auf {gap.beforeTrack}.", "es_ES": "Vídeo en negro durante {labels.duration} (de {gap.startTimecode} a {gap.endTimecode}) después de \"{gap.beforeName}\" en {gap.beforeTrack}.", "fr_FR": "Vidéo noire pendant {labels.duration} ({gap.startTimecode} à {gap.endTimecode}) après « {gap.beforeName} » sur {gap.beforeTrack}.", "it_IT": "Video nero per {labels.duration} (da {gap.startTimecode} a {gap.endTimecode}) dopo \"{gap.beforeName}\" su {gap.beforeTrack}.", "ja_JP": "「{gap.beforeName}」({gap.beforeTrack})の後に{labels.duration}の黒いビデオがあります({gap.startTimecode}~{gap.endTimecode})。", "ko_KR": "{labels.duration} 동안 검은 화면({gap.startTimecode}~{gap.endTimecode}): {gap.beforeTrack}의 \"{gap.beforeName}\" 뒤.", "pt_BR": "Vídeo preto por {labels.duration} ({gap.startTimecode} a {gap.endTimecode}) depois de \"{gap.beforeName}\" em {gap.beforeTrack}.", "ru_RU": "Черный экран в течение {labels.duration} (с {gap.startTimecode} по {gap.endTimecode}) после «{gap.beforeName}» на {gap.beforeTrack}.", "zh_CN": "{labels.duration} 黑场视频({gap.startTimecode} 至 {gap.endTimecode}),位于 {gap.beforeTrack} 上的“{gap.beforeName}” 之后。" } }, { "condition": { "all": [ { "field": "gap.durationFrames", "operator": "greaterThanOrEqual", "value": { "field": "options.minFrames" } }, { "any": [ { "field": "gap.kind", "operator": "equals", "value": "inner" }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "leading" }, { "field": "options.leading", "operator": "equals", "value": true } ] }, { "all": [ { "field": "gap.kind", "operator": "equals", "value": "trailing" }, { "field": "options.trailing", "operator": "equals", "value": true } ] } ] }, { "all": [ { "field": "gap.hasBefore", "operator": "equals", "value": false }, { "field": "gap.hasAfter", "operator": "equals", "value": false } ] } ] }, "message": { "en_US": "Black video for {labels.duration} ({gap.startTimecode} to {gap.endTimecode}).", "de_DE": "Schwarzbild für {labels.duration} ({gap.startTimecode} bis {gap.endTimecode}).", "es_ES": "Vídeo en negro durante {labels.duration} (de {gap.startTimecode} a {gap.endTimecode}).", "fr_FR": "Vidéo noire pendant {labels.duration} ({gap.startTimecode} à {gap.endTimecode}).", "it_IT": "Video nero per {labels.duration} (da {gap.startTimecode} a {gap.endTimecode}).", "ja_JP": "{labels.duration}の黒いビデオがあります({gap.startTimecode}~{gap.endTimecode})。", "ko_KR": "{labels.duration} 동안 검은 화면({gap.startTimecode}~{gap.endTimecode}).", "pt_BR": "Vídeo preto por {labels.duration} ({gap.startTimecode} a {gap.endTimecode}).", "ru_RU": "Черный экран в течение {labels.duration} (с {gap.startTimecode} по {gap.endTimecode}).", "zh_CN": "{labels.duration} 黑场视频({gap.startTimecode} 至 {gap.endTimecode})。" } } ], "labels": { "duration": { "field": "gap.durationIsSeconds", "values": { "true": { "en_US": "{gap.durationSeconds} s", "de_DE": "{gap.durationSeconds} s", "es_ES": "{gap.durationSeconds} s", "fr_FR": "{gap.durationSeconds} s", "it_IT": "{gap.durationSeconds} s", "ja_JP": "{gap.durationSeconds} s", "ko_KR": "{gap.durationSeconds} s", "pt_BR": "{gap.durationSeconds} s", "ru_RU": "{gap.durationSeconds} с", "zh_CN": "{gap.durationSeconds} s" }, "false": { "en_US": { "count": "gap.durationFramesRounded", "one": "{gap.durationFramesRounded} frame", "other": "{gap.durationFramesRounded} frames" }, "de_DE": { "count": "gap.durationFramesRounded", "one": "{gap.durationFramesRounded} Frame", "other": "{gap.durationFramesRounded} Frames" }, "es_ES": { "count": "gap.durationFramesRounded", "one": "{gap.durationFramesRounded} fotograma", "other": "{gap.durationFramesRounded} fotogramas" }, "fr_FR": { "count": "gap.durationFramesRounded", "one": "{gap.durationFramesRounded} image", "other": "{gap.durationFramesRounded} images" }, "it_IT": { "count": "gap.durationFramesRounded", "one": "{gap.durationFramesRounded} fotogramma", "other": "{gap.durationFramesRounded} fotogrammi" }, "ja_JP": "{gap.durationFramesRounded}フレーム", "ko_KR": "{gap.durationFramesRounded}프레임", "pt_BR": { "count": "gap.durationFramesRounded", "one": "{gap.durationFramesRounded} quadro", "other": "{gap.durationFramesRounded} quadros" }, "ru_RU": { "count": "gap.durationFramesRounded", "one": "{gap.durationFramesRounded} кадр", "few": "{gap.durationFramesRounded} кадра", "many": "{gap.durationFramesRounded} кадров", "other": "{gap.durationFramesRounded} кадра" }, "zh_CN": "{gap.durationFramesRounded} 帧" } } } }, "data": { "gapStart": "gap.start", "gapEnd": "gap.end", "gapTicks": "gap.durationTicks", "kind": "gap.kind", "gapFrames": "gap.durationFrames", "minFrames": "options.minFrames" } } ``` # Zero-duration clips (/docs/rules/no-zero-duration-clips) Reports clips whose end is not after their start. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :----------------------- | | Id | `no-zero-duration-clips` | | Category | Static | | Default severity | error | | Scope | `clip` | ## Options [#options] This rule has no options. ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `no-zero-duration-clips.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="no-zero-duration-clips.rule.json" { "formatVersion": 1, "id": "no-zero-duration-clips", "name": { "en_US": "Zero-duration clips", "de_DE": "Clips ohne Dauer", "es_ES": "Clips de duración cero", "fr_FR": "Éléments de durée nulle", "it_IT": "Clip di durata zero", "ja_JP": "デュレーションが 0 のクリップ", "ko_KR": "지속 시간이 0인 클립", "pt_BR": "Clipes de duração zero", "ru_RU": "Клипы нулевой длительности", "zh_CN": "零持续时间剪辑" }, "description": { "en_US": "Reports clips whose end is not after their start.", "de_DE": "Meldet Clips, deren Ende nicht nach ihrem Anfang liegt.", "es_ES": "Detecta clips cuyo final no es posterior a su inicio.", "fr_FR": "Signale les éléments dont la fin n'est pas postérieure au début.", "it_IT": "Segnala le clip la cui fine non è successiva all'inizio.", "ja_JP": "終了が開始より後にないクリップを報告します。", "ko_KR": "끝이 시작보다 뒤에 있지 않은 클립을 보고합니다.", "pt_BR": "Relata clipes cujo fim não é posterior ao início.", "ru_RU": "Сообщает о клипах, конец которых не находится после начала.", "zh_CN": "报告结尾不晚于开头的剪辑。" }, "category": "static", "scope": "clip", "severity": "error", "checks": [ { "condition": { "field": "clip.duration", "operator": "equals", "value": 0 }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} has zero duration.", "de_DE": "Clip „{clip.name}“ auf {clip.track} hat die Dauer null.", "es_ES": "Clip \"{clip.name}\" en {clip.track} tiene duración cero.", "fr_FR": "Élément « {clip.name} » sur {clip.track} a une durée nulle.", "it_IT": "Clip \"{clip.name}\" su {clip.track} ha durata zero.", "ja_JP": "クリップ「{clip.name}」({clip.track})のデュレーションが0です。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 지속 시간이 0입니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} tem duração zero.", "ru_RU": "Клип «{clip.name}» на {clip.track} имеет нулевую длительность.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 的持续时间为零。" } }, { "condition": { "field": "clip.duration", "operator": "lessThan", "value": 0 }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} ends before it starts.", "de_DE": "Clip „{clip.name}“ auf {clip.track} endet, bevor er beginnt.", "es_ES": "Clip \"{clip.name}\" en {clip.track} termina antes de empezar.", "fr_FR": "Élément « {clip.name} » sur {clip.track} se termine avant de commencer.", "it_IT": "Clip \"{clip.name}\" su {clip.track} termina prima di iniziare.", "ja_JP": "クリップ「{clip.name}」({clip.track})は開始より前に終了しています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 끝이 시작보다 앞에 있습니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} termina antes de começar.", "ru_RU": "Клип «{clip.name}» на {clip.track} заканчивается раньше, чем начинается.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 的结尾早于开头。" } } ], "data": { "durationTicks": "clip.duration" } } ``` # Required effects (/docs/rules/required-effects) Reports clips missing a configured effect. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :-------------------------------------------------------------------------------------- | | Id | `required-effects` | | Category | Project | | Default severity | warning | | Scope | [`required-effects`](/docs/reference/computed-scopes#required-effects) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :------------ | :--------- | :------------- | :---------------------------------------------------------------------------------------------------------------------------- | | `effects` | `json` | `[]` | Requirements: \{ "matchName", "tracks"?: \["V1"], "trackType"?: "video" \| "audio", "message"? }. Empty: nothing is required. | | `ignoreKinds` | `string[]` | `["sequence"]` | Source kinds exempt from requirements. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `required-effects.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="required-effects.rule.json" { "formatVersion": 1, "id": "required-effects", "name": { "en_US": "Required effects", "de_DE": "Erforderliche Effekte", "es_ES": "Efectos obligatorios", "fr_FR": "Effets requis", "it_IT": "Effetti obbligatori", "ja_JP": "必須のエフェクト", "ko_KR": "필수 효과", "pt_BR": "Efeitos obrigatórios", "ru_RU": "Обязательные эффекты", "zh_CN": "必需效果" }, "description": { "en_US": "Reports clips missing a configured effect.", "de_DE": "Meldet Clips, denen ein konfigurierter Effekt fehlt.", "es_ES": "Detecta clips a los que les falta un efecto configurado.", "fr_FR": "Signale les éléments auxquels il manque un effet configuré.", "it_IT": "Segnala le clip prive di un effetto configurato.", "ja_JP": "設定されたエフェクトがないクリップを報告します。", "ko_KR": "설정된 효과가 없는 클립을 보고합니다.", "pt_BR": "Relata clipes sem um efeito configurado.", "ru_RU": "Сообщает о клипах без заданного эффекта.", "zh_CN": "报告缺少已配置效果的剪辑。" }, "category": "project", "scope": "required-effects", "severity": "warning", "options": { "effects": { "type": "json", "default": [], "description": "Requirements: { \"matchName\", \"tracks\"?: [\"V1\"], \"trackType\"?: \"video\" | \"audio\", \"message\"? }. Empty: nothing is required." }, "ignoreKinds": { "type": "string[]", "default": [ "sequence" ], "description": "Source kinds exempt from requirements." } }, "checks": [ { "condition": { "field": "requirement.matchName", "operator": "exists" }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is missing required effect \"{requirement.displayName}\".{requirement.explanation}", "de_DE": "Bei Clip „{clip.name}“ auf {clip.track} fehlt der erforderliche Effekt „{requirement.displayName}“.{requirement.explanation}", "es_ES": "Clip \"{clip.name}\" en {clip.track} no tiene el efecto obligatorio \"{requirement.displayName}\".{requirement.explanation}", "fr_FR": "Il manque l'effet requis « {requirement.displayName} » sur Élément « {clip.name} » sur {clip.track}.{requirement.explanation}", "it_IT": "Clip \"{clip.name}\" su {clip.track} non ha l'effetto obbligatorio \"{requirement.displayName}\".{requirement.explanation}", "ja_JP": "クリップ「{clip.name}」({clip.track})に必須のエフェクト「{requirement.displayName}」がありません。{requirement.explanation}", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"에 필수 효과 \"{requirement.displayName}\"이(가) 없습니다.{requirement.explanation}", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} não tem o efeito obrigatório \"{requirement.displayName}\".{requirement.explanation}", "ru_RU": "Клип «{clip.name}» на {clip.track} не содержит обязательный эффект «{requirement.displayName}».{requirement.explanation}", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 缺少必需效果“{requirement.displayName}”。{requirement.explanation}" } } ], "data": { "matchName": "requirement.matchName", "tracks": "requirement.tracks", "trackType": "requirement.trackType" } } ``` # Required markers (/docs/rules/required-markers) Reports configured sequence markers that are missing. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :-------------------------------------------------------------------------------------- | | Id | `required-markers` | | Category | Project | | Default severity | warning | | Scope | [`required-markers`](/docs/reference/computed-scopes#required-markers) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :-------- | :----- | :------ | :------------------------------------------------------------------------------------------------------------------------------------------------------ | | `markers` | `json` | `[]` | Requirements: \{ "type"?, "name"?, "namePattern"?, "colorIndex"?, "minCount"? (1), "message"? }; criteria combine with AND. Empty: nothing is required. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `required-markers.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="required-markers.rule.json" { "formatVersion": 1, "id": "required-markers", "name": { "en_US": "Required markers", "de_DE": "Erforderliche Marken", "es_ES": "Marcadores obligatorios", "fr_FR": "Marques requises", "it_IT": "Marcatori obbligatori", "ja_JP": "必須のマーカー", "ko_KR": "필수 마커", "pt_BR": "Marcadores obrigatórios", "ru_RU": "Обязательные маркеры", "zh_CN": "必需标记" }, "description": { "en_US": "Reports configured sequence markers that are missing.", "de_DE": "Meldet fehlende konfigurierte Sequenzmarken.", "es_ES": "Detecta los marcadores de secuencia configurados que faltan.", "fr_FR": "Signale les marques de séquence configurées qui sont absentes.", "it_IT": "Segnala i marcatori di sequenza configurati che mancano.", "ja_JP": "設定されたシーケンスマーカーがない場合に報告します。", "ko_KR": "설정된 시퀀스 마커 중 없는 마커를 보고합니다.", "pt_BR": "Relata marcadores de sequência configurados que estão ausentes.", "ru_RU": "Сообщает об отсутствующих заданных маркерах эпизода.", "zh_CN": "报告缺失的已配置序列标记。" }, "category": "project", "scope": "required-markers", "severity": "warning", "options": { "markers": { "type": "json", "default": [], "description": "Requirements: { \"type\"?, \"name\"?, \"namePattern\"?, \"colorIndex\"?, \"minCount\"? (1), \"message\"? }; criteria combine with AND. Empty: nothing is required." } }, "checks": [ { "condition": { "field": "requirement.found", "operator": "equals", "value": 0 }, "message": { "en_US": "Sequence has no {labels.word}{labels.named}{labels.matching}{labels.color} (at least {requirement.minCount} required).{requirement.explanation}", "de_DE": "Die Sequenz hat keine {labels.word}{labels.named}{labels.matching}{labels.color} (mindestens {requirement.minCount} erforderlich).{requirement.explanation}", "es_ES": "La secuencia no tiene {labels.word}{labels.named}{labels.matching}{labels.color} (mínimo obligatorio: {requirement.minCount}).{requirement.explanation}", "fr_FR": "La séquence ne comporte aucune {labels.word}{labels.named}{labels.matching}{labels.color} (minimum requis : {requirement.minCount}).{requirement.explanation}", "it_IT": "La sequenza non ha alcun {labels.word}{labels.named}{labels.matching}{labels.color} (almeno {requirement.minCount} richiesti).{requirement.explanation}", "ja_JP": "シーケンスに{labels.word}{labels.named}{labels.matching}{labels.color}がありません({requirement.minCount}個以上必要)。{requirement.explanation}", "ko_KR": "시퀀스에 다음이 없습니다: {labels.word}{labels.named}{labels.matching}{labels.color}(최소 {requirement.minCount}개 필요).{requirement.explanation}", "pt_BR": "A sequência não tem nenhum {labels.word}{labels.named}{labels.matching}{labels.color} (mínimo exigido: {requirement.minCount}).{requirement.explanation}", "ru_RU": "В эпизоде отсутствует {labels.word}{labels.named}{labels.matching}{labels.color} (требуется не менее {requirement.minCount}).{requirement.explanation}", "zh_CN": "序列中没有{labels.word}{labels.named}{labels.matching}{labels.color}(至少需要 {requirement.minCount} 个)。{requirement.explanation}" } }, { "condition": { "field": "requirement.found", "operator": "greaterThan", "value": 0 }, "message": { "en_US": "Sequence has {requirement.found} {labels.word}{labels.named}{labels.matching}{labels.color} (at least {requirement.minCount} required).{requirement.explanation}", "de_DE": "Die Sequenz hat {requirement.found} {labels.word}{labels.named}{labels.matching}{labels.color} (mindestens {requirement.minCount} erforderlich).{requirement.explanation}", "es_ES": "La secuencia tiene {requirement.found} {labels.word}{labels.named}{labels.matching}{labels.color} (mínimo obligatorio: {requirement.minCount}).{requirement.explanation}", "fr_FR": "La séquence comporte {requirement.found} {labels.word}{labels.named}{labels.matching}{labels.color} (minimum requis : {requirement.minCount}).{requirement.explanation}", "it_IT": "La sequenza ha {requirement.found} {labels.word}{labels.named}{labels.matching}{labels.color} (almeno {requirement.minCount} richiesti).{requirement.explanation}", "ja_JP": "シーケンスの{labels.word}{labels.named}{labels.matching}{labels.color}は{requirement.found}個です({requirement.minCount}個以上必要)。{requirement.explanation}", "ko_KR": "시퀀스의 {labels.word}{labels.named}{labels.matching}{labels.color}: {requirement.found}개(최소 {requirement.minCount}개 필요).{requirement.explanation}", "pt_BR": "A sequência tem {requirement.found} {labels.word}{labels.named}{labels.matching}{labels.color} (mínimo exigido: {requirement.minCount}).{requirement.explanation}", "ru_RU": "В эпизоде только {requirement.found} {labels.word}{labels.named}{labels.matching}{labels.color} (требуется не менее {requirement.minCount}).{requirement.explanation}", "zh_CN": "序列中有 {requirement.found} 个{labels.word}{labels.named}{labels.matching}{labels.color}(至少需要 {requirement.minCount} 个)。{requirement.explanation}" } } ], "labels": { "word": { "field": "requirement.hasType", "values": { "true": { "en_US": { "count": "requirement.pluralCount", "one": "\"{requirement.type}\" marker", "other": "\"{requirement.type}\" markers" }, "de_DE": { "count": "requirement.pluralCount", "one": "„{requirement.type}“-Marke", "other": "„{requirement.type}“-Marken" }, "es_ES": { "count": "requirement.pluralCount", "one": "marcador de tipo \"{requirement.type}\"", "other": "marcadores de tipo \"{requirement.type}\"" }, "fr_FR": { "count": "requirement.pluralCount", "one": "marque de type « {requirement.type} »", "other": "marques de type « {requirement.type} »" }, "it_IT": { "count": "requirement.pluralCount", "one": "marcatore \"{requirement.type}\"", "other": "marcatori \"{requirement.type}\"" }, "ja_JP": "「{requirement.type}」マーカー", "ko_KR": "\"{requirement.type}\" 마커", "pt_BR": { "count": "requirement.pluralCount", "one": "marcador \"{requirement.type}\"", "other": "marcadores \"{requirement.type}\"" }, "ru_RU": { "count": "requirement.pluralCount", "one": "маркер «{requirement.type}»", "few": "маркера «{requirement.type}»", "many": "маркеров «{requirement.type}»", "other": "маркера «{requirement.type}»" }, "zh_CN": "“{requirement.type}”标记" }, "false": { "en_US": { "count": "requirement.pluralCount", "one": "marker", "other": "markers" }, "de_DE": { "count": "requirement.pluralCount", "one": "Marke", "other": "Marken" }, "es_ES": { "count": "requirement.pluralCount", "one": "marcador", "other": "marcadores" }, "fr_FR": { "count": "requirement.pluralCount", "one": "marque", "other": "marques" }, "it_IT": { "count": "requirement.pluralCount", "one": "marcatore", "other": "marcatori" }, "ja_JP": "マーカー", "ko_KR": "마커", "pt_BR": { "count": "requirement.pluralCount", "one": "marcador", "other": "marcadores" }, "ru_RU": { "count": "requirement.pluralCount", "one": "маркер", "few": "маркера", "many": "маркеров", "other": "маркера" }, "zh_CN": "标记" } } }, "named": { "field": "requirement.hasName", "values": { "true": { "en_US": " named \"{requirement.name}\"", "de_DE": " namens „{requirement.name}“", "es_ES": " con el nombre \"{requirement.name}\"", "fr_FR": " avec le nom « {requirement.name} »", "it_IT": " con nome \"{requirement.name}\"", "ja_JP": " (名前「{requirement.name}」)", "ko_KR": " (이름: \"{requirement.name}\")", "pt_BR": " com o nome \"{requirement.name}\"", "ru_RU": " с именем «{requirement.name}»", "zh_CN": " 名为“{requirement.name}”的" }, "false": "" } }, "matching": { "field": "requirement.hasPattern", "values": { "true": { "en_US": " matching /{requirement.namePattern}/", "de_DE": " passend zu /{requirement.namePattern}/", "es_ES": " con el patrón /{requirement.namePattern}/", "fr_FR": " correspondant à /{requirement.namePattern}/", "it_IT": " con nome conforme a /{requirement.namePattern}/", "ja_JP": " (/{requirement.namePattern}/ に一致)", "ko_KR": " (/{requirement.namePattern}/ 일치)", "pt_BR": " com nome correspondente a /{requirement.namePattern}/", "ru_RU": " с именем по шаблону /{requirement.namePattern}/", "zh_CN": " 匹配 /{requirement.namePattern}/ 的" }, "false": "" } }, "color": { "field": "requirement.hasColor", "values": { "true": { "en_US": " with color index {requirement.colorIndex}", "de_DE": " mit Farbindex {requirement.colorIndex}", "es_ES": " con el índice de color {requirement.colorIndex}", "fr_FR": " avec l'indice de couleur {requirement.colorIndex}", "it_IT": " con indice colore {requirement.colorIndex}", "ja_JP": " (カラーインデックス {requirement.colorIndex})", "ko_KR": " (색상 인덱스 {requirement.colorIndex})", "pt_BR": " com o índice de cor {requirement.colorIndex}", "ru_RU": " с индексом цвета {requirement.colorIndex}", "zh_CN": " 颜色索引为 {requirement.colorIndex} 的" }, "false": "" } } }, "data": { "requirement": "requirement.requirement", "found": "requirement.found", "minCount": "requirement.minCount" } } ``` # Required tracks (/docs/rules/required-tracks) Reports a track layout that does not match the configured requirements. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :------------------------------------------------------------------------------------ | | Id | `required-tracks` | | Category | Project | | Default severity | warning | | Scope | [`required-tracks`](/docs/reference/computed-scopes#required-tracks) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :---------------- | :--------- | :------ | :----------------------------------------------------------------- | | `minVideoTracks` | `number` | `0` | Minimum number of video tracks. 0: not checked. | | `minAudioTracks` | `number` | `0` | Minimum number of audio tracks. 0: not checked. | | `videoTrackNames` | `string[]` | `[]` | Names that must exist among video tracks. | | `audioTrackNames` | `string[]` | `[]` | Names that must exist among audio tracks. | | `tracks` | `json` | `[]` | Per-position requirements: \{ "ref": "V1", "name"?, "nonEmpty"? }. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `required-tracks.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="required-tracks.rule.json" { "formatVersion": 1, "id": "required-tracks", "name": { "en_US": "Required tracks", "de_DE": "Erforderliche Spuren", "es_ES": "Pistas obligatorias", "fr_FR": "Pistes requises", "it_IT": "Tracce obbligatorie", "ja_JP": "必須のトラック", "ko_KR": "필수 트랙", "pt_BR": "Trilhas obrigatórias", "ru_RU": "Обязательные дорожки", "zh_CN": "必需轨道" }, "description": { "en_US": "Reports a track layout that does not match the configured requirements.", "de_DE": "Meldet ein Spurlayout, das nicht den konfigurierten Anforderungen entspricht.", "es_ES": "Detecta una disposición de pistas que no cumple los requisitos configurados.", "fr_FR": "Signale une disposition des pistes qui ne correspond pas aux exigences configurées.", "it_IT": "Segnala una disposizione delle tracce che non corrisponde ai requisiti configurati.", "ja_JP": "設定された要件と一致しないトラック構成を報告します。", "ko_KR": "설정된 요구 사항과 맞지 않는 트랙 구성을 보고합니다.", "pt_BR": "Relata uma disposição de trilhas que não corresponde aos requisitos configurados.", "ru_RU": "Сообщает о структуре дорожек, не соответствующей заданным требованиям.", "zh_CN": "报告与已配置要求不符的轨道布局。" }, "category": "project", "scope": "required-tracks", "severity": "warning", "options": { "minVideoTracks": { "type": "number", "default": 0, "description": "Minimum number of video tracks. 0: not checked." }, "minAudioTracks": { "type": "number", "default": 0, "description": "Minimum number of audio tracks. 0: not checked." }, "videoTrackNames": { "type": "string[]", "default": [], "description": "Names that must exist among video tracks." }, "audioTrackNames": { "type": "string[]", "default": [], "description": "Names that must exist among audio tracks." }, "tracks": { "type": "json", "default": [], "description": "Per-position requirements: { \"ref\": \"V1\", \"name\"?, \"nonEmpty\"? }." } }, "checks": [ { "condition": { "field": "violation.kind", "operator": "equals", "value": "minVideo" }, "message": { "en_US": { "count": "violation.count", "one": "Sequence has {violation.count} video track (at least {violation.min} required).", "other": "Sequence has {violation.count} video tracks (at least {violation.min} required)." }, "de_DE": { "count": "violation.count", "one": "Die Sequenz hat {violation.count} Videospur (mindestens {violation.min} erforderlich).", "other": "Die Sequenz hat {violation.count} Videospuren (mindestens {violation.min} erforderlich)." }, "es_ES": { "count": "violation.count", "one": "La secuencia tiene {violation.count} pista de vídeo (mínimo obligatorio: {violation.min}).", "other": "La secuencia tiene {violation.count} pistas de vídeo (mínimo obligatorio: {violation.min})." }, "fr_FR": { "count": "violation.count", "one": "La séquence comporte {violation.count} piste vidéo (minimum requis : {violation.min}).", "other": "La séquence comporte {violation.count} pistes vidéo (minimum requis : {violation.min})." }, "it_IT": { "count": "violation.count", "one": "La sequenza ha {violation.count} traccia video (almeno {violation.min} richieste).", "other": "La sequenza ha {violation.count} tracce video (almeno {violation.min} richieste)." }, "ja_JP": "シーケンスのビデオトラックは{violation.count}個です({violation.min}個以上必要)。", "ko_KR": "시퀀스의 비디오 트랙이 {violation.count}개입니다(최소 {violation.min}개 필요).", "pt_BR": { "count": "violation.count", "one": "A sequência tem {violation.count} trilha de vídeo (mínimo exigido: {violation.min}).", "other": "A sequência tem {violation.count} trilhas de vídeo (mínimo exigido: {violation.min})." }, "ru_RU": { "count": "violation.count", "one": "В эпизоде {violation.count} видеодорожка (требуется не менее {violation.min}).", "few": "В эпизоде {violation.count} видеодорожки (требуется не менее {violation.min}).", "many": "В эпизоде {violation.count} видеодорожек (требуется не менее {violation.min}).", "other": "В эпизоде {violation.count} видеодорожки (требуется не менее {violation.min})." }, "zh_CN": "序列有 {violation.count} 个视频轨道(至少需要 {violation.min} 个)。" } }, { "condition": { "field": "violation.kind", "operator": "equals", "value": "minAudio" }, "message": { "en_US": { "count": "violation.count", "one": "Sequence has {violation.count} audio track (at least {violation.min} required).", "other": "Sequence has {violation.count} audio tracks (at least {violation.min} required)." }, "de_DE": { "count": "violation.count", "one": "Die Sequenz hat {violation.count} Audiospur (mindestens {violation.min} erforderlich).", "other": "Die Sequenz hat {violation.count} Audiospuren (mindestens {violation.min} erforderlich)." }, "es_ES": { "count": "violation.count", "one": "La secuencia tiene {violation.count} pista de audio (mínimo obligatorio: {violation.min}).", "other": "La secuencia tiene {violation.count} pistas de audio (mínimo obligatorio: {violation.min})." }, "fr_FR": { "count": "violation.count", "one": "La séquence comporte {violation.count} piste audio (minimum requis : {violation.min}).", "other": "La séquence comporte {violation.count} pistes audio (minimum requis : {violation.min})." }, "it_IT": { "count": "violation.count", "one": "La sequenza ha {violation.count} traccia audio (almeno {violation.min} richieste).", "other": "La sequenza ha {violation.count} tracce audio (almeno {violation.min} richieste)." }, "ja_JP": "シーケンスのオーディオトラックは{violation.count}個です({violation.min}個以上必要)。", "ko_KR": "시퀀스의 오디오 트랙이 {violation.count}개입니다(최소 {violation.min}개 필요).", "pt_BR": { "count": "violation.count", "one": "A sequência tem {violation.count} trilha de áudio (mínimo exigido: {violation.min}).", "other": "A sequência tem {violation.count} trilhas de áudio (mínimo exigido: {violation.min})." }, "ru_RU": { "count": "violation.count", "one": "В эпизоде {violation.count} аудиодорожка (требуется не менее {violation.min}).", "few": "В эпизоде {violation.count} аудиодорожки (требуется не менее {violation.min}).", "many": "В эпизоде {violation.count} аудиодорожек (требуется не менее {violation.min}).", "other": "В эпизоде {violation.count} аудиодорожки (требуется не менее {violation.min})." }, "zh_CN": "序列有 {violation.count} 个音频轨道(至少需要 {violation.min} 个)。" } }, { "condition": { "field": "violation.kind", "operator": "equals", "value": "missingVideoName" }, "message": { "en_US": "No video track named \"{violation.name}\".", "de_DE": "Keine Videospur namens „{violation.name}“.", "es_ES": "No hay ninguna pista de vídeo con el nombre \"{violation.name}\".", "fr_FR": "Aucune piste vidéo nommée « {violation.name} ».", "it_IT": "Nessuna traccia video denominata \"{violation.name}\".", "ja_JP": "「{violation.name}」という名前のビデオトラックがありません。", "ko_KR": "이름이 \"{violation.name}\"인 비디오 트랙이 없습니다.", "pt_BR": "Nenhuma trilha de vídeo com o nome \"{violation.name}\".", "ru_RU": "Нет видеодорожки с именем «{violation.name}».", "zh_CN": "没有名为“{violation.name}”的视频轨道。" } }, { "condition": { "field": "violation.kind", "operator": "equals", "value": "missingAudioName" }, "message": { "en_US": "No audio track named \"{violation.name}\".", "de_DE": "Keine Audiospur namens „{violation.name}“.", "es_ES": "No hay ninguna pista de audio con el nombre \"{violation.name}\".", "fr_FR": "Aucune piste audio nommée « {violation.name} ».", "it_IT": "Nessuna traccia audio denominata \"{violation.name}\".", "ja_JP": "「{violation.name}」という名前のオーディオトラックがありません。", "ko_KR": "이름이 \"{violation.name}\"인 오디오 트랙이 없습니다.", "pt_BR": "Nenhuma trilha de áudio com o nome \"{violation.name}\".", "ru_RU": "Нет аудиодорожки с именем «{violation.name}».", "zh_CN": "没有名为“{violation.name}”的音频轨道。" } }, { "condition": { "field": "violation.kind", "operator": "equals", "value": "missingTrack" }, "message": { "en_US": "Track {violation.trackRef} is required and does not exist.", "de_DE": "Spur {violation.trackRef} ist erforderlich, existiert aber nicht.", "es_ES": "La pista {violation.trackRef} es obligatoria y no existe.", "fr_FR": "La piste {violation.trackRef} est requise mais n'existe pas.", "it_IT": "La traccia {violation.trackRef} è obbligatoria e non esiste.", "ja_JP": "トラック {violation.trackRef} は必須ですが、存在しません。", "ko_KR": "트랙 {violation.trackRef}이(가) 필요하지만 존재하지 않습니다.", "pt_BR": "A trilha {violation.trackRef} é obrigatória e não existe.", "ru_RU": "Дорожка {violation.trackRef} обязательна, но отсутствует.", "zh_CN": "轨道 {violation.trackRef} 为必需轨道,但不存在。" } }, { "condition": { "field": "violation.kind", "operator": "equals", "value": "wrongName" }, "message": { "en_US": "Track {violation.trackRef} is named \"{violation.name}\", expected \"{violation.expected}\".", "de_DE": "Spur {violation.trackRef} heißt „{violation.name}“, erwartet: „{violation.expected}“.", "es_ES": "La pista {violation.trackRef} se llama \"{violation.name}\"; se esperaba \"{violation.expected}\".", "fr_FR": "La piste {violation.trackRef} est nommée « {violation.name} » au lieu de « {violation.expected} ».", "it_IT": "La traccia {violation.trackRef} è denominata \"{violation.name}\", previsto \"{violation.expected}\".", "ja_JP": "トラック {violation.trackRef} の名前は「{violation.name}」ですが、「{violation.expected}」である必要があります。", "ko_KR": "트랙 {violation.trackRef}의 이름이 \"{violation.name}\"입니다. 필요한 이름: \"{violation.expected}\".", "pt_BR": "A trilha {violation.trackRef} tem o nome \"{violation.name}\", esperado \"{violation.expected}\".", "ru_RU": "Дорожка {violation.trackRef} называется «{violation.name}», ожидалось «{violation.expected}».", "zh_CN": "轨道 {violation.trackRef} 名为“{violation.name}”,应为“{violation.expected}”。" } }, { "condition": { "field": "violation.kind", "operator": "equals", "value": "empty" }, "message": { "en_US": "Track {violation.trackRef} (\"{violation.trackName}\") is required to carry clips and is empty.", "de_DE": "Spur {violation.trackRef} („{violation.trackName}“) muss Clips enthalten, ist aber leer.", "es_ES": "Pista {violation.trackRef} (\"{violation.trackName}\") debe contener clips y está vacía.", "fr_FR": "Piste {violation.trackRef} (« {violation.trackName} ») doit contenir des éléments mais est vide.", "it_IT": "Traccia {violation.trackRef} (\"{violation.trackName}\") deve contenere clip ed è vuota.", "ja_JP": "トラック {violation.trackRef}(「{violation.trackName}」)にはクリップが必要ですが、空です。", "ko_KR": "트랙 {violation.trackRef}(\"{violation.trackName}\")에는 클립이 있어야 하지만 비어 있습니다.", "pt_BR": "Trilha {violation.trackRef} (\"{violation.trackName}\") deve conter clipes e está vazia.", "ru_RU": "Дорожка {violation.trackRef} («{violation.trackName}») должна содержать клипы, но пуста.", "zh_CN": "轨道 {violation.trackRef}(“{violation.trackName}”) 必须包含剪辑,但为空。" } } ], "data": { "requirement": "violation.requirement", "found": "violation.found" } } ``` # Scale outliers (/docs/rules/scale-outlier) Reports video clips whose scale is unusual compared with other clips. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :---------------------------------------------------------------------------------- | | Id | `scale-outlier` | | Category | Local consistency | | Default severity | info | | Scope | [`scale-outliers`](/docs/reference/computed-scopes#scale-outliers) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :-------------------- | :------- | :-------- | :------------------------------------------------------------------------------------------------------------------ | | `maxDeviationPercent` | `number` | `10` | Report clips whose scale differs from the median by more than this percentage of the median. Equal is not reported. | | `minClips` | `number` | `4` | Populations smaller than this are insufficient data and are not analysed. | | `scope` | `string` | `"track"` | "track" compares clips with the other clips on the same track; "sequence" with every eligible clip of the sequence. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `scale-outlier.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="scale-outlier.rule.json" { "formatVersion": 1, "id": "scale-outlier", "name": { "en_US": "Scale outliers", "de_DE": "Abweichende Skalierung", "es_ES": "Escalas atípicas", "fr_FR": "Échelles atypiques", "it_IT": "Scale anomale", "ja_JP": "スケールの外れ値", "ko_KR": "비율 이상값", "pt_BR": "Escalas atípicas", "ru_RU": "Нетипичный масштаб", "zh_CN": "缩放异常" }, "description": { "en_US": "Reports video clips whose scale is unusual compared with other clips.", "de_DE": "Meldet Videoclips, deren Skalierung im Vergleich zu anderen Clips ungewöhnlich ist.", "es_ES": "Detecta clips de vídeo cuya escala es inusual en comparación con otros clips.", "fr_FR": "Signale les éléments vidéo dont l'échelle est inhabituelle par rapport aux autres éléments.", "it_IT": "Segnala le clip video con una scala insolita rispetto alle altre clip.", "ja_JP": "スケールが他のクリップと比べて極端なビデオクリップを報告します。", "ko_KR": "비율이 다른 클립과 비교해 이례적인 비디오 클립을 보고합니다.", "pt_BR": "Relata clipes de vídeo cuja escala é incomum em relação aos outros clipes.", "ru_RU": "Сообщает о видеоклипах с масштабом, нетипичным по сравнению с другими клипами.", "zh_CN": "报告缩放与其他剪辑相比异常的视频剪辑。" }, "category": "local-consistency", "scope": "scale-outliers", "severity": "info", "options": { "maxDeviationPercent": { "type": "number", "default": 10, "description": "Report clips whose scale differs from the median by more than this percentage of the median. Equal is not reported." }, "minClips": { "type": "number", "default": 4, "description": "Populations smaller than this are insufficient data and are not analysed." }, "scope": { "type": "string", "default": "track", "description": "\"track\" compares clips with the other clips on the same track; \"sequence\" with every eligible clip of the sequence." } }, "checks": [ { "condition": { "field": "outlier.deviationPercent", "operator": "greaterThan", "value": { "field": "options.maxDeviationPercent" } }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is scaled to {outlier.value} %, {outlier.absDeviationPercent} % larger than the median ({outlier.median} %) of {labels.population}.", "de_DE": "Clip „{clip.name}“ auf {clip.track} ist auf {outlier.value} % skaliert, {outlier.absDeviationPercent} % größer als der Median ({outlier.median} %) von {labels.population}.", "es_ES": "Clip \"{clip.name}\" en {clip.track} tiene una escala del {outlier.value} %, un {outlier.absDeviationPercent} % mayor que la mediana ({outlier.median} %) de {labels.population}.", "fr_FR": "Élément « {clip.name} » sur {clip.track} est mis à l'échelle à {outlier.value} %, soit {outlier.absDeviationPercent} % de plus que la médiane ({outlier.median} %) de {labels.population}.", "it_IT": "Clip \"{clip.name}\" su {clip.track} è in scala al {outlier.value} %, {outlier.absDeviationPercent} % più grande della mediana ({outlier.median} %) di {labels.population}.", "ja_JP": "クリップ「{clip.name}」({clip.track})のスケールは{outlier.value} %で、{labels.population}の中央値({outlier.median} %)より{outlier.absDeviationPercent} %大きくなっています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 비율({outlier.value} %)이 {labels.population}의 중앙값({outlier.median} %)보다 {outlier.absDeviationPercent} % 큽니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está com escala de {outlier.value} %, {outlier.absDeviationPercent} % maior que a mediana ({outlier.median} %) de {labels.population}.", "ru_RU": "Клип «{clip.name}» на {clip.track}: масштаб {outlier.value} %, на {outlier.absDeviationPercent} % больше медианы ({outlier.median} %) для {labels.population}.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 缩放为 {outlier.value} %,比{labels.population}的中位数({outlier.median} %)大 {outlier.absDeviationPercent} %。" } }, { "condition": { "all": [ { "field": "outlier.absDeviationPercent", "operator": "greaterThan", "value": { "field": "options.maxDeviationPercent" } }, { "field": "outlier.deviationPercent", "operator": "lessThan", "value": 0 } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is scaled to {outlier.value} %, {outlier.absDeviationPercent} % smaller than the median ({outlier.median} %) of {labels.population}.", "de_DE": "Clip „{clip.name}“ auf {clip.track} ist auf {outlier.value} % skaliert, {outlier.absDeviationPercent} % kleiner als der Median ({outlier.median} %) von {labels.population}.", "es_ES": "Clip \"{clip.name}\" en {clip.track} tiene una escala del {outlier.value} %, un {outlier.absDeviationPercent} % menor que la mediana ({outlier.median} %) de {labels.population}.", "fr_FR": "Élément « {clip.name} » sur {clip.track} est mis à l'échelle à {outlier.value} %, soit {outlier.absDeviationPercent} % de moins que la médiane ({outlier.median} %) de {labels.population}.", "it_IT": "Clip \"{clip.name}\" su {clip.track} è in scala al {outlier.value} %, {outlier.absDeviationPercent} % più piccola della mediana ({outlier.median} %) di {labels.population}.", "ja_JP": "クリップ「{clip.name}」({clip.track})のスケールは{outlier.value} %で、{labels.population}の中央値({outlier.median} %)より{outlier.absDeviationPercent} %小さくなっています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 비율({outlier.value} %)이 {labels.population}의 중앙값({outlier.median} %)보다 {outlier.absDeviationPercent} % 작습니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está com escala de {outlier.value} %, {outlier.absDeviationPercent} % menor que a mediana ({outlier.median} %) de {labels.population}.", "ru_RU": "Клип «{clip.name}» на {clip.track}: масштаб {outlier.value} %, на {outlier.absDeviationPercent} % меньше медианы ({outlier.median} %) для {labels.population}.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 缩放为 {outlier.value} %,比{labels.population}的中位数({outlier.median} %)小 {outlier.absDeviationPercent} %。" } } ], "labels": { "population": { "field": "outlier.populationIsTrack", "values": { "true": { "en_US": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip on {outlier.populationKey}", "other": "{outlier.populationSize} clips on {outlier.populationKey}" }, "de_DE": { "count": "outlier.populationSize", "one": "{outlier.populationSize} Clip auf {outlier.populationKey}", "other": "{outlier.populationSize} Clips auf {outlier.populationKey}" }, "es_ES": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip en {outlier.populationKey}", "other": "los {outlier.populationSize} clips en {outlier.populationKey}" }, "fr_FR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} élément sur {outlier.populationKey}", "other": "{outlier.populationSize} éléments sur {outlier.populationKey}" }, "it_IT": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip su {outlier.populationKey}", "other": "{outlier.populationSize} clip su {outlier.populationKey}" }, "ja_JP": "{outlier.populationKey}の{outlier.populationSize}個のクリップ", "ko_KR": "{outlier.populationKey}의 클립 {outlier.populationSize}개", "pt_BR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clipe em {outlier.populationKey}", "other": "{outlier.populationSize} clipes em {outlier.populationKey}" }, "ru_RU": { "count": "outlier.populationSize", "one": "{outlier.populationSize} клипа на {outlier.populationKey}", "few": "{outlier.populationSize} клипов на {outlier.populationKey}", "many": "{outlier.populationSize} клипов на {outlier.populationKey}", "other": "{outlier.populationSize} клипа на {outlier.populationKey}" }, "zh_CN": "{outlier.populationKey} 上的 {outlier.populationSize} 个剪辑" }, "false": { "en_US": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip in the sequence", "other": "{outlier.populationSize} clips in the sequence" }, "de_DE": { "count": "outlier.populationSize", "one": "{outlier.populationSize} Clip in der Sequenz", "other": "{outlier.populationSize} Clips in der Sequenz" }, "es_ES": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip de la secuencia", "other": "los {outlier.populationSize} clips de la secuencia" }, "fr_FR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} élément de la séquence", "other": "{outlier.populationSize} éléments de la séquence" }, "it_IT": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip nella sequenza", "other": "{outlier.populationSize} clip nella sequenza" }, "ja_JP": "シーケンス内の{outlier.populationSize}個のクリップ", "ko_KR": "시퀀스의 클립 {outlier.populationSize}개", "pt_BR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clipe na sequência", "other": "{outlier.populationSize} clipes na sequência" }, "ru_RU": { "count": "outlier.populationSize", "one": "{outlier.populationSize} клипа в эпизоде", "few": "{outlier.populationSize} клипов в эпизоде", "many": "{outlier.populationSize} клипов в эпизоде", "other": "{outlier.populationSize} клипа в эпизоде" }, "zh_CN": "序列中的 {outlier.populationSize} 个剪辑" } } } }, "data": { "scalePercent": "outlier.value", "medianPercent": "outlier.median", "deviationPercent": "outlier.deviationPercent", "maxDeviationPercent": "options.maxDeviationPercent", "population": "outlier.populationKey", "populationSize": "outlier.populationSize" } } ``` # Scale range (/docs/rules/scale-range) Reports video clips scaled outside the allowed range. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :------------ | | Id | `scale-range` | | Category | Static | | Default severity | info | | Scope | `clip` | ## Options [#options] | Option | Type | Default | Description | | :----- | :------- | :------ | :--------------------------------------------------- | | `min` | `number` | `25` | Lowest allowed scale, in percent. Equal is allowed. | | `max` | `number` | `200` | Highest allowed scale, in percent. Equal is allowed. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `scale-range.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="scale-range.rule.json" { "formatVersion": 1, "id": "scale-range", "name": { "en_US": "Scale range", "de_DE": "Skalierungsbereich", "es_ES": "Intervalo de escala", "fr_FR": "Plage d'échelle", "it_IT": "Intervallo di scala", "ja_JP": "スケールの範囲", "ko_KR": "비율 범위", "pt_BR": "Intervalo de escala", "ru_RU": "Диапазон масштаба", "zh_CN": "缩放范围" }, "description": { "en_US": "Reports video clips scaled outside the allowed range.", "de_DE": "Meldet Videoclips, deren Skalierung außerhalb des zulässigen Bereichs liegt.", "es_ES": "Detecta clips de vídeo con una escala fuera del intervalo permitido.", "fr_FR": "Signale les éléments vidéo dont l'échelle est hors de la plage autorisée.", "it_IT": "Segnala le clip video con una scala fuori dall'intervallo consentito.", "ja_JP": "スケールが許容範囲外のビデオクリップを報告します。", "ko_KR": "비율이 허용 범위를 벗어난 비디오 클립을 보고합니다.", "pt_BR": "Relata clipes de vídeo cuja escala está fora do intervalo permitido.", "ru_RU": "Сообщает о видеоклипах, масштаб которых вне допустимого диапазона.", "zh_CN": "报告缩放超出允许范围的视频剪辑。" }, "category": "static", "scope": "clip", "severity": "info", "options": { "min": { "type": "number", "default": 25, "description": "Lowest allowed scale, in percent. Equal is allowed." }, "max": { "type": "number", "default": 200, "description": "Highest allowed scale, in percent. Equal is allowed." } }, "checks": [ { "condition": { "all": [ { "field": "clip.disabled", "operator": "equals", "value": false }, { "field": "clip.adjustmentLayer", "operator": "equals", "value": false }, { "field": "clip.scaleAnimated", "operator": "equals", "value": false }, { "any": [ { "field": "clip.scale", "operator": "lessThan", "value": { "field": "options.min" } }, { "field": "clip.scale", "operator": "greaterThan", "value": { "field": "options.max" } } ] } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} is scaled to {clip.scale} %, outside the allowed range ({options.min}–{options.max} %).", "de_DE": "Clip „{clip.name}“ auf {clip.track} ist auf {clip.scale} % skaliert, außerhalb des zulässigen Bereichs ({options.min}–{options.max} %).", "es_ES": "Clip \"{clip.name}\" en {clip.track} está escalado al {clip.scale} %, fuera del intervalo permitido ({options.min}–{options.max} %).", "fr_FR": "Élément « {clip.name} » sur {clip.track} est mis à l'échelle à {clip.scale} %, hors de la plage autorisée ({options.min}–{options.max} %).", "it_IT": "Clip \"{clip.name}\" su {clip.track} è scalata al {clip.scale} %, fuori dall'intervallo consentito ({options.min}–{options.max} %).", "ja_JP": "クリップ「{clip.name}」({clip.track})のスケールは{clip.scale} %で、許容範囲({options.min}~{options.max} %)外です。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 비율이 {clip.scale} %로, 허용 범위({options.min}~{options.max} %)를 벗어났습니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} está com escala de {clip.scale} %, fora do intervalo permitido ({options.min}–{options.max} %).", "ru_RU": "Клип «{clip.name}» на {clip.track} масштабирован до {clip.scale} %, вне допустимого диапазона ({options.min}–{options.max} %).", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 的缩放为 {clip.scale} %,超出允许范围({options.min}–{options.max} %)。" } } ], "data": { "scalePercent": "clip.scale", "min": "options.min", "max": "options.max" } } ``` # Sequence settings (/docs/rules/sequence-settings) Reports a sequence whose frame rate or frame size is not an allowed one. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :---------------------------------------------------------------------------------------- | | Id | `sequence-settings` | | Category | Project | | Default severity | warning | | Scope | [`sequence-settings`](/docs/reference/computed-scopes#sequence-settings) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :----------- | :--------- | :------------------------------------------------------ | :---------------------------------------------------------------------------------------- | | `frameRates` | `number[]` | `[23.976,24,25,29.97,30,48,50,59.94,60,100,119.88,120]` | Allowed frame rates. 23.976, 29.97… stand for 24000/1001, 30000/1001… Empty: not checked. | | `frameSizes` | `json` | `[]` | Allowed frame sizes: \{ "width", "height" }. Empty: not checked. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `sequence-settings.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="sequence-settings.rule.json" { "formatVersion": 1, "id": "sequence-settings", "name": { "en_US": "Sequence settings", "de_DE": "Sequenzeinstellungen", "es_ES": "Ajustes de secuencia", "fr_FR": "Paramètres de séquence", "it_IT": "Impostazioni sequenza", "ja_JP": "シーケンス設定", "ko_KR": "시퀀스 설정", "pt_BR": "Configurações da sequência", "ru_RU": "Настройки эпизода", "zh_CN": "序列设置" }, "description": { "en_US": "Reports a sequence whose frame rate or frame size is not an allowed one.", "de_DE": "Meldet eine Sequenz, deren Framerate oder Framegröße nicht zulässig ist.", "es_ES": "Detecta una secuencia cuya velocidad de fotogramas o tamaño de fotograma no está permitido.", "fr_FR": "Signale une séquence dont la fréquence d'images ou la taille d'image n'est pas autorisée.", "it_IT": "Segnala una sequenza con frequenza fotogrammi o dimensione fotogramma non consentite.", "ja_JP": "フレームレートまたはフレームサイズが許可されていないシーケンスを報告します。", "ko_KR": "프레임 속도 또는 프레임 크기가 허용되지 않는 시퀀스를 보고합니다.", "pt_BR": "Relata uma sequência cuja taxa de quadros ou tamanho de quadro não é permitido.", "ru_RU": "Сообщает об эпизоде с недопустимой частотой кадров или размером кадра.", "zh_CN": "报告帧速率或帧大小不在允许范围内的序列。" }, "category": "project", "scope": "sequence-settings", "severity": "warning", "options": { "frameRates": { "type": "number[]", "default": [ 23.976, 24, 25, 29.97, 30, 48, 50, 59.94, 60, 100, 119.88, 120 ], "description": "Allowed frame rates. 23.976, 29.97… stand for 24000/1001, 30000/1001… Empty: not checked." }, "frameSizes": { "type": "json", "default": [], "description": "Allowed frame sizes: { \"width\", \"height\" }. Empty: not checked." } }, "checks": [ { "condition": { "field": "setting.kind", "operator": "equals", "value": "frameRate" }, "message": { "en_US": "Sequence \"{sequence.name}\" runs at {setting.frameRate:3} fps, which is not an allowed frame rate.", "de_DE": "Sequenz „{sequence.name}“ läuft mit {setting.frameRate:3} fps, was keine zulässige Framerate ist.", "es_ES": "La secuencia \"{sequence.name}\" usa {setting.frameRate:3} fps, que no es una velocidad de fotogramas permitida.", "fr_FR": "La séquence « {sequence.name} » est à {setting.frameRate:3} fps, une fréquence d'images non autorisée.", "it_IT": "La sequenza \"{sequence.name}\" è a {setting.frameRate:3} fps, una frequenza fotogrammi non consentita.", "ja_JP": "シーケンス「{sequence.name}」のフレームレートは{setting.frameRate:3} fpsで、許可されたフレームレートではありません。", "ko_KR": "시퀀스 \"{sequence.name}\"의 프레임 속도 {setting.frameRate:3} fps는 허용되지 않는 프레임 속도입니다.", "pt_BR": "A sequência \"{sequence.name}\" está a {setting.frameRate:3} fps, que não é uma taxa de quadros permitida.", "ru_RU": "Частота кадров эпизода «{sequence.name}» ({setting.frameRate:3} fps) не входит в число допустимых.", "zh_CN": "序列“{sequence.name}”的帧速率为 {setting.frameRate:3} fps,不是允许的帧速率。" }, "data": { "frameRate": "setting.frameRate", "frameDuration": "sequence.frameDuration", "frameRates": "setting.frameRates" } }, { "condition": { "field": "setting.kind", "operator": "equals", "value": "frameSize" }, "message": { "en_US": "Sequence \"{sequence.name}\" is {setting.frameSizeText}, not one of the allowed frame sizes ({setting.frameSizesText}).", "de_DE": "Sequenz „{sequence.name}“ hat die Größe {setting.frameSizeText}, keine der zulässigen Framegrößen ({setting.frameSizesText}).", "es_ES": "La secuencia \"{sequence.name}\" tiene un tamaño de {setting.frameSizeText}, que no es uno de los tamaños de fotograma permitidos ({setting.frameSizesText}).", "fr_FR": "La séquence « {sequence.name} » est en {setting.frameSizeText}, qui ne fait pas partie des tailles d'image autorisées ({setting.frameSizesText}).", "it_IT": "La sequenza \"{sequence.name}\" è {setting.frameSizeText}, non una delle dimensioni fotogramma consentite ({setting.frameSizesText}).", "ja_JP": "シーケンス「{sequence.name}」のフレームサイズは{setting.frameSizeText}で、許可されたフレームサイズ({setting.frameSizesText})ではありません。", "ko_KR": "시퀀스 \"{sequence.name}\"의 프레임 크기 {setting.frameSizeText}은(는) 허용된 프레임 크기({setting.frameSizesText})가 아닙니다.", "pt_BR": "A sequência \"{sequence.name}\" tem {setting.frameSizeText}, que não é um dos tamanhos de quadro permitidos ({setting.frameSizesText}).", "ru_RU": "Размер кадра эпизода «{sequence.name}» ({setting.frameSizeText}) не входит в число допустимых ({setting.frameSizesText}).", "zh_CN": "序列“{sequence.name}”的帧大小为 {setting.frameSizeText},不在允许的帧大小({setting.frameSizesText})之内。" }, "data": { "frameSize": "setting.frameSize", "frameSizes": "setting.frameSizes" } } ], "matching": "all" } ``` # Speed outliers (/docs/rules/speed-outlier) Reports clips whose speed is unusual compared with other clips. {/* Generated by scripts/generate-docs.ts. Do not edit. */} | Property | Value | | :--------------- | :---------------------------------------------------------------------------------- | | Id | `speed-outlier` | | Category | Local consistency | | Default severity | info | | Scope | [`speed-outliers`](/docs/reference/computed-scopes#speed-outliers) (computed scope) | ## Options [#options] | Option | Type | Default | Description | | :-------------------- | :------- | :-------- | :------------------------------------------------------------------------------------------------------------------ | | `maxDeviationPercent` | `number` | `5` | Report clips whose speed differs from the median by more than this percentage of the median. Equal is not reported. | | `minClips` | `number` | `4` | Populations smaller than this are insufficient data and are not analysed. | | `scope` | `string` | `"track"` | "track" compares clips with the other clips on the same track; "sequence" with every eligible clip of the sequence. | ## Customize it [#customize-it] Turn the rule on or off in the panel's Rules settings. To change its options, severity or wording, open it with its cogwheel in the rule editor and save: your copy replaces the built-in rule until you revert it. You can also copy the file below into your rules folder as `speed-outlier.rule.json` and edit it. See [Change a built-in rule](/docs/editor/saving#change-a-built-in-rule). ## Rule file [#rule-file] ```json title="speed-outlier.rule.json" { "formatVersion": 1, "id": "speed-outlier", "name": { "en_US": "Speed outliers", "de_DE": "Abweichende Geschwindigkeit", "es_ES": "Velocidades atípicas", "fr_FR": "Vitesses atypiques", "it_IT": "Velocità anomale", "ja_JP": "速度の外れ値", "ko_KR": "속도 이상값", "pt_BR": "Velocidades atípicas", "ru_RU": "Нетипичная скорость", "zh_CN": "速度异常" }, "description": { "en_US": "Reports clips whose speed is unusual compared with other clips.", "de_DE": "Meldet Clips, deren Geschwindigkeit im Vergleich zu anderen Clips ungewöhnlich ist.", "es_ES": "Detecta clips cuya velocidad es inusual en comparación con otros clips.", "fr_FR": "Signale les éléments dont la vitesse est inhabituelle par rapport aux autres éléments.", "it_IT": "Segnala le clip con una velocità insolita rispetto alle altre clip.", "ja_JP": "速度が他のクリップと比べて極端なクリップを報告します。", "ko_KR": "속도가 다른 클립과 비교해 이례적인 클립을 보고합니다.", "pt_BR": "Relata clipes cuja velocidade é incomum em relação aos outros clipes.", "ru_RU": "Сообщает о клипах со скоростью, нетипичной по сравнению с другими клипами.", "zh_CN": "报告速度与其他剪辑相比异常的剪辑。" }, "category": "local-consistency", "scope": "speed-outliers", "severity": "info", "options": { "maxDeviationPercent": { "type": "number", "default": 5, "description": "Report clips whose speed differs from the median by more than this percentage of the median. Equal is not reported." }, "minClips": { "type": "number", "default": 4, "description": "Populations smaller than this are insufficient data and are not analysed." }, "scope": { "type": "string", "default": "track", "description": "\"track\" compares clips with the other clips on the same track; \"sequence\" with every eligible clip of the sequence." } }, "checks": [ { "condition": { "field": "outlier.deviationPercent", "operator": "greaterThan", "value": { "field": "options.maxDeviationPercent" } }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} plays {outlier.absDeviationPercent} % faster than the median speed of {labels.population}.", "de_DE": "Clip „{clip.name}“ auf {clip.track} wird {outlier.absDeviationPercent} % schneller abgespielt als der Median der Geschwindigkeit von {labels.population}.", "es_ES": "Clip \"{clip.name}\" en {clip.track} se reproduce un {outlier.absDeviationPercent} % más rápido que la velocidad mediana de {labels.population}.", "fr_FR": "Élément « {clip.name} » sur {clip.track} est lu {outlier.absDeviationPercent} % plus vite que la vitesse médiane de {labels.population}.", "it_IT": "Clip \"{clip.name}\" su {clip.track} viene riprodotta {outlier.absDeviationPercent} % più veloce della velocità mediana di {labels.population}.", "ja_JP": "クリップ「{clip.name}」({clip.track})の再生速度は、{labels.population}の中央値より{outlier.absDeviationPercent} %速くなっています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 재생 속도가 {labels.population}의 중앙값 속도보다 {outlier.absDeviationPercent} % 빠릅니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} é reproduzido {outlier.absDeviationPercent} % mais rápido que a velocidade mediana de {labels.population}.", "ru_RU": "Клип «{clip.name}» на {clip.track} воспроизводится на {outlier.absDeviationPercent} % быстрее медианной скорости для {labels.population}.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 的播放速度比{labels.population}的中位速度快 {outlier.absDeviationPercent} %。" } }, { "condition": { "all": [ { "field": "outlier.absDeviationPercent", "operator": "greaterThan", "value": { "field": "options.maxDeviationPercent" } }, { "field": "outlier.deviationPercent", "operator": "lessThan", "value": 0 } ] }, "message": { "en_US": "Clip \"{clip.name}\" on {clip.track} plays {outlier.absDeviationPercent} % slower than the median speed of {labels.population}.", "de_DE": "Clip „{clip.name}“ auf {clip.track} wird {outlier.absDeviationPercent} % langsamer abgespielt als der Median der Geschwindigkeit von {labels.population}.", "es_ES": "Clip \"{clip.name}\" en {clip.track} se reproduce un {outlier.absDeviationPercent} % más lento que la velocidad mediana de {labels.population}.", "fr_FR": "Élément « {clip.name} » sur {clip.track} est lu {outlier.absDeviationPercent} % plus lentement que la vitesse médiane de {labels.population}.", "it_IT": "Clip \"{clip.name}\" su {clip.track} viene riprodotta {outlier.absDeviationPercent} % più lenta della velocità mediana di {labels.population}.", "ja_JP": "クリップ「{clip.name}」({clip.track})の再生速度は、{labels.population}の中央値より{outlier.absDeviationPercent} %遅くなっています。", "ko_KR": "{clip.track}의 클립 \"{clip.name}\"의 재생 속도가 {labels.population}의 중앙값 속도보다 {outlier.absDeviationPercent} % 느립니다.", "pt_BR": "Clipe \"{clip.name}\" em {clip.track} é reproduzido {outlier.absDeviationPercent} % mais devagar que a velocidade mediana de {labels.population}.", "ru_RU": "Клип «{clip.name}» на {clip.track} воспроизводится на {outlier.absDeviationPercent} % медленнее медианной скорости для {labels.population}.", "zh_CN": "{clip.track} 上的剪辑“{clip.name}” 的播放速度比{labels.population}的中位速度慢 {outlier.absDeviationPercent} %。" } } ], "labels": { "population": { "field": "outlier.populationIsTrack", "values": { "true": { "en_US": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip on {outlier.populationKey}", "other": "{outlier.populationSize} clips on {outlier.populationKey}" }, "de_DE": { "count": "outlier.populationSize", "one": "{outlier.populationSize} Clip auf {outlier.populationKey}", "other": "{outlier.populationSize} Clips auf {outlier.populationKey}" }, "es_ES": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip en {outlier.populationKey}", "other": "los {outlier.populationSize} clips en {outlier.populationKey}" }, "fr_FR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} élément sur {outlier.populationKey}", "other": "{outlier.populationSize} éléments sur {outlier.populationKey}" }, "it_IT": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip su {outlier.populationKey}", "other": "{outlier.populationSize} clip su {outlier.populationKey}" }, "ja_JP": "{outlier.populationKey}の{outlier.populationSize}個のクリップ", "ko_KR": "{outlier.populationKey}의 클립 {outlier.populationSize}개", "pt_BR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clipe em {outlier.populationKey}", "other": "{outlier.populationSize} clipes em {outlier.populationKey}" }, "ru_RU": { "count": "outlier.populationSize", "one": "{outlier.populationSize} клипа на {outlier.populationKey}", "few": "{outlier.populationSize} клипов на {outlier.populationKey}", "many": "{outlier.populationSize} клипов на {outlier.populationKey}", "other": "{outlier.populationSize} клипа на {outlier.populationKey}" }, "zh_CN": "{outlier.populationKey} 上的 {outlier.populationSize} 个剪辑" }, "false": { "en_US": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip in the sequence", "other": "{outlier.populationSize} clips in the sequence" }, "de_DE": { "count": "outlier.populationSize", "one": "{outlier.populationSize} Clip in der Sequenz", "other": "{outlier.populationSize} Clips in der Sequenz" }, "es_ES": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip de la secuencia", "other": "los {outlier.populationSize} clips de la secuencia" }, "fr_FR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} élément de la séquence", "other": "{outlier.populationSize} éléments de la séquence" }, "it_IT": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clip nella sequenza", "other": "{outlier.populationSize} clip nella sequenza" }, "ja_JP": "シーケンス内の{outlier.populationSize}個のクリップ", "ko_KR": "시퀀스의 클립 {outlier.populationSize}개", "pt_BR": { "count": "outlier.populationSize", "one": "{outlier.populationSize} clipe na sequência", "other": "{outlier.populationSize} clipes na sequência" }, "ru_RU": { "count": "outlier.populationSize", "one": "{outlier.populationSize} клипа в эпизоде", "few": "{outlier.populationSize} клипов в эпизоде", "many": "{outlier.populationSize} клипов в эпизоде", "other": "{outlier.populationSize} клипа в эпизоде" }, "zh_CN": "序列中的 {outlier.populationSize} 个剪辑" } } } }, "data": { "speed": "clip.speed", "medianSpeed": "outlier.median", "deviationPercent": "outlier.deviationPercent", "maxDeviationPercent": "options.maxDeviationPercent", "reversed": "clip.reversed", "population": "outlier.populationKey", "populationSize": "outlier.populationSize" } } ``` # Installing (/docs/using/install) Download PPROLint from your aescripts account, install its .ccx file and open its panel in Premiere Pro. PPROLint is a UXP plugin for Premiere Pro. It needs **Premiere Pro 25.6 or later**, on macOS or Windows. ## Download [#download] PPROLint is sold and delivered by [aescripts + aeplugins](https://aescripts.com): **Get PPROLint** on the [home page](/) leads to its page there. Download it from your aescripts account. The download holds the plugin as a `.ccx` file, the package of a UXP plugin. To update PPROLint later, download the new version from your aescripts account and install it the same way. ## Install the .ccx file [#install-the-ccx-file] Quit Premiere Pro first, then use one of these: * **Double-click** the `.ccx` file. The Creative Cloud desktop app opens and asks you to confirm the installation. It may show a warning first, as for any plugin installed from a file. * The **ZXP / UXP Installer** from aescripts + aeplugins: drop the `.ccx` file on it. See [aescripts.com/learn/zxp-installer](https://aescripts.com/learn/zxp-installer/). * Adobe's command-line installer, the Unified Plugin Installer Agent (UPIA): ```sh title="macOS" "/Library/Application Support/Adobe/Adobe Desktop Common/RemoteComponents/UPI/UnifiedPluginInstallerAgent/UnifiedPluginInstallerAgent.app/Contents/MacOS/UnifiedPluginInstallerAgent" --install /path/to/PPROLint.ccx ``` ```bat title="Windows" "C:\Program Files\Common Files\Adobe\Adobe Desktop Common\RemoteComponents\UPI\UnifiedPluginInstallerAgent\UnifiedPluginInstallerAgent.exe" /install C:\path\to\PPROLint.ccx ``` Adobe lists [what its error codes mean](https://helpx.adobe.com/creative-cloud/apps/troubleshoot/plugin-installation-issues/plugin-installation-errors-using-exman-or-upia.html). Do not copy the plugin's files into Adobe's plugin folders by hand: Premiere only loads plugins it installed itself. ## Open the panel [#open-the-panel] In Premiere Pro, choose **Window > UXP Plugins > PPROLint > PPROLint**. The panel docks like any other: drag its tab next to your timeline. Its toolbar has **Check now** and **Settings**. Settings opens a second panel, *PPROLint Settings*, also in **Window > UXP Plugins > PPROLint**. Next, [start the 7-day trial or activate your license](/docs/using/license). # Activate and manage your license (/docs/using/license) Buy PPROLint on aescripts, start the 7-day trial or activate your license in the panel, and where to turn for license questions. PPROLint is sold and licensed by [aescripts + aeplugins](https://aescripts.com). Your purchase and your license are tied to your aescripts account. ## Try it for 7 days [#try-it-for-7-days] [Install PPROLint](/docs/using/install), open its panel and the **License Settings** dialog, then start the trial. It runs for 7 days and needs no purchase. ## Activate [#activate] 1. Buy PPROLint on aescripts: **Get PPROLint** on the [home page](/) leads to it. 2. In Premiere Pro, open the PPROLint panel and its **License Settings** dialog. 3. Follow the dialog to activate the license from your aescripts account. ## Move, deactivate, refunds [#move-deactivate-refunds] Deactivating PPROLint, moving it to another computer, lost licenses and refunds are handled by aescripts, under their policies. Their [license activation and management guide](https://aescripts.com/knowledgebase/index/view/faq/license-activation-management/) answers most questions; for anything else, contact aescripts support from your account. For questions about PPROLint itself, write to [support@pprolint.com](mailto:support@pprolint.com). # Uninstalling (/docs/using/uninstall) Free your license, keep your rules, then remove PPROLint from Premiere Pro. ## 1. Free the license [#1-free-the-license] Deactivate PPROLint in the panel's **License Settings** dialog, so the license is free for another computer. If you forgot, aescripts can free it: see [Your license](/docs/using/license#move-deactivate-refunds). ## 2. Keep your rules [#2-keep-your-rules] Your own rules and your changes to built-in rules are files in the rules folder of PPROLint. To keep them, open **Settings > Rules > Open rules folder** and copy the `*.rule.json` files somewhere else. Removing the plugin may remove that folder with it. ## 3. Remove the plugin [#3-remove-the-plugin] In the Creative Cloud desktop app, open the list of your installed plugins, find PPROLint and uninstall it from its menu. Plugins installed from a `.ccx` file are listed there too. Restart Premiere Pro: the PPROLint panels are gone from **Window > UXP Plugins**. Your license stays valid: reinstall PPROLint and [activate it](/docs/using/license#activate) again whenever you like.