Skip to content

Latest commit

 

History

History
801 lines (609 loc) · 39.5 KB

adobe-extendscript-programming-basics.md

File metadata and controls

801 lines (609 loc) · 39.5 KB

Adobe's ExtendScript Programming Basics

Photo by Fotis Fotopoulos on Unsplash.

Table of Content

Introduction

In this tutorial we look at the basics of programming in JavaScript, and by extension Adobe's ExtendScript. We give a brief overview of the history of JavaScript to touch on the overlap between JavaScript and ExtendScript via ECMAScript.

The tutorial then goes on to show you how you can start coding JavaScript within your Chrome web browser's console. The tutorial touches on programming concepts like variables, variable types, if-statements, for-loops and JSON objects and brings all these concepts together in an example that loops through a list of clips and checks whether each clip has a certain length.

History of JS and Adobe's Extend Script

Below is a shameless copy from Wikipedia. Why rewrite what has been curated over the years by the world?

JavaScript often abbreviated as JS, is a programming language that conforms to the ECMAScript specification. JavaScript is high-level, often just-in-time compiled, and multi-paradigm. Alongside HTML and CSS, JavaScript is one of the core technologies of the World Wide Web. JavaScript enables interactive web pages and is an essential part of web applications. The vast majority of websites use it for client-side page behaviour, and all major web browsers have a dedicated JavaScript engine to execute it.

JavaScript is a language programmers love to hate. Over the years, JavaScript has become such a bastardised language; you can really do anything with JavaScript. Usually, there's a plug-in for almost everything you want to do and there are a ton of online resources available to help you on your way to greatness. For a concise JS tutorial you can check out learn-js' tutorial, or if you're looking for a tutorial with a bit more around the waist, check out w3schools' tutorial.

But, who's in control of the JavaScript language? Who says this is how we are doing things in this version of the JavaScript language? Who decides what stays and what goes over the years? All these are good questions, however, probably the most important question about JavaScript for us in this tutorial is:

How does JavaScript relate to Adobe's ExtendScript?

And the answer is...

JavaScript is related to Adobe's ExtendScript via the ECMAScript specification. Again, from the wiki:

ECMAScript first appeared in 1997 as a scripting-language specification standardized by Ecma International. JavaScript has remained the most widely used implementation of ECMAScript since the standard was first published, with other implementations including JScript and ActionScript.

Funny how the Wikipedia community doesn't even mention Adobe's ExtendScript as another, quite successful, implementations of ECMAScript. But it is, Adobe's ExtendScript was build using the ECMAScript 3 standard published in December 1997. Pretty old right? To give you an idea, in 2019 the ECMAScript 10 standard was published. For a full list of the ECMAScript version you can check this out.

If you think this is confusing, you're right! It is! A table that sort of brought it together for me was the one shown below from w3schools.

Year JavaScript ECMA Browser
1996 1.0 Netscape 2
1997   ECMAScript 1 IE 4
1998 1.3   Netscape 4
1999   ECMAScript 2 IE 5
2000   ECMAScript 3 IE 5.5
2000 1.5   Netscape 6
2000 1.5   Firefox 1
2011   ECMAScript 5 IE 9 (Except "use strict")
2011 1.8.5 Firefox 4 (Except leading zeroes in parseInt)
2012   IE 10
2012     Chrome 23
2012     Safari 6
2013     Firefox 21
2013     Opera 15
2015   ECMAScript 2015 Partially Supported in all Browser

To summarise, JavaScript was developed for the Netscape browser. Netscape 2 was the first browser to run JavaScript. After Netscape, the Mozilla foundation continued to develop JavaScript for the Firefox browser. As of early 2018 only the Chrome (version 68) and Opera (version 55) browsers are supporting ES7. In 2020, until all the kinks have been worked out with the ES7 standard, most browsers: Chrome (version 51), Firefox (version 54), Edge (version 14), Safari (version 10), Opera (version 38) support ES6 - i.e. most popular browsers except IE.

