How to Build a Trivia App Like HQ Trivia

May 8, 2019 by


Developers are changing the mobile landscape with live-streaming apps. From HQ Trivia to TriviaWOW, these interactive apps allow users to engage like never before. Find out how to build a trivia app like HQ Trivia by watching this screencast. Andrew Riley, head of mobile development at Radiant Interactive, walks through the process.


Full Video Transcript:

Andrew Riley:

Welcome to the TriviaWOW! screen cast for the TriviaWOW! app that was designed for NAB 2019. This was brought to you by Wowza Media Systems as well as Radiant Interactive. The purpose of this app was to create, by using the metadata from a video stream, being able to have it interact with the user by manipulating the user interface. So, let’s dive right in.

From the beginning, we start the application. We will check to see if the terms and conditions are met. That was one of the requirements for this application. So, from the menu, all the controllers are set up to be a sequential. So, you’ll be starting on the landing screen and going all the way down through the application. Definitely, there are more ways to create this application by making more it granular. This was chosen to be easier for the general audience as well as to be able to pick it up quickly and not have to worry about following the trail of tons of classes.

The first screen we see is called the landing screen. When you launch it, the application initially, it will check to see if the terms and conditions are met or have been selected. If not, it’ll go to this. Following instances of launching that application will go into the log-in screen. Here’s the version of the terms. Just a scroll view. Nothing too crazy. Once selected, you’re presented with the log-in screen. This log-in screen hits a server to grab the next instance of the game ID so it’s checking when the next time interval is. From there, it creates the countdown clock with the current time with the user. Additionally, you are required to create a nickname and there is a code to check that that is set. The reason that is set instead of letting the user jump right in is just because we have a scoreboard in the application as well to make it more challenging.

Going to backtrack a little bit. This is what the term conditions screen looks like. It’s a very plain. Most of our code or UI stuff was written into storyboard just for quick and easy simplicity and to be able to see more at a high level how the screens are interacting with each other. One of the things you’ll notice within this application are a lot of the texts or UI changes are within the codebase instead of its own individual class, like a styling class. That was probably something that would change later for later additions, but it was just put it in there at the moment primarily because we’re using a custom font called Railway.

So, here’s the log-in screen as shown here on the right side as well. So, within the code, the countdown timer is initiated when it first loads. It’ll check three times. If it fails during initializing and the enter button for the game, the active game, will become highlighted or active five minutes prior to the game starting. Once the game starts, you’ll just get a message saying that the games had begun and someone can jump in mid game if needed.

So, let’s start off. We’re going to be jumping in by entering our username and I will be muting the audio from the game just to make it easier to communicate with you. So, there’s a small introduction. So, I’m going to fast forward through that and we get to question one. All the data for this question is returned to the metadata including the three answers as well as the question, the index of the question and the allotted time. Once we are given that information, we start the clock and display the information to the user.

Once the time has run out, we highlight the answer according to what the user selects. They can still change their answer until the clock goes to zero. At that time, the correct answer is displayed as well as giving the point or increasing the counter for the correct or incorrect. From there, the game just continues. Following each question, you might’ve noticed that you opened up the scoreboard. That is more for the live feed which shows the active scores that get pulled from the game server. That code is also available if you would like it. Coming to the end of the game, we get our final question, but more importantly, we have our end game metadata which, when triggered, will launch the last screen ending the game. It’s also very important that we stop the player during that time, which if we don’t, can cause odd issues.

Now that that’s done, dig into a little bit more of the code. The code is structured to where most of the IB outlets are near the top because we’re using a storyboard as well as local variables or counters following that. There are some comments to help separate them, but nothing too crazy. The lobby as well as the player can have the most, but the code is pretty much following the same. Jumping back to the lobby, it’s a pretty simple view controller. It’s basically just some text with a timer on it that just has a countdown going periodically down per second.

So, the first thing we do when we start initializing this player is to check the license key. I am not quite sure if this is required with each initializing of the player, but I found it to be very useful just to do and it didn’t have much resource need. Following that, our player starts automatically. So, once the view is started up, we start the player to go. The main things that we’re getting in this function, start play, is that for the live player, the L’s part of the FL’s, is that we have to register for each event type. All of those event types are what’s passed within the metadata, so they’re pretty easy to catch, we have to list them all out. Android is the same way.

