New xLights API, Package Script

Late last year, the xLights developers started adding API functionality to xLights so you can script repeating tasks. For example- you can roll your own batch-render or batch controller upload scripts now. The API is still being developed, but I asked the devs to include an option to package a sequence as part of it, and they followed through! As of v. 2022.1, packageSequence is now included in the API.

The reason I asked for this is it saves a lot of end-of-the-season tedium for me, and I’m sure others. Since our layout changes fairly significantly each year, along with the names and locations of props, we basically need to start almost from scratch on our sequences. Just opening up last season’s sequence with the current season’s layout can be a mess, and doesn’t often give us the results we want. Meanwhile- xLights has an outstanding direct-import from Zip feature for “packaged” sequences, so starting last year- I package (Zip) all of our sequences up. That way- we can import them as new sequences into our new layout, and it allows us to very-easily map old props to new ones.

The other advantage is it keeps our show directory structure clean. To set up a new directory for the current year, all we have to do is copy a few files and folders from the previous season’s show directory to a clean directory:

  • 3D (3D model directory. You may be using a different folder.)
  • DownloadedFaces
  • colorcurves
  • Images (Layout (house, yard) images. You may be using a different folder.)
  • pallettes
  • valuecurves
  • xlights_keybindings.xml
  • xlights_networks.xml
  • xlights_rgbeffects.xml

When you package a sequence- only the resources that sequence actually uses are packaged with it (images, videos, etc.). When you import it, a folder called “Imported Media” is created and a folder within it named after the sequence will hold all of the media needed for it (except for the music). This keeps everything neat, and you avoid copying a bunch of unused images, videos, etc. from previous years that you aren’t using anymore. We keep all of the music files in a separate folder that is used year-to-year, so it isn’t duplicated anywhere. (I turn off the option to include music in packaged sequences in xLights Preferences.)

In order to package our current season’s sequences in the past, I would have to…

  • Open each sequence in-turn
  • Render All
  • Save
  • Tools -> Package Sequence
  • Save

…for every sequence in our show. As of 2021 that’s over 60 sequences. Very time-consuming and tedious.

UPDATE (January 10, 2022):
There is a bug in the Mac version of the API for packageSequence. If the packaged sequences are not saved to your show folder, they may be in: /Users/{username}/Library/Containers/xLights/Data/

The script below may be outdated. I’ve moved all of my scripts to GitHub:

So, now thanks to the new xLights API- I’ve got it down to a PHP script…

 * batch_package.php
 * by Wolf I. Butler
 * v. 1.1, Last Updated: 01/07/2022
 * Script using the new xLights API to render and package all sequences
 * in the current Show Directory.
 * This was designed to work on Mac or Linux with PHP installed.
 * For Windows- PHP CLI will need to be installed.

//Be sure the API server is enabled in xLights. As of this writing, it is set in Preferences -> Output
//Set xFade/xSchedule to "Port A".

//Just set this...
define ( 'SHOWDIR', '/Users/chuck/xlights/2021/Christmas' );   //This needs to match your xLights Show Directory

//You shouldn't need to chnage this unless xLights devs change the port number (49913)
define ( 'BASEURL', '' ); //This is the default for the xLights API.

//Leave the rest alone...

//Send GET request to the API
function do_get ( $request ) {
    //Initiate cURL.
    $ch = curl_init(BASEURL . '/' . $request);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//    curl_setopt($ch, CURLOPT_FRESH_CONNECT, TRUE);
    //Set high timouts as some sequences take a long time to render...
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
    curl_setopt($ch, CURLOPT_TIMEOUT, 600); //Yes- 10 minutes, for long renders!

    if ( $curlResult = curl_exec($ch) ) {
        if ( $json = json_decode ( $curlResult, TRUE ) ) return $json;
        else return $curlResult;
    return FALSE;

function disp_result ( $input ) {
    //Since the still-in-development API doesn't always return an array, process returned text accordingly.
    if ( is_array ( $input ) ) {
        foreach ( $input as $index => $value ) echo "\n\t$index: $value";
    else echo "\n\t$input";

//Make sure xLights is running...
if ( ! do_get ( 'getVersion' ) ) {
    echo "\nYou must have xLights open to run this script!\n\n";

//Get file list from current directory and process all .xsq files:
$arrDir = scandir ( SHOWDIR );
foreach ( $arrDir as $file ) {
    if ( substr ( $file, -4 ) == '.xsq' ) {
        $encFile = str_replace ( ' ', '%20', $file );
        echo "\nProcessing: " . $file;
        disp_result ( do_get ( "openSequence/$encFile" ) );
        echo "\n\tRendering...";
        disp_result ( do_get ( "renderAll") );
        disp_result ( do_get ( "saveSequence") );
        echo "\n\tPackaging...";
        disp_result ( do_get ( "packageSequence") );

As long as you have a PHP CLI installed on your Mac or Windows machine, all you need to do is edit the Show Directory in the file and run it. It will open every sequence, render it, and export it.

If you aren’t a developer and don’t already have PHP* installed, MAMP is one of the easiest ways to get it on your machine.

Once done- I can delete everything but the .zip files from last season’s show directory, and we are ready to import them into this season’s directory/layout. 🙂

* I like doing everything in PHP, but the above could easily be adapted into a Mac or Linux shell script using cURL. I don’t use Windows, but I understand cURL is included in recent versions of Windows 10 as well, so you could build a .BAT to do the above. I believe you can also install a Linux CLI in Windows now too.