How to create typewriter effect

Is it possible to use shotstack to create typewriter effect such as this?

Potentially something like this:

{
    "output": {
        "format": "mp4",
        "size": {
            "width": 500,
            "height": 500
        }
    },
    "timeline": {
        "soundtrack": {
            "src": "https://shotstack-content.s3.amazonaws.com/rocky.mp3",
            "effect": "fadeInFadeOut"
        },
        "fonts": [
            {
                "src": "https://templates.shotstack.io/basic/asset/font/notosans-bold.ttf"
            }
        ],
        "background": "#000000",
        "tracks": [
            {
                "clips": [
                    {
                        "asset": {
                            "height": 30,
                            "width": 450,
                            "type": "html",
                            "html": "<div>The world ain't all sunshine and rainbows.</div>",
                            "css": "div { line-height: 125%; font-family: \"Noto Sans\"; font-weight: 600; text-align: left; color: #FFF; font-size: 18px; }"
                        },
                        "start": 0,
                        "length": 5,
                        "position": "top",
                        "offset": {
                            "y": -0.03
                        }
                    }
                ]
            },
    		{
                "clips": [
                    {
                        "asset": {
                            "height": 30,
                            "width": 450,
                            "type": "html",
                            "html": "<div>Rocky Balboa</div>",
                            "css": "div { line-height: 125%; font-family: \"Noto Sans\"; font-weight: 600; text-align: left; color: #FFF; font-size: 22px; }"
                        },
                        "start": 0,
                        "length": 5,
                        "position": "top",
                        "offset": {
                            "y": -0.09
                        }
                    }
                ]
            },
            {
                "clips": [
                    {
                        "start": 3.72,
                        "length": 1.28,
                        "position": "center",
                        "asset": {
                            "height": 350,
                            "width": 450,
                            "html": "<div><span>Let me tell you something you already know</span></div>",
                            "css": "div { line-height: 125%; font-family: \"Noto Sans\"; font-weight: 600; text-align: left; color: #dfe4ea; font-size: 55px; } span {color: #FFF;}",
                            "type": "html"
                        },
                        "offset": {
                            "y": -0.1
                        }
                    }
                ]
            },
			{
                "clips": [
                    {
                        "start": 3.44,
                        "length": 1.56,
                        "position": "center",
                        "asset": {
                            "height": 350,
                            "width": 450,
                            "html": "<div><span>Let me tell you something you already</span> know</div>",
                            "css": "div { line-height: 125%; font-family: \"Noto Sans\"; font-weight: 600; text-align: left; color: #dfe4ea; font-size: 55px; } span {color: #FFF;}",
                            "type": "html"
                        },
                        "offset": {
                            "y": -0.1
                        }
                    }
                ]
            },
            {
                "clips": [
                    {
                        "start": 3.34,
                        "length": 1.66,
                        "position": "center",
                        "asset": {
                            "height": 350,
                            "width": 450,
                            "html": "<div><span>Let me tell you something you</span> already know</div>",
                            "css": "div { line-height: 125%; font-family: \"Noto Sans\"; font-weight: 600; text-align: left; color: #dfe4ea; font-size: 55px; } span {color: #FFF;}",
                            "type": "html"
                        },
                        "offset": {
                            "y": -0.1
                        }
                    }
                ]
            },
            {
                "clips": [
                    {
                        "start": 2.97,
                        "length": 2.03,
                        "position": "center",
                        "asset": {
                            "height": 350,
                            "width": 450,
                            "html": "<div><span>Let me tell you something</span> you already know</div>",
                            "css": "div { line-height: 125%; font-family: \"Noto Sans\"; font-weight: 600; text-align: left; color: #dfe4ea; font-size: 55px; } span {color: #FFF;}",
                            "type": "html"
                        },
                        "offset": {
                            "y": -0.1
                        }
                    }
                ]
            },
            {
                "clips": [
                    {
                        "start": 2.86,
                        "length": 2.14,
                        "position": "center",
                        "asset": {
                            "height": 350,
                            "width": 450,
                            "html": "<div><span>Let me tell you</span> something you already know</div>",
                            "css": "div { line-height: 125%; font-family: \"Noto Sans\"; font-weight: 600; text-align: left; color: #dfe4ea; font-size: 55px; } span {color: #FFF;}",
                            "type": "html"
                        },
                        "offset": {
                            "y": -0.1
                        }
                    }
                ]
            },
            {
                "clips": [
                    {
                        "start": 2.67,
                        "length": 2.33,
                        "position": "center",
                        "asset": {
                            "height": 350,
                            "width": 450,
                            "html": "<div><span>Let me tell</span> you something you already know</div>",
                            "css": "div { line-height: 125%; font-family: \"Noto Sans\"; font-weight: 600; text-align: left; color: #dfe4ea; font-size: 55px; } span {color: #FFF;}",
                            "type": "html"
                        },
                        "offset": {
                            "y": -0.1
                        }
                    }
                ]
            },
            {
                "clips": [
                    {
                        "start": 2.59,
                        "length": 2.41,
                        "position": "center",
                        "asset": {
                            "height": 350,
                            "width": 450,
                            "html": "<div><span>Let me</span> tell you something you already know</div>",
                            "css": "div { line-height: 125%; font-family: \"Noto Sans\"; font-weight: 600; text-align: left; color: #dfe4ea; font-size: 55px; } span {color: #FFF;}",
                            "type": "html"
                        },
                        "offset": {
                            "y": -0.1
                        }
                    }
                ]
            },
            {
                "clips": [
                    {
                        "start": 2.44,
                        "length": 2.56,
                        "position": "center",
                        "asset": {
                            "height": 350,
                            "width": 450,
                            "html": "<div><span>Let</span> me tell you something you already know</div>",
                            "css": "div { line-height: 125%; font-family: \"Noto Sans\"; font-weight: 600; text-align: left; color: #dfe4ea; font-size: 55px; } span {color: #FFF;}",
                            "type": "html"
                        },
                        "offset": {
                            "y": -0.1
                        }
                    }
                ]
            },
            {
                "clips": [
                    {
                        "start": 1.5,
                        "length": 3.5,
                        "position": "center",
                        "asset": {
                            "height": 350,
                            "width": 450,
                            "html": "<div>Let me tell you something you already know</div>",
                            "css": "div { line-height: 125%; font-family: \"Noto Sans\"; font-weight: 600; text-align: left; color: #dfe4ea; font-size: 55px; } span {color: #FFF;}",
                            "type": "html"
                        },
                        "offset": {
                            "y": -0.1
                        },
                        "transition": {
                            "in": "fadeFast"
                        }
                    }
                ]
            },
            {
                "clips": [
                    {
                        "start": 0,
                        "length": 5,
                        "asset": {
                            "type": "image",
                            "src": "https://media.discordapp.net/attachments/915787846063915052/920466103535284224/rocky.png"
                        }
                    }
                ]
            }
        ]
    }
}