The other part of this FL’s is for in our stand alone video, which isn’t coming from the live stream. We could put this into the GoCoder SDK as well, but we’re using a different observer called a timed metadata. Both of these functions grab the data and they are being pushed into the same functions. They just get the data initially differently.

For the most part, all of the IB actions are connected to one of the buttons on the screen, specifically the buttons that the user can press for the answers as well as the launch of the scoreboard. The functions are pretty simple going down the list. Most of them are either updating some of the metrics within the screen or resetting it for the next question. They’re pretty easy to follow along. They just go one to the other. So, if you have any questions, sequentially go down the list and hit the lives. There’s not too many so it’s pretty quick, but the main stuff that we want to get into are these functions at the very bottom. The first one is related to the player, which checks on the status of the player and we can coordinate the status label. Giving more information to the user of what is happening with the player, such as that it’s starting up or stopping. The function at the very bottom is related to the metadata. That function is what starts the whole process moving.

When an event comes through the stream, it will have an event type and we grab the event, check that it doesn’t have the same GUID as a previous one. This is because we put the metadata on a few frames just in case there’s am instance where some data gets dropped. Once that’s checked, that it wasn’t previously run, we continue on and use switch statements determining which event type it is. Depending on what it is, it will update either the question or the periodic info, which is the user counts in the toolbar. You’ll notice that show results and start game weren’t used within this code base. That’s primarily because it was used more within the back-end server, but we put them here just to be more visual and what’s all going through at certain times.

Moving on up, the first function you’ll see was the show period info. This is updating a total viewer number and further down is the ask question which updates the question information that’s passed in the metadata. The other function that we have to watch out for, or notice, is the observed value function. This is related to the video feed that’s coming in. I’m using the AV Foundation Tools or Apple’s Tools. So, we’re looking for the timed metadata specifically and so, that first line is very important. Following that, we are basically converting the data that is returned in Apple’s Styling to the stuff we want to use within the GoCoder or to have them similar so we can reuse the functions. Going into the other view controllers now, the reward is the one that you get following the game completion which is a static text homage and it just informs the user that they scored so much points or correct answers out of the total questions.

The total questions is passed along within the metadata as well. Scoreboard pretty similar as the reward. The only difference is it has a networking call, which gets the list from the game server and it gives them a little icon depending on how they are doing related to how the others within the session are doing as well. The submit view controller is our very last controller and it was a networking call that pushed more information to our servers to give more information if anyone was interested in learning more about the application during the conference. The two models that we had to deal with are game and player. This is because the game is what do we get back in our lobby controller when we are trying to figure out what the start time is. So, we hit the lobby controller, it returns a game object and we use that information to have a game ID, as well as the gained time to calculate all that.

The reason we need that is because the game ID is used in an additional networking calls such as submitting answers to the survey or the game or sorry, submitting answers to the server for that game session. When you create a new player or when you enter your new username, that player is unique to one person. We didn’t have it to where you can have multiple players having the same username. So, that nickname which you signed in was unique. If you didn’t have an unique one, we threw back in error, which tells you to add in a new nickname and player is the other type that we use because it’s used in some of the networking calls as well. So, the settings bundle helper or something, I added in there just to be a little bit more friendly without having to dig into the code and you can modify the settings without getting too far into the Kobe’s to launch your own application. So, basically, it’s tying into the setting’s dot bundle file which can be accessed through the settings menu.

So, here’s a view of the storyboard, which has a lot of arrows. Yes, but it’s not as complete as you think. They basically just all returned to the lobby screen following exits or returning. So, for the most part it’s pretty singular directions with all of them returning to the lobby. The pods we use for this were Alamofire as well as SwiftDate. These could be removed. They ran it in just for simplicity sake because dates can be a little annoying to work with within code, especially when we are dealing with different time zones. Alamofire was just a way to have it simplify the networking layer as well. If you have any questions regarding this code or you want to learn more about Wowza’s services, go to Thank you.


Get the Sample Code

Interactive App Resources