What does this all mean to you and me as Adobe ExtendScript developers? Well, think about it this way. If you were Adobe in the early 2000 and you needed a programming language to interact with your awesome suite of applications, would you write a programming language yourself? Or, start using a variant of a language that has gained some traction; and more importantly, a language that already has developers that speak it.

For us, in 2020 this means we are going to be writing JavaScript code, but old-school JavaScript code - ES3 code. Not that the core functionality and syntax of JS changed much from 1997 to 2020. Notice I say core functionality. Don't get me wrong, many benefits come with using the latest ECMAScript standards, such as more built-in functions that ease your life and much more concise syntax that encourages writing cleaner and more robust code.

So, ideally, we want to write our code in ES6 JavaScript, JS as it used mostly on the web today, but when we deploy our code within Adobe we want to deploy ES3 (ExtendScript) code so that Adobe can understand it. Luckily technologies exist that do exactly that for us, translate our code between different versions of ECMAScript. To give you a taste of the high-level additions that ExtendScript has seen over the years, below we show another table from w3schools with the high-level changes that ES has seen over the years.

Ver Official Name Description
1 ECMAScript 1 (1997) First Edition.
2 ECMAScript 2 (1998) Editorial changes only.
3 ECMAScript 3 (1999) Added Regular Expressions.
Added try/catch.
4 ECMAScript 4 Never released.
5 ECMAScript 5 (2009)

Read More: JS ES5
Added "strict mode".
Added JSON support.
Added String.trim().
Added Array.isArray().
Added Array Iteration Methods.
5.1 ECMAScript 5.1 (2011) Editorial changes.
6 ECMAScript 2015

Read More: JS ES6
Added let and const.
Added default parameter values.
Added Array.find().
Added Array.findIndex().
7 ECMAScript 2016 Added exponential operator (**).
Added Array.prototype.includes.
8 ECMAScript 2017 Added string padding.
Added new Object properties.
Added Async functions.
Added Shared Memory.
9 ECMAScript 2018 Added rest / spread properties.
Added Asynchronous iteration.
Added Promise.finally().
Additions to RegExp.

All things considered, all of this ECMA stuff only becomes important when you're getting serious about writing ExtendScript and you want to distribute a sustainable extension. However, for us today, we're doing basic ExtendScript programming, but keep the ECMAScript version concept in mind when you copy JS code from the web and it doesn't just work in your ExstendScript code - it might have some syntax that is not supported in Adobe's ExtendScript, a.k.a. ECMAScript 3. Hopefully, I've convinced you that JS and ES are "basically" the same and going forward, I'll refer to us coding in JavaScript and not ExtendScript or ECMAScript.

Writing JavaScript in Chrome

Since the core JS syntax like declaring a variable, adding numbers together or printing something out to the console hasn't changed much over the years, we can hop into our Chrome browser, which will give us an easy place to write some JS code and explain the above concepts. To open a console in Chrome, right-click anywhere on an open webpage and click Inspect. I show this below, but you're going to have to excuse my Dutch: Inspecteren=Inspect. Clicking on Inspect should bring up the the Chrome Inspector and you're going to want to go to the Console tab shown below.

Great! Maybe you didn't know that all browsers have a JavaSript console built-in. B.t.w. they do, sometimes it is a bit tricky to get to them. I know with Safari on Mac you've got to enable "Developer Tools". The interface you are presented with, the image shown above, is what we call a Command Line Interface (CLI) as opposed to a Graphical User Interface (GUI). The difference? The one uses pictures, the other uses text. For reference, the console is also sometimes referred to as the terminal or just CLI.

JS Basics

If you've never coded JavaScript in your life, I urge you to work through this learn-js tutorial and this w3schools tutorial at your own pace.

⚠️ Warning! If you can code JavaScript the following section is not for you, the next bit covers the basics of JavaScript like what is variable, variable types, conditionals, JSON objects and functions. If you know these words and concepts well, you need not proceed. If you've never heard of these words or you want a refresher on coding in JS, read forth.

