Creating Video "Stories"

January 25, 2021 - Doug in Video list, NodeJS

Apps like Snapchat and Instagram have "video stories" where the videos are visible for 24 hours, and then disappear. Stories are a great way to keep engagement, and have users regularly check in (so they do not miss a story).

In this post, we'll walk through a demo application that mimics the "story" framework. You'll see how you can easily implement a feature like stories with api.video.

Our sample code is on Github - and you can launch youer own with just an api.video API token.


We've build a demo application at storyify.a.video that will display videos that fit our "Story" parameters.

To start, we need to identify the videos we want to appear in our story timeline. In your app, you'd probably ID this by a username or groupname, either from your dyanamic metadata or perhaps with a tag.

In the demo app, I have 3 groups of videos that will appear:

  1. Saved videos from watch.a.video/broadcast livestream.
  2. Saved videos from livestream.a.video stream.
  3. The Tutorial videos from a.video. All of these tutorials are tagged with the "avideo" tag.

In practice, you're most likely to use a tagging method to sort your stories. However, we don't publish a new tutorial video daily, so it does not work well with the demo (on the other hand, the livestreams almost always have one or more video saved a day).

You can also set the period for the story. Like Instagram and Snapchat, we've set this value to 24 hours.

screenshot of form to build story

Determining the videos to display

On submittal of this form, the data appears on the NodeJS backend. This code is available on Github

	var currentTime = new Date();
	//get the values from the form to figure out which stream, and for how far backwards 
		hours = req.query.hours;
		videoStream = req.query.chooseStory;
	//we need to convert hours to ms, 3600s in an hour, 1000ms in a sec
	var hoursInMs = hours*3600*1000
	var earliestTime = new Date(currentTime - hoursInMs);

First we retrieve the current time on the server (currentTime). We then extract the number of hours, and the story chosen from the form.

Since time is measured in ms since 1970, we convert the hours our story will stay live to milliseconds, and then do a difference from the currentTime to find the beginning time for our story timeframe.

Search for videos

Now we can search for videos that fit these parameters. Our sample apps backend is Node, so we can use the NodeJS SDK video search. We'll modify the search parameters based on the story type selected by the user on the form

const client = new apiVideo.Client({ apiKey: apiVideoKey });
if (videoStream==="piLivestream"){
		// pi livestream saved videos
		 searchParameters = {currentPage: 1, pageSize: 25, sortBy: 'publishedAt', sortOrder: 'desc', liveStreamId: 'liEJzHaTzuWTSWilgL0MSJ9'};
	else if (videoStream==="foreheads"){
		// livestream a video saved videos
		//"foreheads" is a joke - most of the thumbnails are of someone's forehead
		searchParameters = {currentPage: 1, pageSize: 25, sortBy: 'publishedAt', sortOrder: 'desc', liveStreamId: 'li400mYKSgQ6xs7taUeSaEKr'};

	}else if (videoStream==="tutorials"){
		//these are video tutorials for a.video
		//tagged 'avideo'
		searchParameters= {currentPage: 1, pageSize: 25, sortBy: 'publishedAt', sortOrder: 'desc', tags: ['avideo']};


The search parameters is a JSON list of the parameters to search over: 1. We cannot search by timeframe, so I am making a guess that there will not be over 25 stories in the timeframe. 2. Videos are sorted by publishedAt, with newest videos first. 3. we use either the liveStreamId, or tags attribute to refine the videos to the ones we want.

Now we are ready to make our query:

let result =client.videos.search(searchParameters);	
		//25 most recent stories
		//let's get the ones that fit inside the "story lifetime"
		var validStories=[];
		for (var i=0;i<videoList.length;i++){
			var publishDate = new Date(videoList[i].publishedAt);
			//console.log("published", publishDate);
			if(publishDate > earliestTime){
				//any videos that match this are valid to display
				//grab the title and the iframe url
				console.log("published", publishDate);
				var iframe = "iframe src=\""+videoList[i].assets.player+"\" width=\"50%\" height=\"25%\" frameborder=\"0\" scrolling=\"no\" allowfullscreen=\true\"";
				var name = videoList[i].title;

				var data = {
					"name": name, 
		//ow we have all the videos
		//send them to the webpage
		return res.render('story', {hours, validStories});

		}).catch((err) => {

The videoList array will have the most recent 25 videos that fit our filters. We can then loop through this list, and only look for videos where the publishedAt date is greater than the earliestTime (the earliest allowed story).

For all videos that meet the story timeline criteria, we create an iframe to display the video, the created time and the title of the video. We return this array to the webpage, where the videos are listed (with their name and created date.

Here is a screenshot from my park livestream "stories"

Screenshot of park video stories

In the last 24 hours, there were 9 videos posted to the park livestream.


The idea of videos that "expire" after a certain amount of time, much like video stories in Instagram or Snapchat, can easily be enabled in your api.video based application. Using the example at storyify.a.video, and the sample code on Github, can help you get started with your video story plan.

Have you implemented something similar? Drop a link in our community forum. We've love to see what you came up with, and if you had any challenges.


Developer Evangelist

Get started now

Connect your users with videos