Using the After Effects Socket Object and JSON to dynamically populate a Drop-Down List

In my last post I talked about adding project and scene information to our timestamp script. We’ve covered using system.callSystem() as a gateway to information outside of After Effects. This time we are going to use After Effects built in Socket object to dynamically populate a DropDown list for our script. We’ll also pull JSON out of our old bag of tricks.

The Socket object allows you to set up a TCP connection with a server and exchange data with this server. A Socket is pretty versatile. We can set up different services like FTP file transfer, SMTP email, and Web services via HTTP. Today we are going to demo a very bare-bones Web Service using HTTP. How bare bones? Well, for this demo we are simply going to prepopulate some sample values in a JSON string and serve it up from a web server. In our next demo, we’ll go about connecting this service to different databases.

After Effects 7 introduced some useful new UI controls including a ListBox and DropDownList. Both of these controls work really well for grabbing multiple values like a group of projects, scene list, lower thirds or slate info. The main difference between the two is that a ListBox displays all of the values available and let’s you select multiple items if you rig it correctly whereas the DropDownList only displays one value at a time. For this demo we’ll use a DropDownList.

Typically, you would create an array of string values in your script and those values would populate your list. Like so…

var projectArray =["Sample Project1", "Sample Project2", "Sample Project3"];
win.projectList = win.add ("dropdownlist", [20,25,230,120], projectArray);

But what happens if you don’t know what values you’ll need in your list when you write your script? You can dynamically populate your script at script runtime. Aditionally, After Effects 7 has a strong event model that let’s you update information based on user interaction. We’ll also cover updating our info in a later demo.

So we’ve covered our UI control, what about the Socket? It is pretty straight forward. We set up our Objects with a typical Javascript Constructor and set some variables with the location of our Web Service and use the open(), write(), read(), and close() methods of the Socket object to communicate with our Web Server over port 80. Like so…

       webConnect	= new Socket;
	  response	= new String;
	  lines		= new Array;
	  if(webConnect.open("your-web-server.com:80")) {

		webConnect.write('GET /path/to/your/sampleProject.json HTTP/1.0nn');
		response	=  webConnect.read();
		lines		= response.split(/n/);
		projects	= lines[lines.length-1];

		webConnect.close();

		return projects.toString();
				
				
	}else{
		return  '{["unable to open webConnect via Socket"]}';
				
	}

There are a couple of lines of interest in the previous code. Notice how we use response.split(/n/) and lines[lines.length-1] above? We do this because we really are communicating at a low level with the Socket object and response = webConnect.read() includes the response header including the server information, response type, etc. We know we have a simple one-line JSON file at the end of our web service so we can simply grab the last line. In a more complex service we'd need to be much more robust. We also wrap our Unable to connect message with a JSON wrapper, return '{["unable to open webConnect via Socket"]}'; so that we can use eval() on the string even in an error condition.

Our final demo script.

//grab our projects via a simple web service
var projectsString = getProjects();
//check for existence of Projects string and populate DropDown with error if we don't have one

if(projectsString){
    //the JSON eval to get an array of projects
    var projectArray = eval(projectsString);
}else{
	var projectArray = ['Unable to connect to Projects Server'];
}

//buid and show our UI
var win = new Window('palette', 'Project DropDown Demo',[100,100,352,165]);
var w = buildUI();
w.show();

//the getProjects method, notice the nested function. The nested (inner) function is private to its containing (outer) function. This gives us an opaque interface for getProjects() that let's us do validation and webConnect without revealing the details of the connect. More on this in later demos

function getProjects() {
		
           	//here is where we do internal validation before we return a valid webConnect
		//things like version check etc.

		return webConnect();
		
           //the Socket connection setup
		function webConnect (){

			webConnect	= new Socket;
			response	= new String;
			lines		= new Array;
                 
                //open the connection, change the your-web-server.com obviously
			if(webConnect.open("your-web-server.com:80")) {
                      //Use GET to grab the JSON with the path to your web service
				webConnect.write('GET /path/to/your/sampleProject.json HTTP/1.0nn');
				//put the response in a variable
                      response	=  webConnect.read();
                      //grab the last line
				lines		= response.split(/n/);
				projects	= lines[lines.length-1];
                      //close the connection
				webConnect.close();
                      //return a string value to the eval()
				return projects.toString();
				
				
			}else{
                       //return a JSON string with our problem
				return  '{["unable to open webConnect via Socket"]}';
				
			}
		}
				
	}

