How to Create an OBS Studio Quiz Using Lua Script

This guide explains how to build an automated, interactive quiz system directly within OBS Studio using a custom Lua script. By leveraging OBS Studio’s built-in scripting engine, you can dynamically update Text (GDI+) sources to display questions, countdown timers, and answers for your live stream audience without relying on heavy external browser overlays.

Step 1: Set Up Text Sources in OBS Studio

Before writing or loading the script, you need to create the visual text elements in your OBS scene that the script will control.

  1. Open OBS Studio.
  2. In your active scene, click the + icon under the Sources dock.
  3. Select Text (GDI+) and name it Quiz Question.
  4. Create a second Text (GDI+) source and name it Quiz Timer.
  5. Position and style these text sources on your canvas as desired.

Step 2: Create the Lua Script

OBS Studio has a built-in Lua interpreter. Below is a lightweight, complete script that handles a simple quiz database, updates the text sources in real time, and manages a countdown timer.

Create a file named obs_quiz.lua on your computer using a text editor (like Notepad or VS Code) and paste the following code:

obs = obslua

-- Global variables
source_name_question = ""
source_name_timer = ""
current_question_index = 1
timer_seconds = 10
is_running = false

-- Quiz questions database
quiz_data = {
    {q = "What is the capital of France?", a = "Paris"},
    {q = "What is 5 + 7?", a = "12"},
    {q = "Which planet is known as the Red Planet?", a = "Mars"},
    {q = "What is the speed of light? (approx)", a = "300,000 km/s"}
}

-- Script description displayed in OBS
function script_description()
    return "An automated interactive quiz system that updates OBS text sources with questions and a timer."
end

-- Define script properties (UI controls in OBS)
function script_properties()
    local props = obs.obs_properties_create()
    
    local p_quest = obs.obs_properties_add_list(props, "question_source", "Question Source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
    local p_timer = obs.obs_properties_add_list(props, "timer_source", "Timer Source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)

    -- Populate dropdowns with text sources
    local sources = obs.obs_enum_sources()
    if sources ~= nil then
        for _, source in ipairs(sources) do
            local source_id = obs.obs_source_get_id(source)
            if source_id == "text_gdiplus" or source_id == "text_ft2_source" then
                local name = obs.obs_source_get_name(source)
                obs.obs_property_list_add_string(p_quest, name, name)
                obs.obs_property_list_add_string(p_timer, name, name)
            end
        end
    end
    obs.source_list_release(sources)

    obs.obs_properties_add_button(props, "start_btn", "Start Quiz", start_quiz)
    return props
end

-- Save selected settings
function script_update(settings)
    source_name_question = obs.obs_data_get_string(settings, "question_source")
    source_name_timer = obs.obs_data_get_string(settings, "timer_source")
end

-- Helper to update OBS text source content
function update_text_source(source_name, text)
    local source = obs.obs_get_source_by_name(source_name)
    if source ~= nil then
        local settings = obs.obs_data_create()
        obs.obs_data_set_string(settings, "text", text)
        obs.obs_source_update(source, settings)
        obs.obs_data_release(settings)
        obs.obs_source_release(source)
    end
end

-- Main timer loop
function quiz_tick()
    if timer_seconds > 0 then
        timer_seconds = timer_seconds - 1
        update_text_source(source_name_timer, "Time Left: " .. tostring(timer_seconds) .. "s")
    else
        obs.timer_remove(quiz_tick)
        local current_q = quiz_data[current_question_index]
        update_text_source(source_name_question, "Answer: " .. current_q.a)
        update_text_source(source_name_timer, "Next question soon...")
        obs.timer_add(next_question, 5000) -- Wait 5 seconds before showing next question
    end
end

-- Transition to next question
function next_question()
    obs.timer_remove(next_question)
    current_question_index = current_question_index + 1
    
    if current_question_index > #quiz_data then
        update_text_source(source_name_question, "Quiz Complete! Thanks for playing!")
        update_text_source(source_name_timer, "")
        is_running = false
    else
        timer_seconds = 10
        local current_q = quiz_data[current_question_index]
        update_text_source(source_name_question, "Q: " .. current_q.q)
        update_text_source(source_name_timer, "Time Left: 10s")
        obs.timer_add(quiz_tick, 1000)
    end
end

-- Start or restart the quiz
function start_quiz()
    current_question_index = 1
    timer_seconds = 10
    local current_q = quiz_data[current_question_index]
    
    update_text_source(source_name_question, "Q: " .. current_q.q)
    update_text_source(source_name_timer, "Time Left: 10s")
    
    obs.timer_remove(quiz_tick)
    obs.timer_remove(next_question)
    obs.timer_add(quiz_tick, 1000)
end

Step 3: Load the Script Into OBS Studio

With the script saved locally, you can now link it to OBS Studio:

  1. In OBS Studio, click on Tools in the top menu bar, then select Scripts.
  2. In the Scripts window, click the + (Add) icon at the bottom left.
  3. Locate and select your saved obs_quiz.lua file, then click Open.
  4. Once loaded, you will see configuration settings on the right panel.

Step 4: Configure and Run the Quiz

  1. In the script properties panel on the right side of the Scripts window, click the dropdown menu for Question Source and select your Quiz Question text layer.
  2. Select your Quiz Timer text layer in the Timer Source dropdown.
  3. Click the Start Quiz button to execute the code.

The script will instantly change your “Quiz Question” text to the first question in the database and begin counting down from 10 seconds. When the timer hits 0, it will display the answer for 5 seconds before pulling the next question from the quiz_data array.

Customizing Your Questions

To add your own custom questions, open the obs_quiz.lua file and locate the quiz_data table at the top. You can add as many lines as you want using this syntax:

quiz_data = {
    {q = "Your Custom Question Here?", a = "Your Answer Here"},
    {q = "Another Question?", a = "Another Answer"}
}

Save the file and click the Reload Scripts button (circular arrow icon) in the OBS Scripts window to apply your changes.