Youβre now subscribed to the Twelve Labs Newsletter! You'll be getting the latest news and updates in video understanding.
Oh no, something went wrong. Please try again.
Introduction
Imagine a world where every video becomes an interactive quiz, effortlessly transforming passive viewing into active learning π
In this tutorial, we'll explore the Video Content Quiz Generator, an application designed to revolutionize the learning experience associated with video content. Powered by Twelve Labs, this video-based tool automatically generates Multiple Choice Questions (MCQs) from video content, enhancing both learning and assessment.
Whether you're an educator seeking quick assessments or a content creator aiming to boost engagement, the Video Content MCQ Generator is your ally in fostering active learning.
Find the repository for the notebooks and this application on GitHub.
How the Application Works
This section outlines the application flow for developing the video content quiz (MCQ) generator using Twelve Labs.
The process begins when a user uploads video or educational content, which is then transformed into an active quiz assessment. After upload, the video is indexed on a specific index created during setup. Indexing is performed using Marengo 2.6 (Embedding Engine). Once indexed, the video content is converted into MCQs using the open-ended prompt functionality in Pegasus 1.1 (Generative Engine).
The prompt assigns the role of an educational video analyzer, tasked with generating quiz questions and correct answers. These are used to evaluate user responses based on the indexed video, following a specified format. After a user submits an answer, the application provides a score and the correct answer. A reset button allows users to start over.
Preparation Steps
There are two ways to create the index: through the Twelve Labs Playground or using provided code snippets. We'll discuss both methods. To prepare the index ID from the playground, follow these steps:
Create a new index by calling client.index with the Index name and engine configuration parameters. Use a unique and identifiable name for the Index.
index = client.index.create(
name="<YOUR_INDEX_NAME>",
engines=engines
)
print(f"A new index has been created: Index id={index.id} name={index.name} engines={index.engines}")
The index.id field represents the unique identifier of your new index. This identifier is crucial for indexing videos in their correct location.
With these steps completed, you're now ready to develop the application!
β
Walkthrough for Video Content Quiz Generator
In this tutorial, we will build a Streamit application with a minimal frontend. Below is the directory structure to be followed:
After completing the previous steps, it's time to build the Streamlit application. This app offers a straightforward way to upload a video and convert it into a multiple-choice quiz assessment. The application comprises two files:
app.py: Contains the application flow with a minimal page layout
utils.py: Contains all the utility functions essential for the application's operation
β
1 - Setting up the utility function for the operation
In this section, we'll explore how to set up the utility function using the Twelve Labs SDK to transform video content into interactive learning experiences. This AI-powered system enables educators and content creators to craft engaging assessments based on visual content by automating video analysis and quiz generation. The code combines video indexing and custom prompt engineering to generate relevant multiple-choice questions from any uploaded video, making it a versatile tool for creating interactive learning materials.
# Import the necessary libraries
import json
import tempfile
import os
from twelvelabs import TwelveLabs
from twelvelabs.models.task import Task
import re
from dotenv import load_dotenv
load_dotenv()
# Get the API Key from the Dashboard - https://playground.twelvelabs.io/dashboard/api-key
API_KEY = os.getenv("API_KEY")
# Create the INDEX ID as specified in the README.md and get the INDEX_ID
INDEX_ID = os.getenv("INDEX_ID")
# Initialize the Twelve Labs client
client = TwelveLabs(api_key=API_KEY)
# Create a temporary directory for uploaded files
UPLOAD_DIR = tempfile.mkdtemp()
def create_task(file_path):
# Create a new task for video indexing
return client.task.create(
index_id=INDEX_ID,
file=file_path,
)
def on_task_update(task: Task):
# Callback function to print task status updates
print(f" Status={task.status}")
def wait_for_task(task):
# Wait for the indexing task to complete
task.wait_for_done(sleep_interval=5, callback=on_task_update)
if task.status != "ready":
raise RuntimeError(f"Indexing failed with status {task.status}")
return task.video_id
def generate_mcq(video_id):
# Prompt to generate the multiple choice questions based on video content
prompt = """You're Educational Content Analyzer, and you are tasked to prepare the three Multiple Choice Questions based on the video content and the concept which is been discussed by the speaker or shown. The difficulty of the question should also gradually increase.
The response should be in the json format where there is Q1, Q2, and Q3. Each section would contain the question with options in question and the correct_answer"""
# Twelve Labs SDK to generate text based on the video content
gist_r = client.generate.text(
video_id=video_id,
prompt=prompt
)
return gist_r.data
def parse_json_with_regex(text):
# Extract and parse JSON content from the response
match = re.search(r'\{[\s\S]*\}', text)
if match:
json_str = match.group(0)
try:
return json.loads(json_str)
except json.JSONDecodeError:
# Return None if JSON parsing fails
return None
else:
# Return None if no JSON like content is found
return None
def save_uploaded_file(uploaded_file):
# Save the uploaded file to the temporary directory
file_path = os.path.join(UPLOAD_DIR, uploaded_file.name)
with open(file_path, "wb") as f:
f.write(uploaded_file.getbuffer())
return file_path
# Calculate the user's score based on their answers
def calculate_score(user_answers, questions):
return sum(answer == questions[q_num]["correct_answer"] for q_num, answer in user_answers.items())
First, we import the necessary modules, including json, tempfile, os, and the Twelve Labs SDK, along with the API Key and Index ID environment variables.
The create_task(file_path) method initiates a new video indexing task using the Twelve Labs SDK. It returns the work object for the indexing application. A callback function, on_task_update(task: Task), prints status updates for the indexing task. Once the status becomes "ready" and returns the video_id, the generate_mcq(video_id) function is triggered.
The generate_mcq(video_id) function generates multiple-choice questions based on the indexed content using Pegasus 1.1. The prompt defines the model's role, objective, and output format. The result is then parsed using parse_json_with_regex(text).
The calculate_score(user_answers, questions) function computes the user's score based on their answers and returns the total score when the user clicks the submit button in the next section.
β
2. Instruction Flow of the Streamlit Application [app.py]
2.1 Quiz Assessment Instruction Flow
As mentioned earlier, app.py contains the proper flow of instructions for the Streamlit application, utilizing the utility functions from utils.py. This section focuses on the function and flow of the quiz assessment and scoring system.
# Import the necessary libraries and functions
import streamlit as st
from utils import create_task, wait_for_task, generate_mcq, parse_json_with_regex, save_uploaded_file, calculate_score
def upload_and_index():
# Minimal custom HTML and CSS
st.markdown("""
<h1 style='text-align: center; color: #2c3e50; font-size: 36px; font-weight: bold; margin-bottom: 30px;'>
πΉ Video Content Quiz Generator
</h1>
""", unsafe_allow_html=True)
st.write("Upload a video to start the quiz generation process and test yourself!")
# # Check if a video has already been indexed
if 'video_id' in st.session_state and st.session_state.video_id:
st.info("Video already indexed. Next, Proceeding to quiz generation.")
return generate_quiz()
# File uploader for video files
uploaded_file = st.file_uploader("Choose a video file", type=['mp4'])
if uploaded_file is not None:
# Save the uploaded file
file_path = save_uploaded_file(uploaded_file)
st.success("File uploaded successfully!")
# To proceed witht the indexing of the video
with st.spinner("Indexing video... Please wait"):
task = create_task(file_path)
video_id = wait_for_task(task)
st.success("Video indexed successfully!")
st.session_state.video_id = video_id
return generate_quiz()
# Utility function to generate the quiz questions based on the indexed video
def generate_quiz():
with st.spinner("Generating quiz questions..."):
raw_response = generate_mcq(st.session_state.video_id)
questions = parse_json_with_regex(raw_response)
if questions:
st.session_state.questions = questions
st.session_state.page = "quiz"
st.experimental_rerun()
else:
st.error("Failed to generate quiz questions. Please try again.")
def quiz():
st.title("π Video Content Quiz")
st.write("Answer the following questions based on the video content -")
questions = st.session_state.questions
# # Initialize user answers if not already done
if 'user_answers' not in st.session_state:
st.session_state.user_answers = {q_num: None for q_num in questions}
if 'submitted' not in st.session_state:
st.session_state.submitted = False
# Display the questions and answer options
for q_num, q_data in questions.items():
with st.container():
st.subheader(f"Question {q_num[-1]}")
st.write(q_data["question"])
answer = st.radio(
f"Select your answer for Question {q_num[-1]}:",
options=q_data["options"],
key=f"select_{q_num}",
index=q_data["options"].index(st.session_state.user_answers[q_num]) if st.session_state.user_answers[q_num] else 0,
on_change=update_answer,
args=(q_num,)
)
st.markdown("---")
# Submit quiz button
col1, col2, col3 = st.columns([1, 2, 1])
with col2:
submit_button = st.button("Submit Quiz π", key="submit_quiz", use_container_width=True)
if submit_button:
submit_quiz()
st.balloons()
# Display results if quiz is submitted
if st.session_state.submitted:
display_results()
start_over_button = st.button("Start Over π", key="start_over", use_container_width=True)
if start_over_button:
reset_state()
def update_answer(q_num):
# Session state, to update the user's answer
st.session_state.user_answers[q_num] = st.session_state[f"select_{q_num}"]
def submit_quiz():
# On the submission button, mark quiz as submitted and calculate score
st.session_state.submitted = True
st.session_state.score = calculate_score(st.session_state.user_answers, st.session_state.questions)
def display_results():
# To display the user's score
st.success(f"π Your score: {st.session_state.score} out of {len(st.session_state.questions)}")
# Display the correct results for each question
for q_num, q_data in st.session_state.questions.items():
with st.expander(f"Question {q_num[-1]} Details"):
st.write(f"**Your answer:** {st.session_state.user_answers[q_num]}")
st.write(f"**Correct answer:** {q_data['correct_answer']}")
if st.session_state.user_answers[q_num] == q_data['correct_answer']:
st.success("Correct! π")
else:
st.error("Incorrect β")
def reset_state():
# Clear all session state variables
for key in list(st.session_state.keys()):
del st.session_state[key]
st.experimental_rerun()
This part of the Streamlit application focuses on generating quizzes from video content and managing quiz interactions.
The upload_and_index() function utilizes the Twelve Labs SDK for video uploading and indexing. Once indexing is complete, the quiz generation process begins.
To generate quiz questions, the function uses the 'video_id' of the indexed video. It then calls generate_mcq() followed by parse_json_with_regex(), as previously discussed. This process creates the Quiz Questions and Answers. Upon successful generation, the quiz page is displayed.
The quiz() function presents the generated quiz and handles user interactions, including answer selection and quiz submission. A "Start Over" option is provided after submission. Several utility functions manage quiz interactions:
update_answer() updates the user's response for a specific question.
submit_quiz() processes quiz submission and calculates the score.
display_results() shows the quiz results, including the score and correct answers.
reset_state() clears all session state variables to restart the quiz.
β
2.2 Streamlit Session State and Custom CSS
The main function in the app.py package configures the Streamlit page and applies custom CSS. It sets the background image, styles buttons, and determines the overall look of the application. It also initializes the session state.
Serving as the entry point for launching the Streamlit application, the main() function sets up a page with a title and uses a wide layout for better space utilization. Custom CSS enhances visual appeal by stylizing the background, buttons, radio buttons, and expanders, while reducing the opacity of headings.
To manage navigation between different sections of the app, a session state variable 'page' is initialized. It's set to "upload" by default if not already defined.
The application renders various pages based on its current state using conditional statements:
"upload" β Calls the upload_and_index() function for the video upload interface.
"quiz" β Calls the quiz() function to display the generated quiz.
Here's a demo quiz generated after uploading and indexing the video content on the PCA topic:
Explore further by experimenting with the open-ended prompt and Pegasus 1.1, powered by Twelve Labs.
β
More Ideas to Experiment with the Tutorial
Understanding how an application works and its development process empowers you to implement innovative ideas and create products that meet users' needs. Here are some use cases similar to the tutorial blog:
ποΈ Self-Paced Learning: Students can generate questions to test their understanding of video lessons.
π Educational Assessment: Teachers can quickly create quizzes based on lecture videos or educational content.
π’οΈ Corporate Training: Organizations can enhance their video-based training programs with automated assessments tailored to different learners.
π¬ Content Engagement: Video content creators, including YouTubers, can increase engagement by providing interactive quizzes for their content.
π§ Memory Retention: Users can reinforce their learning by answering questions generated from informational videos.
β
Conclusion
This blog post offers a comprehensive explanation of the working procedure and development of the video content quiz generator using Twelve Labs. We appreciate you following along with the tutorial and look forward to your ideas on improving the user experience and addressing various challenges.
β
Additional Resources
To deepen your understanding of the engines used for the generation task, check out Marengo 2.6 (Embedding Engine) and Pegasus 1.1 (Generator Engine). To further explore Twelve Labs and enhance your grasp of video content analysis, consider these valuable resources:
Discord Community: Join our vibrant community of developers and enthusiasts to discuss ideas, ask questions, and share your projects.
Sample Applications: Explore a variety of sample applications to inspire your next project or learn new implementation techniques.
Explore Tutorials: Dive deeper into Twelve Labs capabilities with our comprehensive tutorials.
We encourage you to leverage these resources to expand your knowledge and create innovative applications using Twelve Labs' video understanding technology.
Learn how to build a semantic video search engine with the powerful integration of Twelve Labs' Embed API with ApertureDB for advanced semantic video search.
Whether you're looking to find the perfect berry-toned lipstick or just curious about spotting specific colors in your videos, this guide will help you leverage cutting-edge AI to do so effortlessly.
Leverage Twelve Labs Embed API and LanceDB to create AI applications that can process and analyze video content with unprecedented accuracy and efficiency.