//build our UI
function buildUI(){
		
	 if (win != null) {
	 	
		win.projectList = win.add ("dropdownlist", [20,25,230,120], projectArray);
		win.projectList.selection = 0;
		 
      }
         return win

	}

When I run our demo with this JSON

{["Sample Project1", "Sample Project2", "Sample Project3"]}

I get this in After Effects

DropDown Demo 1
DropDown Demo 2

Pretty nice. What's next? There isn't any security model so we'll either need to add authentication or run this service behind a firewall. We need to hook up our service to a database and develop methods for acquiring different sets of data. We're on our way.

The downloadable version of this script includes a link to a working demo that I'll try and keep running for a bit. It's pretty straight forward to set up on any working web server.

Downloadable version of this script and sample JSON file

8 Comments

  1. Michel said

    Hi, does anyone has ever used a script to retrieve an RSS feed with socket.

    Here is the code I use :

    //–

    var webConnect = new Socket;

    var response = new String;

    var rss = “”;

    if(webConnect.open(“api.meteorologic.net:80″,”UTF-8”)){

    webConnect.write(“GET /forecarss?p=Paris”);

    response = webConnect.read(9999999);

    response = response.toString();

    var xmlStart = response.indexOf(“<?xml");

    var xmlString = response.substring(xmlStart, response.length);

    try

    {

    rss = new XML(xmlString);

    }catch(e){ alert('error parsing XML with error \r ' + e.toString()) }

    alert(rss);

    }

    //–

    but the display "alert(rss);" is blank while the web page contains much information : http://api.meteorologic.net/forecarss?p=Paris

    thanks for any help..

    Michel

  2. patrick ochieng said

    is it possible to connect after effects to a database and have it display and update the values?
    Im looking at creating an elections pack for a small tv station in kenya and im looking into linking a database to ae.

  3. admin said

    Hi patrick,

    I’d write a web service in a scripting language like php, python or ruby to connect to the database and then have an AE socket connect to a translation service. AE sockets are pretty bear and aren’t great for DB connections and authentication.

    Dale

  4. michael cardeiro said

    thanks for the code. I was really stuck on this. here seems to be an error in your code, the line:
    lines = response.split(/n/);

    should be
    lines = response.split(/\n/);

  5. admin said

    Thanks for the heads up michael. The download script is correct, but it looks like my code style plugin is mangling the display code.

  6. David said

    I have an After Effect project, I need to access a picture from a url and never worked with sockets, any help would be appreciated. I need to replace a placeholder with file in my script. Works on my network and local files, but can’t get the connection with a url address. The picture is located, as an example, at http://distilleryimage3.s3.amazonaws.com/2940b7e0236511e2af9022000a1f9a23_7.jpg. I can import into AE from the GUI, but I need to move this to script. Thanks in advance for your help.
    David

    webConnect = new Socket;
    if(webConnect.open(“http://distilleryimage3.s3.amazonaws.com”)) {
    webConnect.write(‘GET /2940b7e0236511e2af9022000a1f9a23_7.jpg HTTP/1.0nn’);
    response = webConnect.read();
    webConnect.close();
    aler(‘complete’);
    }else{
    alert(‘fail’);
    }

  7. admin said

    Hey David,

    A couple of things.
    1. I think you need to indicate the port to connect over, does http://distilleryimage3.s3.amazonaws.com:80 work?
    2. The root http://distilleryimage3.s3.amazonaws.com/ throws an access denied. I wonder if attempts to connect then errors out so that it doesn’t traverse to the directory at that point.

    If it continues to give you problems, you might use a proxy that first fetches the image and then has a different endpoint for your url.

    Hope that helps,

    Dale

  8. […] in communicated through socket objects the article here was indispensable (albeit 6 years […]

RSS feed for comments on this post

Comments are closed.