Learning a programming language is very similar to learning to speak a new language. First, you learn basic words; in English words like: Hi, I, am, is, are, etc. Once you know the basic words you can start stringing them together to form sentences: Hi I am _. Once you're comfortable with writing sentences, you can start stringing those together to get paragraphs and essays. To continue this metaphor, in programming terms, paragraphs will be short little scripts that execute a bit of code, whereas essays will be fully-fledged programs that do a lot of complex computations.

Below we show some basic "words", "sentences" and "paragraphs" that you'll see in the JS programming language along with a short description of their meaning.

Examples of "Words" in JS with their meaning

  • var: Used to declare a variable
  • const: Used to declare a constant
  • ``: Used to add variables to text inline
  • //: Used to comments (text that is not executed)
  • "" or '': Used to indicate text
  • ;: Used to indicate the end of a line
  • []: Used to declare lists
  • {}: Used to declare objects and indicate scope.
  • if: Used to check if something is true or false
  • for: Used to loop through lists
  • console.log(): Used to print something out to console
  • console.dir(): Used to print out objects to the console

We can then start using these words to make some sentences, for example:

  • var myName = "John": Declare a variable called myName and assign a value of "John" to it
  • var fruits = ['Apples', 'Pears', 'Peaches']: Declare a list called fruits that contains 3 values: 'Apples', 'Pears', 'Peaches'
  • var clip = {'start':0, 'end':10, 'type':'Audio'}: Declare an object, also called a JSON (JavaScript Object Notation) object called clip that contains 3 attributes: 'start', 'end' and 'type' and 3 associated values: 0, 10 and "Audio".

A short "paragraph" in JavaScript would look something like:

var durationThreshold = 10;
var clips = [
  {'id':1, 'start':0, 'end':10, 'type':'Audio'}, 
  {'id':2, 'start':10, 'end':15, 'type':'Audio'},
  {'id':3, 'start':15, 'end':35, 'type':'Video'}
  ];

for (var clip in clips) {
  var clipDuration = clips[clip].end - clips[clip].start
  if (clipDuration >= durationThreshold){
    console.log(`id: ${clips[clip].id}, type: ${clips[clip].type}`);
  } 
}

Not making any sense? Don't worry! How long it took you to write your first diary entry in English? Luckily, this time around you can already spell English words, you just need to learn the terms you are allowed to use and the "grammar" of stringing these terms and concepts together in JavaScript.

For the inquisitive, the code above does the following:

  • Declare a variable called durationThreshold and set it equal to the value of 10.
  • Declare a list, also called an array, of 3 objects, with each object having 4 attributes ('start', '**end**', 'type' and 'id') and 4 associated values.
  • We then loop through the clips list using what is called a for-loop and calculate the clipDuration of each clip as the difference between the end and start attribute of each clip.
  • We then ask the question: Is the current clip's duration greater or equal that our durationThreshold's value (10), if so, print out the type and id of the current clip to the console.

The output is shown below:

Before we start writing essays, let's start with the words...

Hallo World

There is a coding tradition that the first program you write in any new language has something to do printing out or displaying the text "hallo world". At the bottom of your console, next to the >-character is where we're going to be writing some code.

Execute the following command in the console:

console.log("Hallo World");

Let's unpack what is happening here. We've used the built-in JS function console.log to print out "Hallo World" to the console. Pretty intuitive right? JavaScript comes with a lot of in-built functions, think of these as the words in a spoken language. You first need to know what words you can speak and how

Variables

Variables... What are variables?

Essentially variables are placeholders, things that house values for us that change (are variable) over time. For example, below we will declare 2 variables called a and b. These names are completely arbitrary and it is up to you to choose meaningful variable names - a and b are bad variable names BTW.

In JavaScript, we declare variables using the var keyword, like var a = 1. OK, you don't have to type var, a = 1 will work just fine. However, this is where those ECMA Script version snags come in. In ES3 it is fine to declare your variables without using var, however, if you're going to be transpiling code from ES6 to ES3, you're going to need the var keyword.