Ok, I see what you are doing! Let me play with it. Thank you!

1 Like

hey! super interested in this too. I think I got it more or less:

  • shorten time of each clip so it does one word by one word

The problem if I understand this correctly is that it is not scalable with various dynamic text.
Would there be any other approach? Have you implemented any other effect to animate text @dazzatron ?

This would be amazing feature for engagement on the videos rather than have a full text directly showing…

Thanks a lot

If I understand correctly, to do this dynamically, i.e. for any sentence, you would need to program that using a script, like Node, PHP, Python etc…

You would need to split the sentence in to an array of multiple parts and then loop through that array, for each word create a clip and add to the start position. Something like below, (JavaScript but not tested):

let start = 0; // the very start of the video
let delay = 0.2; // default length
let length = 5; // the time to show the whole sentence once displayed

cons clips = []; // an array to hold all the clips that get created for each word.
const words = "this is my sentence".split(" "); // split the sentence to an array of words


words.forEach((word) => {
    clips.push(.......) // create the clip here using word, start and length. You can use the SDK here or an object
    start += delay; // start the next word 0.2 seconds after the previous word
    length -= delay; // deduct 0.2 seconds from the length so all words show for the same time
});

// Add the clips array to a track, track to a timeline, etc... and POST to the API.

Something along these lines should do it.

1 Like