How to handle variable number of Clips?

Hi!

I’m working on an app that concatenates Question and Answer videos together to form a final edit. My current stack is No Code - Bubble, Integromat, ShotStack.

The Challenge: The number of Questions and Answers is a variable number, therefore I cannot predefine a set number of Clips in each Track.

For example, Video Edit #1 might be comprised of 3 Qs and 3 As. Video Edit #2 might have 5 Qs and 5As. So in aggregate, I’d have 6 or 10 separate video files, respectively.

This is complicated by the fact that each Question and Answer must also have a Transition asset between them (such as a Luma Matte, or simple overlaid Video Asset). Lastly, the final edit must also have a quick Intro Video and Outro Video.

The intended full length Interview edit format is:

  • Intro Video Asset
  • Question #1 Video Asset
  • Transition
  • Answer #1 Video Asset
  • Transition
  • Question #2 Video Asset
  • Transition
  • Anser #2 Video Asser
  • Repeat this sequence X times, where X = total number of Questions and Answers
  • Outro Video Asset

I’m trying to understand how I should handle the variable number of total Clips.

Cumbersome Potential Solution #1:

  • Setup a filter that routes the most “common” total Clip values (let’s say 4, 6, 8, 10) each to its own JSON template, where each template is preset with the expected number of Clips

Potential Solution #2:

  • Pre set a high number of Clips that is higher than what I would actually need for any given full video (let’s say 20)
  • I think this will not work, because I would have more Transition assets than video assets (such as in the example above…if I only had 1 Q and 1 A…I would have 2 extra Transitions playing)
  • Unless I can write if/then statements within the JSON perhaps? Such as if next Clip contains no Video Asset URL, ignore subsequent Clips?

Potential Solution #3:

  • Create a first edit that simple concats Question #1 - Transition - Answer #1, Q2-T-A2, Q3-T-A3, etc
  • Then join those together with the intro and outro videos in a completely new second edit?

Is there something obvious I’m missing?

I can see three potential solutions here. One is straight via the API using the Node.js SDK which I’ll include for completeness sake, one via Integromat, and one via Zapier.

All build the same video with two different sets of interview questions and answers.

Node.js SDK

const Shotstack = require('shotstack-sdk');

const defaultClient = Shotstack.ApiClient.instance;
const DeveloperKey = defaultClient.authentications['DeveloperKey'];
const api = new Shotstack.EditApi();

let apiUrl = 'https://api.shotstack.io/v1';

defaultClient.basePath = apiUrl;
DeveloperKey.apiKey = 'YOUR_KEY';

// Assuming that intro and outro are the same
const introVideoSrc = 'https://cdn.shotstack.io/au/v1/gazk9hycb0/6cbe13c3-4975-4de1-b20e-63150dda90d1.mp4';
const outroVideoSrc = 'https://cdn.shotstack.io/au/v1/gazk9hycb0/2d984358-658d-45a4-a741-84ed1fc5f84d.mp4';

// This can be a variable number of interview clips
const interviewQuestions = [
    {
        'question': 'https://cdn.shotstack.io/au/v1/gazk9hycb0/d1c4dfe9-0a54-4d62-aca4-ac94869ce1f0.mp4',
        'answer': 'https://cdn.shotstack.io/au/v1/gazk9hycb0/b368eac3-e24e-45fe-9ab0-7c0a0a25c137.mp4'
    },
    {
        'question': 'https://cdn.shotstack.io/au/v1/gazk9hycb0/60f54caa-9054-4fcf-8459-9f5b0cdec5f7.mp4',
        'answer': 'https://cdn.shotstack.io/au/v1/gazk9hycb0/8afba3da-5799-45e8-adfe-168b9c8f9441.mp4'
    }
]

let clips = [];
let start = 0;
const length = 3;

// Create intro clip
let introAsset = new Shotstack.VideoAsset;
introAsset.setSrc(introVideoSrc);

let introClip = new Shotstack.Clip;
introClip
    .setAsset(introAsset)
    .setStart(start)
    .setLength(length)

clips.push(introClip);

start += length;

// Generate clips
interviewQuestions.forEach((interviewQuestion) => {

    let questionAsset = new Shotstack.VideoAsset;
    questionAsset.setSrc(interviewQuestion.question);

    let answerAsset = new Shotstack.VideoAsset;
    answerAsset.setSrc(interviewQuestion.answer);

    let questionClip = new Shotstack.Clip;

    questionClip
        .setAsset(questionAsset)
        .setStart(start)
        .setLength(length)

    clips.push(questionClip);

    start += length;

    let answerClip = new Shotstack.Clip;

    answerClip
        .setAsset(answerAsset)
        .setStart(start)
        .setLength(length)

    clips.push(answerClip);

    start += length;
});

// Create outro clip
let outroAsset = new Shotstack.VideoAsset;
outroAsset.setSrc(outroVideoSrc);

let outroClip = new Shotstack.Clip;
outroClip
    .setAsset(outroAsset)
    .setStart(start)
    .setLength(length)

clips.push(outroClip);

// Put the video together
let track = new Shotstack.Track;
track.setClips(clips);

let timeline = new Shotstack.Timeline;
timeline
    .setBackground('#000000')
    .setTracks([track]);

let output = new Shotstack.Output;
output
    .setFormat('mp4')
    .setResolution('hd')

let edit = new Shotstack.Edit;
edit
    .setTimeline(timeline)
    .setOutput(output);

// Render the video
api.postRender(edit).then((data) => {
    let message = data.response.message;
    let id = data.response.id
    
    console.log(message + '\n');
    console.log('>> Render successfully completed with id: ' + id);

}, (error) => {
    console.error('Request failed: ', error);
    process.exit(1);
});

Integromat

To process a variable amount of clips you will have to add the JSON to the Shotstack module using the array aggregator module. The following example extracts a range of variables from a Google Sheet, creates an array out of that data that’s in the same format as what the API expects (I added a Create JSON module to the blueprint to make this easier). Subsequently that array is mapped to the Clips object inside the Shotstack Render module.

You could only do this for the variable question/answer clips, and add the intro and outro directly into the module if you expect these to stay static.

I haven’t added transitions as a variable component, but you could make this dynamic for every asset.

You can copy the Google Sheet template here, and use the below blueprint to import it straight into your Integromat scenario.

variable-clips.json (82.1 KB)

Zapier

Zapier (more on Zapier here) follows a lot of the logic from this Learn article and uses the same Google Sheet template as the above Integromat example. It would have been the easiest if it wasn’t for the outro.

The only module that you need is the stitch module where you set it up for the maximum amount of question/answer sets you’re expecting. In the case you are sending less than the maximum amount of clips you set the Zap up for it’ll go on and ignore those ones not filled in.

Once you have stitched together your intro and interview questions/answers you wait for the render to complete, and then repeat the process for the outro.

The Zapier stitch module doesn’t yet take transitions but that functionality is planned for the full release.