Small things like this give the later versions of ECMAScript its robustness. In the background, JavaScript can do a lot more checks and balances if you explicitoly declare what type of variable you are declaring. A variable that will change over time, or a variable that will stay constant. In the later versions of ECMAScript there's a distinction, for example:

var a = 3;
const b = 4;

If you later want to reassign b an error will be thrown,

Compared to assigning a value to a,

However, if you type nothing,

a = 3;
b = 4;

anything can really be done with your variable downstream. So where does this leave you? Rather use var instead of nothing. This way you can use your code later on if you start using transpilers, also, it's only 4 characters and a good JS coding habit to form. Until you know why the other keywords exist and know why you need them, just use var.

Ok, so variable hold values. But why? Well, to make programming more modular and easier to write. To bring it back to the Premiere Pro API, instead of writing:

app.project.activeSequence.videoTracks[0].setMute(true);

We can be a bit more verbose, declaring intermediary variables to store our sub computations and make the code more readable, maintainable and ultimately sustainable.

videoTracks = app.project.activeSequence.videoTracks; // Get all the video tracks
firstTrack = videoTracks[0]; // Get the first video track
firstTrack.setMute(true); // Set the firstTrack's muted attribute using the setMute method

But what about efficiency I hear you say? Doesn't declaring more variables take up more space in memory? In the background, JS doesn't really need that much more space to store your extra variable because of what are called pointers. With most big things we want to store in variables, we only store them in one place and then point to them. Pointers are way outside of the scope this series, but just some motivation as to why more variables are usually good things if you're code is more readable and understandable.

Someone once said: "machines don't read code, humans do."

Variable Types

After the value of your variable stored in RAM, your variable's type is the seconds most important thing to take note of. Knowing which type your variable is will allow you to anticipate how they will behave when certain operations are applied to them. For example, if we declare 2 text variables, called string variables,

var greetingTemplate = "Hallo there, ";
var name = "John";
var result = greetingTemplate + name;
console.log(result);

and I sum them together using the + operator I get, "Hello there, John"

You can think that the behaviour will be different if I declare 2 numbers, for example

var number1 = 1;
var number2 = 2;
var result = number1+number2;
console.log(result);

So what tells JavaScript which is which? The double quotes, "", in this case. If we write anything in double-quotes JavaScript interprets it as a string. We can check the types of variables using the typeof function, for example

var stringNumber = "2";
var numberNumber = 2;
console.log(typeof(stringNumber))
console.log(typeof(numberNumber))

If Statements

If statements, sometimes referred to as conditionals, are used to control the flow of our code. Most of the time in your code you'd want to execute a bit of code if somethings holds true, otherwise, you want to execute another piece of code - if-statements enable us to do that.

A basic if statement looks as follows:

if (condition){
  // code to execute
}

We tell javascript we would like to check if something is true by typing if followed by an open and close round-brackets containing the condition we want to evaluate. We then put all the code we want to execute if the conditions hold between curly braces, {}. For example, we might want to check if the age variable is greater or equal to 18 and if so print out Legal Eagle! to the console, for that we'd write something like:

if (age >= 18){
  console.log("Legal Eagle!")
}

Some basic comparison operators that you'll use in 80% of your if statements:

  • a == b checking if a and b are equal
  • a != b checking if a and b are not equal
  • a > b checks if a is greater than, but not equal to b
  • a >= b checks if a is greater than, or equal to b
  • a < b checks if a is less than, but not equal to b
  • a <= b checks if a is less than, or equal to b

A funky operator you'll see in JS is ===. This operator not only checks if the value of two variable is equal, but also check's that their types match. For example:

var a = "2";
var b = 2;
console.log(a == b);

will print out true, whereas

var a = "2";
var b = 2;
console.log(a === b);

will print out false as "2" !== 2. And yes, !== is also a comparison operator you can use in JS checking that the value and the types aren't equal.

Once you start writing conditionals, you'll quickly run into the situation where you want to write more complex conditions, like this and this, or that should hold before we execute some code. For this, JS uses the && and || operators. The && is a logical AND and the || is a logical OR. Let's expand our Legal Eagle example by also checking if the age is less than 122 - the age of the oldest person to date.

if ((age >= 18) && (age < 123)){
  console.log("Legal Eagle! And a viable age... ")
}

Our sentence, or code snippet, now checks that age is greater or equal to 18 but also checks that the age is less than 123. We've purposefully made this < 123 instead of <= 122 to illustrate the difference. If we know that age will only be an integer (whole) numbers, then both conditions, < 123 and <= 122, are interchangeable, however, if age can have decimal values, then any age up to 122.999999999 will also cause our Legal Eagle! And a viable age... message to print. Also, note the extra round braces around (age >= 18) and (age < 123) which is needed in JS to reduce multiple conditions to one.

OR and AND work as you expect, for 2 conditions to be true when you AND then both conditions need to be true, whereas with OR only one condition needs to be true. The truth table below shows the variations:

a b a AND b a OR b
false false false false
false true false true
true false false true
true true true true

For Loops

After if-statements, loops are probably the tool in your programming toolbox that you'll use most. I'd like to take a sentence or two to linger on this metaphor of programming concepts, like if-statements and for-loops, as tools in your programming toolbox. Initially, you might not know that you should use a hammer to hit a nail into the wall and you might use a screwdriver to get in done. Similarly, in programming, there aren't any rules that say you have to use a for-loop to do this or use an if-statement to do that. Although, hitting in a nail with a hammer does work better once you know how to use the hammer. Ok, done with my one or two sentences about your programming toolbox.

For loops... They do what they say, they loop through lists for a defined condition. In JavaScript they look as follows:

for(var i=0; i<=5; i=i+1){
  console.log(i)
}

Woah! A lot of new symbols here. To give you an idea, the output printed to the console for the above piece of code will be:

0
1
2
3
4
5

Do you see what is happening? Let me alter it a bit:

for(var i=0; i<=5; i=i+1){
  console.log(`The value of i is: ${i}`)
}

The output here will be:

The value of i is: 0
The value of i is: 1
The value of i is: 2
The value of i is: 3
The value of i is: 4
The value of i is: 5

Let's unpack step for step what is happening.

  • First, we indicate to JS that we want to create a for loop using the for keyword.
  • Then we have to create a "dummy" variable that the loop can use to increment every time it loops. Usually, this "dummy" variable is called i and we follow suit.
  • The code in between the braces, var i=0; i<=5; i=i+1, consists of 3 parts separated by the semi-colon (;):
    • The first bit, var i=0, initialises the variable i - in our case, we start at 0.
    • The second part, i<=5, specifies the condition when we should stop - in our case when i becomes greater than 5, i<=5.
    • The last part, i=i+1, specifies what should happen to i every time we go around our loop - in our case, add 1 to i.
  • We then open the for-loop scope using the curly braces, {}. Similar to the if-statement, the curly braces groups together code that should be executed every time we loop through - in our case, we just print out: The value of i is: <THE VALUE OF i> every loop.

Note that the last bit of the code between the round braces, var i=0; i<=5; i=i+1, is usually shorthanded as i=0;i<=5;i++, dropping the var and substituting i++ for i=i+1. Note that i++ only increments i with 1, if you want to loop that increments with 2, then you still have to use i=i+2.

To solidify what's happening here, here is another example where we start i at 10 and decrease it every loop with 2.

for(var i=10; i > 0; i=i - 2){
  console.log(`The value of i is: ${i}`)
}

The output here will be:

The value of i is: 10
The value of i is: 8
The value of i is: 6
The value of i is: 4
The value of i is: 2

There are a few other short-hand variations on the standard for loop. Coming back to our example at the top where we looped through all of our clips:

for (var clip in clips) {
  var clipDuration = clips[clip].end - clips[clip].start
  if (clipDuration >= durationThreshold){
    console.log(`id: ${clips[clip].id}, type: ${clips[clip].type}`);
  } 
}

As you can see, in this for-loop there is no mention of an i, instead we access each clip via the clip variable directly. This only works if the list, clips in our case, is a list of JSON objects. Remember, our clips variable is defined as:

var clips = [
  {'id':1, 'start':0, 'end':10, 'type':'Audio'}, 
  {'id':2, 'start':10, 'end':15, 'type':'Audio'},
  {'id':3, 'start':15, 'end':35, 'type':'Video'}
  ];

This is indeed a list of JSON objects, so we can use the shorthand for(var clip in clips). If we wanted to use the for-loop with the i variable, the code would look something like:

for (i = 0; i < clips.length; i++) {
  var clip = clips[i];
  var clipDuration = clips[clip].end - clips[clip].start;
  if (clipDuration >= durationThreshold){
    console.log(`id: ${clips[clip].id}, type: ${clips[clip].type}`);
  } 
}

Here we increment i from 0 to clips.length which will be equal to 3 as there are 3 elements in the clips list. Note the i < clips.length and not i <= clips.length. Using i < clips.length ensures that we don't access the value stored at clips[clips.length] as this value doesn't exist!

Why?

Remember, in JS, and most other programming languages, lists are indexed starting at 0, so

  clips[0] = {'id':1, 'start':0, 'end':10, 'type':'Audio'}
  clips[1] = {'id':2, 'start':10, 'end':15, 'type':'Audio'}
  clips[2] = {'id':3, 'start':15, 'end':35, 'type':'Video'}

But there is no clips[3]!.

Objects

Objects in JavaScript make the world go round. So much so that there is a dedicated file type, JSON, or JavaScript Object Notation. From their website:

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language Standard ECMA-262 3rd Edition - December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language.

So JSON is great between languages, but what about within JavaScript? Well, let's look at a few examples. You can think of an object as a collection of key-value pairs. We define an object using the curly braces, {} and then we list the key-value pairs for each attribute of our object. Let's create a dog object:

dog = {
    "color": "brown",
    "tail": "long",
    "vaccinated": true,
    "age": 5
}

In objects, value to the left of the colon is referred to as the key and the value to the right is referred to as the value. In JS, we can access each attribute of the dog object variable using the dot (.) or braces ([]) syntax, like dog.color or dog['color'].

The dot . and brace [] syntaxes are exactly the same, however, if your key has got space, the . syntax won't work. For example:

dog = {
    "eye color": "brown"
}

Here we won't be able to call, dog.eye color and you can see why? The space will confuse JavaScript into thinking color is a separate variable, so here we'll use dog['eye color'].

Bringing it together

To bring everything together let's have a look at our short "paragraph" we wrote at the beginning of this tutorial:

var durationThreshold = 10;
var clips = [
  {'id':1, 'start':0, 'end':10, 'type':'Audio'}, 
  {'id':2, 'start':10, 'end':15, 'type':'Audio'},
  {'id':3, 'start':15, 'end':35, 'type':'Video'}
  ];

for (var clip in clips) {
  var clipDuration = clips[clip].end - clips[clip].start
  if (clipDuration >= durationThreshold){
    console.log(`id: ${clips[clip].id}, type: ${clips[clip].type}`);
  } 
}

Hopefully, after this tutorial, you can look at this bit of code and at least understand what the code is doing. Don't worry if you can't remember the syntax exactly, that's what Google is for. Seriously, no programmer can code without internet access, maybe if they have the instruction manual next to them. But more often than not you'll find yourself Googling:

  • "For loop JavaScript"
  • "If statement JavaScript"
  • "Declare variable JavaScript"
  • etc.

But after the 100th time Google how to write a JavaScript for-loop, either the repetition or the irritation of Googling for the 101st time makes it settle in. ☺️

Applying these concepts to Premiere Pro

If you've come this far and this is the first time you're programming, well done! These concepts are bound to be very weird the first time. We urge to keep going on your programming journey and to illustrate how all of these concepts can be used Premiere Pro, below I show some ExtendScript code that will mute the first video track in our active sequence. We're building on the same example we used in this video.

videoTracks = app.project.activeSequence.videoTracks; // Get all the video tracks
firstTrack = videoTracks[0]; // Get the first video track
firstTrack.setMute(true); // Set the firstTrack's muted attribute using the setMute method

The code above is only able to mute the first track because we create the variable firstTrack and set it equal to the first element in the videoTracks list, i.e. videoTracks[0]. But if we could iterate through all of our tracks, we can set the mute attribute of all our tracks in one go, irrelevant of how many tracks there are. Basically, we would like to call videoTracks[i].setMute(true) for i running from 0 to the total number of tracks - sounds like something familiar? A for-loop will give us the ability to create our i counter, however, we still need to figure out how many video tracks there are. Luckily, the videoTracks object has an attribute numTracks. So our for-loop will look something like this:

// Get video tracks
videoTracks = app.project.activeSequence.videoTracks;

// Loop through video tracks
for(i=0;i<videoTracks.numTracks;i++){

  // Set each track's mute state to true
  videoTracks[i].setMute(true);
}

We can expand this example a bit further to give us some print out when each track is set to mute. This entire time we've been making the statement ExtendScript is basically the same as JavaScript. However, when it comes to printing out values in ExtendScript we've got to use the $.write() method. So basically instead of using console.log(), in ExtendScript world we'll be using $.write() and it's brother $.writeln(). $.writeln() is probably more similar to console.log() as it also includes and "Enter"/"Return" at the end of the line, whereas $.write() just keeps printing in one line.

Let's look at an example. We'll be adding the text Muted track <trackNr> to our for loop that we know when each track has been muted.

videoTracks = app.project.activeSequence.videoTracks;

for(i=0;i<videoTracks.numTracks;i++){
  videoTracks[i].setMute(true);
  $.write("Muted track " + i)
}

However, for 6 video tracks, the code above will print out:

Muted track 1Muted track 2Muted track 3Muted track 4Muted track 5Muted track 6

This is because $.write keeps writing, no new line! We can inject a new line using the \n character. In programming, there are a few "special" characters, usually prepended with \, that indicate special meaning. For example, \n denotes the Enter key, whereas \t denotes the tab character. If we add this our code snippet above:

videoTracks = app.project.activeSequence.videoTracks;

for(i=0;i<videoTracks.numTracks;i++){
  videoTracks[i].setMute(true);
  $.write("\nMuted track " + i)
}

we'd actually get:


Muted track 1
Muted track 2
Muted track 3
Muted track 4
Muted track 5
Muted track 6

Notice the first open line? This is because we start with \n, an alternative would be:

videoTracks = app.project.activeSequence.videoTracks;

for(i=0;i<videoTracks.numTracks;i++){
  videoTracks[i].setMute(true);
  $.write("Muted track " + i + "\n")
}

Here we are adding the "Enter" at the end of the line. The output would be:

Muted track 1
Muted track 2
Muted track 3
Muted track 4
Muted track 5
Muted track 6

Now we get last \n creating an open line on the last line. As we usually just use the printouts to give ourselves an idea of what is going on in the code, the open lines don't matter too much, but if you were wondering, now you know.

Luckily, there is another method that we can use, that deals with all this entering after the text, and it's called $.writeln(), a.k.a. write line.

videoTracks = app.project.activeSequence.videoTracks;

for(i=0;i<videoTracks.numTracks;i++){
  videoTracks[i].setMute(true);
  $.writeln("Muted track " + i)
}

Conclusion

In this tutorial, we discussed the history of JavaScript, ECMAScript and ExtendScript and how the 3 are related. We looked at opening a JavaScript console within Google Chrome and showed you how to write some JS in your browser.

We made the analogy that learning a programming language is a lot like learning a new language. First, you need to learn the words of the language, then you can start writing sentences and paragraphs, and eventually we can build it up to fully-fledge essays that lift a lot of weight for us.

We looked at variables, variable types, if-statements, for-loops and JSON objects and brought all the concepts together in an example that loops through a list of clips and checks whether each clip has a certain length.

Finally, we brought everything together by looking at an ExtendScript example where we loop through all of our video tracks in Premiere Pro and set their mute attributes to false.