
チュートリアル
Twelve Labsを用いたビデオコンテンツクイズジェネレーターの構築

リシケシュ・ヤダフ
このチュートリアルでは、Twelve Labs Pegasusモデルを使用してインデックス化されたビデオから多肢選択式質問(MCQ)を自動生成する「ビデオコンテンツMCQジェネレーター」の構築手順を解説します。このジェネレーターは、ビデオのアップロード、質問への回答、および採点結果の表示を行うためのStreamlitインターフェースを備えています。
このチュートリアルでは、Twelve Labs Pegasusモデルを使用してインデックス化されたビデオから多肢選択式質問(MCQ)を自動生成する「ビデオコンテンツMCQジェネレーター」の構築手順を解説します。このジェネレーターは、ビデオのアップロード、質問への回答、および採点結果の表示を行うためのStreamlitインターフェースを備えています。

この記事の内容
No headings found on page
ニュースレターに登録する
ニュースレターに登録する
ビデオ理解に関する最新の技術進歩、チュートリアル、業界の動向をお届けします
ビデオ理解に関する最新の技術進歩、チュートリアル、業界の動向をお届けします
AIを活用してビデオを検索、分析、探索します。
2024/10/04
13分
記事へのリンクをコピー
すべての動画がインタラクティブなクイズに変わり、受動的な視聴を能動的な学習へと簡単に変化させる世界を想像してみてください 🎓
このチュートリアルでは、動画コンテンツに関連する学習体験に革命を起こすために設計されたアプリケーション「Video Content Quiz Generator」について説明します。Twelve Labsの技術を活用したこの動画ベースのツールは、動画コンテンツから多肢選択式クイズ(MCQ)を自動的に生成し、学習と評価の双方を向上させます。
迅速な評価方法を求めている教育関係者の方でも、エンゲージメントの向上を目指すコンテンツクリエイターの方でも、Video Content MCQ Generatorは能動的な学習を促進するための強力な味方になります。
アプリケーションのデモはこちらからお試しいただけます:Video Content MCQ Generator。また、こちらのReplitテンプレートから実際に使ってみることができます。
前提条件
Twelve Labs Playgroundにサインアップして、APIキーを生成してください。
ノートブックとこのアプリケーションのリポジトリはGitHubで公開されています。

アプリケーションの仕組み
このセクションでは、Twelve Labsを使用して動画コンテンツクイズ(MCQ)ジェネレーターを開発するためのアプリケーションの処理フローの概要を説明します。
プロセスは、ユーザーが動画や教育用コンテンツをアップロードすることから始まり、それが能動的なクイズ評価へと変換されます。アップロードされた動画は、セットアップ中に作成された特定のインデックスにインデックス登録されます。インデックス登録にはMarengo 2.6(エンベディングエンジン)が使用されます。インデックス登録が完了すると、Pegasus 1.1(生成エンジン)のオープンエンドプロンプト機能を使用して、動画コンテンツが多肢選択式クイズ(MCQ)に変換されます。
プロンプトは、教育用動画アナライザーの役割を割り当て、クイズの問題と正解を作成します。これらは、インデックス登録された動画に基づいて、指定された指示フォーマットに従ってユーザーの回答を評価するために使用されます。ユーザーが回答を送信すると、アプリケーションはスコアと正解を表示します。リセットボタンを押すことで、ユーザーは最初からやり直すことができます。

準備手順
インデックスを作成する方法は2つあります。Twelve Labs Playgroundを使用する方法と、提供されているコードスニペットを使用する方法です。両方の方法について解説します。PlaygroundからインデックスIDを準備するには、以下の手順に従ってください。
Twelve Labs Playgroundに登録し、インデックスを作成します。
インデックスに対して以下の動画理解(Video Understanding)エンジンを有効にします(これらのエンジンは、高度な動画理解の強固な基盤を提供します)。
Marengo 2.6(エンベディングエンジン):動画検索および分類用
Pegasus 1.1(生成エンジン):動画からテキストへの生成用

Twelve Labs PlaygroundからAPIキーを取得します。
ステップ1で作成したインデックスを開き、INDEX_IDを取得します。IDはURLに含まれています:https://playground.twelvelabs.io/indexes/{index_id}
APIキーとINDEX_IDを、メインファイルと一緒に.envファイルに設定します。
Twelvelabs_API=your_api_key_here API_URL=your_api_url_here
コードベースのアプローチをお好みの場合は、以下の手順に従ってください。
Twelve Labs PlaygroundからAPIキーを取得し、環境変数を準備します。
Twelve Labs SDKと環境変数をインポートします。環境変数から取得したTwelve Labs APIキーを使用して、SDKクライアントを初期化します。
from twelvelabs import TwelveLabs from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("API_KEY") client = TwelveLabs(api_key=API_KEY)
生成タスクに使用するエンジンを指定します:
engines = [ { "name": "marengo2.6", "options": ["visual", "conversation", "text_in_video", "logo"] }, { "name": "pegasus1.1", "options": ["visual", "conversation"] } ]
インデックス名とエンジン構成パラメータを指定して
client.index.createを呼び出し、新しいインデックスを作成します。インデックスには、一意で識別しやすい名前を使用してください。
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}")
index.id フィールドは、新しいインデックスの一意の識別子を表します。この識別子は、動画を正しい場所にインデックス登録するために不可欠です。
これらの手順が完了したら、アプリケーションを開発する準備は万端です!
Video Content Quiz Generatorの構成解説
このチュートリアルでは、最小限のフロントエンドを持つStreamlitアプリケーションを構築します。以下のディレクトリ構造に従って作成してください:
. ├── app.py ├── requirements.txt ├── utils.py ├── .env └── .gitignore
前の手順を終えたら、いよいよStreamlitアプリケーションを構築します。このアプリは、動画をアップロードして、それを選択式のクイズ評価に変換するシンプルな方法を提供します。アプリケーションは主に以下の2つのファイルで構成されます:
1 - 動作に必要なユーティリティ関数の設定
このセクションでは、Twelve Labs SDKを使用して、動画コンテンツをインタラクティブな学習体験に変換するためのユーティリティ関数をセットアップする方法を探ります。このAI搭載システムにより、教育者やコンテンツクリエイターは、自動化された動画分析とクイズ生成を用いることで、視覚的コンテンツに基づいたエンゲージングな評価問題を作成できます。このコードは、動画のインデックス作成とカスタムプロンプトエンジニアリングを組み合わせることで、アップロードされたあらゆる動画から関連性の高い選択式クイズを自動生成し、インタラクティブな教材を作成するための汎用的なツールを提供します。
# 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())
まず、json、tempfile、os、および Twelve Labs SDK を含む必要なモジュールを、APIキーおよびインデックスIDの環境変数とともにインポートします。
create_task(file_path)メソッドは、Twelve Labs SDKを利用して新しい動画インデックス登録タスクを作成します。これによりインデックス作成アプリケーション用のタスクオブジェクトが返されます。コールバック関数on_task_update(task: Task)は、インデックス作成タスクのステータス更新を標準出力に表示します。ステータスが「ready」になり、video_id が返されると、generate_mcq(video_id)関数がトリガーされます。generate_mcq(video_id)関数は、Pegasus 1.1を使用して、インデックス登録された動画コンテンツに基づいて多肢選択式の質問を生成します。プロンプトは、モデルの役割、目的、および出力形式を定義します。その後、その結果はparse_json_with_regex(text)を使用してパースされます。calculate_score(user_answers, questions)関数は、ユーザーの解答に基づいてスコアを算出し、次のセクションでユーザーが送信ボタンをクリックしたときに合計点数を返します。
2. Streamlitアプリケーションの処理フロー
2.1 クイズ評価の処理フロー
前述の通り、app.py には utils.py のユーティリティ関数を使用した Streamlit アプリケーションの適切な処理フローが含まれています。このセクションでは、クイズ評価と採点システムの機能およびフローに焦点を当てます。
# 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()
Streamlit アプリケーションのこの部分は、動画コンテンツからのクイズ生成と、クイズ開始後のインタラクション管理を担当します。
upload_and_index() 関数は、Twelve Labs SDK を利用して動画のアップロードとインデックス作成を実行します。インデックス作成が完了すると、クイズ生成の処理が開始されます。
クイズ問題を自動生成するために、関数はインデックスされた動画の 'video_id' を使用します。そして、前述したように generate_mcq() を呼び出した後に parse_json_with_regex() を呼び出します。このプロセスによってクイズの問題が作成されます。生成が成功すると、クイズページが表示されます。
quiz() 関数は生成されたクイズを表示し、解答の選択やクイズの送信といったユーザーの操作を処理します。送信後には、**「最初からやり直す(Start Over)」** オプションが提供されます。クイズのやり取りを管理するために、いくつかのユーティリティ関数が用意されています:
update_answer()は、特定の質問に対するユーザーの回答を更新します。submit_quiz()は、クイズ送信の完了処理とスコア計算を行います。display_results()は、スコアや正解を含むクイズ結果画面を表示します。reset_state()は、クイズを最初からやり直すために、すべてのセッション状態変数をクリアします。
2.2 Streamlitのセッション状態(Session State)とカスタムCSS
app.py パッケージの main 関数は、Streamlit ページの設定を行い、カスタムCSSを適用します。背景画像の設定、ボタンの装飾、そしてアプリケーション全体のビジュアルの外観を決定します。また、セッション状態の初期化も行います。
def main(): # Set up the Streamlit page configuration st.set_page_config(page_title="QnA Generator", page_icon="🎥", layout="wide") # Custom CSS st.markdown(""" <style> .stApp { background-color: #f0f2f6; } .stButton > button { background-color: #4CAF50; color: white; font-weight: bold; border-radius: 30px; padding: 15px 30px; font-size: 18px; transition: all 0.3s ease 0s; border: none; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } .stButton > button:hover { background-color: #45a049; box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15); transform: translateY(-2px); } .stButton > button:active { transform: translateY(0px); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .stRadio > label { background-color: #e1e5eb; padding: 12px; border-radius: 8px; margin-bottom: 12px; transition: all 0.2s ease 0s; cursor: pointer; } .stRadio > label:hover { background-color: #d0d4d9; transform: translateY(-2px); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } .stExpander { background-color: #ffffff; border-radius: 15px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); margin-bottom: 20px; } h1 { color: #2c3e50; font-size: 36px; font-weight: bold; margin-bottom: 20px; } h2, h3 { color: #34495e; } .stAlert { border-radius: 10px; font-weight: bold; } .stSpinner > div { border-color: #4CAF50 !important; } [data-testid="stAppViewContainer"] { background-image: url("https://img.freepik.com/free-photo/vivid-blurred-colorful-wallpaper-background_58702-3508.jpg?size=626&ext=jpg"); background-size: cover; } [data-testid="stHeader"] { background-color: rgba(0,0,0,0); } [data-testid="stToolbar"] { right: 2rem; background-image: url(""); background-size: cover; } </style> """, unsafe_allow_html=True) # Initialize the page state if not already set if 'page' not in st.session_state: st.session_state.page = "upload" # To show the appropriate page based on the current state if st.session_state.page == "upload": upload_and_index() elif st.session_state.page == "quiz": quiz() if __name__ == "__main__": main()
Streamlit アプリケーションを起動するエントリポイントとして機能する main() 関数は、タイトル付きのページを設定し、スペースを有効活用するためにワイドレイアウトを使用します。カスタムCSSは、背景、ボタン、ラジオボタン、エクスパンダーのスタイルを整え、意図したデザインへと引き締めて視覚的な魅力を向上させます。
アプリの異なるファイル/セクション間のナビゲーションを管理するために、セッション状態変数 'page' が初期化されます。定義されていない場合、デフォルトで "upload" に設定されます。
アプリケーションは、条件分岐に従い、現在の状態に基づいて適切なページを描画します:
"upload" — 動画アップロードインターフェース用の
upload_and_index()関数を呼び出します。"quiz" — 生成されたクイズを表示するために
quiz()関数を呼び出します。
以下は、PCA(主成分分析)に関する動画コンテンツをアップロードし、インデックスを作成した後に自動生成されたデモクイズの様子です:

Twelve Labsが提供するオープンエンドプロンプトと Pegasus 1.1 をさらに試して、探索してみてください。
このチュートリアルからさらに一歩進めるためのアイデア
アプリケーションの仕組みと開発プロセスを理解すれば、革新的なアイデアを形にし、ユーザーのニーズを満たすプロダクトを作成できるようになります。このチュートリアルブログと同様のユースケースを提案します:
📚️ マイペース学習(Self-Paced Learning):生徒が動画レッスンの理解度をテストするための問題を独自に作成できます。
🎓 教育評価(Educational Assessment):教師は講義動画や教材コンテンツに基づく学習クイズを素早く作成できます。
🏢️ 企業研修(Corporate Training):組織は、さまざまな重要ステップに対応する自動評価クイズを組み込むことで、動画ベースの研修プログラムを強化できます。
🎬 コンテンツへのエンゲージメント(Content Engagement):YouTuberなどの動画クリエイターは、動画に連動したクイズを提供することで、視聴者のエンゲージメントを高めることができます。
🧠 記憶定着(Memory Retention):情報動画から生成された質問に回答することで、学習した知識をしっかりと記憶に定着させることができます。
結論
このブログ記事では、Twelve Labsを使用した動画コンテンツクイズジェネレーターの動作手順と開発プロセスについて包括的に解説しました。チュートリアルにお付き合いいただきありがとうございます。ユーザー体験の向上、そして様々な課題を解決するような皆さんの魅力的なアイデアを楽しみにしています。
追加リソース
自動生成タスクに使用されるエンジンの詳細を理解するには、Marengo 2.6(エンベディングエンジン)およびPegasus 1.1(ジェネレーターエンジン)を参照してください。Twelve Labsをさらに深く知り、動画コンテンツ分析の理解を広げるには、以下の情報が役立ちます:
Discordコミュニティ:開発者や熱心なメンバーが集まる活発なコミュニティに参加して、アイデアを議論したり、質問をしたり、プロジェクトを共有したりしましょう。
サンプルアプリ一覧:様々なサンプルアプリケーションを調べて、次のプロジェクトのインスピレーションを得たり、新しい実装テクニックを学びましょう。
チュートリアルを調べる:包括的なチュートリアルを通じて、Twelve Labsで何ができるのか、その機能をさらに深く体験してください。
これらのリソースを積極的に活用し、知識を広げ、Twelve Labsの動画理解技術を活用した革新的なアプリケーションを構築してみてください。
すべての動画がインタラクティブなクイズに変わり、受動的な視聴を能動的な学習へと簡単に変化させる世界を想像してみてください 🎓
このチュートリアルでは、動画コンテンツに関連する学習体験に革命を起こすために設計されたアプリケーション「Video Content Quiz Generator」について説明します。Twelve Labsの技術を活用したこの動画ベースのツールは、動画コンテンツから多肢選択式クイズ(MCQ)を自動的に生成し、学習と評価の双方を向上させます。
迅速な評価方法を求めている教育関係者の方でも、エンゲージメントの向上を目指すコンテンツクリエイターの方でも、Video Content MCQ Generatorは能動的な学習を促進するための強力な味方になります。
アプリケーションのデモはこちらからお試しいただけます:Video Content MCQ Generator。また、こちらのReplitテンプレートから実際に使ってみることができます。
前提条件
Twelve Labs Playgroundにサインアップして、APIキーを生成してください。
ノートブックとこのアプリケーションのリポジトリはGitHubで公開されています。

アプリケーションの仕組み
このセクションでは、Twelve Labsを使用して動画コンテンツクイズ(MCQ)ジェネレーターを開発するためのアプリケーションの処理フローの概要を説明します。
プロセスは、ユーザーが動画や教育用コンテンツをアップロードすることから始まり、それが能動的なクイズ評価へと変換されます。アップロードされた動画は、セットアップ中に作成された特定のインデックスにインデックス登録されます。インデックス登録にはMarengo 2.6(エンベディングエンジン)が使用されます。インデックス登録が完了すると、Pegasus 1.1(生成エンジン)のオープンエンドプロンプト機能を使用して、動画コンテンツが多肢選択式クイズ(MCQ)に変換されます。
プロンプトは、教育用動画アナライザーの役割を割り当て、クイズの問題と正解を作成します。これらは、インデックス登録された動画に基づいて、指定された指示フォーマットに従ってユーザーの回答を評価するために使用されます。ユーザーが回答を送信すると、アプリケーションはスコアと正解を表示します。リセットボタンを押すことで、ユーザーは最初からやり直すことができます。

準備手順
インデックスを作成する方法は2つあります。Twelve Labs Playgroundを使用する方法と、提供されているコードスニペットを使用する方法です。両方の方法について解説します。PlaygroundからインデックスIDを準備するには、以下の手順に従ってください。
Twelve Labs Playgroundに登録し、インデックスを作成します。
インデックスに対して以下の動画理解(Video Understanding)エンジンを有効にします(これらのエンジンは、高度な動画理解の強固な基盤を提供します)。
Marengo 2.6(エンベディングエンジン):動画検索および分類用
Pegasus 1.1(生成エンジン):動画からテキストへの生成用

Twelve Labs PlaygroundからAPIキーを取得します。
ステップ1で作成したインデックスを開き、INDEX_IDを取得します。IDはURLに含まれています:https://playground.twelvelabs.io/indexes/{index_id}
APIキーとINDEX_IDを、メインファイルと一緒に.envファイルに設定します。
Twelvelabs_API=your_api_key_here API_URL=your_api_url_here
コードベースのアプローチをお好みの場合は、以下の手順に従ってください。
Twelve Labs PlaygroundからAPIキーを取得し、環境変数を準備します。
Twelve Labs SDKと環境変数をインポートします。環境変数から取得したTwelve Labs APIキーを使用して、SDKクライアントを初期化します。
from twelvelabs import TwelveLabs from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("API_KEY") client = TwelveLabs(api_key=API_KEY)
生成タスクに使用するエンジンを指定します:
engines = [ { "name": "marengo2.6", "options": ["visual", "conversation", "text_in_video", "logo"] }, { "name": "pegasus1.1", "options": ["visual", "conversation"] } ]
インデックス名とエンジン構成パラメータを指定して
client.index.createを呼び出し、新しいインデックスを作成します。インデックスには、一意で識別しやすい名前を使用してください。
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}")
index.id フィールドは、新しいインデックスの一意の識別子を表します。この識別子は、動画を正しい場所にインデックス登録するために不可欠です。
これらの手順が完了したら、アプリケーションを開発する準備は万端です!
Video Content Quiz Generatorの構成解説
このチュートリアルでは、最小限のフロントエンドを持つStreamlitアプリケーションを構築します。以下のディレクトリ構造に従って作成してください:
. ├── app.py ├── requirements.txt ├── utils.py ├── .env └── .gitignore
前の手順を終えたら、いよいよStreamlitアプリケーションを構築します。このアプリは、動画をアップロードして、それを選択式のクイズ評価に変換するシンプルな方法を提供します。アプリケーションは主に以下の2つのファイルで構成されます:
1 - 動作に必要なユーティリティ関数の設定
このセクションでは、Twelve Labs SDKを使用して、動画コンテンツをインタラクティブな学習体験に変換するためのユーティリティ関数をセットアップする方法を探ります。このAI搭載システムにより、教育者やコンテンツクリエイターは、自動化された動画分析とクイズ生成を用いることで、視覚的コンテンツに基づいたエンゲージングな評価問題を作成できます。このコードは、動画のインデックス作成とカスタムプロンプトエンジニアリングを組み合わせることで、アップロードされたあらゆる動画から関連性の高い選択式クイズを自動生成し、インタラクティブな教材を作成するための汎用的なツールを提供します。
# 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())
まず、json、tempfile、os、および Twelve Labs SDK を含む必要なモジュールを、APIキーおよびインデックスIDの環境変数とともにインポートします。
create_task(file_path)メソッドは、Twelve Labs SDKを利用して新しい動画インデックス登録タスクを作成します。これによりインデックス作成アプリケーション用のタスクオブジェクトが返されます。コールバック関数on_task_update(task: Task)は、インデックス作成タスクのステータス更新を標準出力に表示します。ステータスが「ready」になり、video_id が返されると、generate_mcq(video_id)関数がトリガーされます。generate_mcq(video_id)関数は、Pegasus 1.1を使用して、インデックス登録された動画コンテンツに基づいて多肢選択式の質問を生成します。プロンプトは、モデルの役割、目的、および出力形式を定義します。その後、その結果はparse_json_with_regex(text)を使用してパースされます。calculate_score(user_answers, questions)関数は、ユーザーの解答に基づいてスコアを算出し、次のセクションでユーザーが送信ボタンをクリックしたときに合計点数を返します。
2. Streamlitアプリケーションの処理フロー
2.1 クイズ評価の処理フロー
前述の通り、app.py には utils.py のユーティリティ関数を使用した Streamlit アプリケーションの適切な処理フローが含まれています。このセクションでは、クイズ評価と採点システムの機能およびフローに焦点を当てます。
# 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()
Streamlit アプリケーションのこの部分は、動画コンテンツからのクイズ生成と、クイズ開始後のインタラクション管理を担当します。
upload_and_index() 関数は、Twelve Labs SDK を利用して動画のアップロードとインデックス作成を実行します。インデックス作成が完了すると、クイズ生成の処理が開始されます。
クイズ問題を自動生成するために、関数はインデックスされた動画の 'video_id' を使用します。そして、前述したように generate_mcq() を呼び出した後に parse_json_with_regex() を呼び出します。このプロセスによってクイズの問題が作成されます。生成が成功すると、クイズページが表示されます。
quiz() 関数は生成されたクイズを表示し、解答の選択やクイズの送信といったユーザーの操作を処理します。送信後には、**「最初からやり直す(Start Over)」** オプションが提供されます。クイズのやり取りを管理するために、いくつかのユーティリティ関数が用意されています:
update_answer()は、特定の質問に対するユーザーの回答を更新します。submit_quiz()は、クイズ送信の完了処理とスコア計算を行います。display_results()は、スコアや正解を含むクイズ結果画面を表示します。reset_state()は、クイズを最初からやり直すために、すべてのセッション状態変数をクリアします。
2.2 Streamlitのセッション状態(Session State)とカスタムCSS
app.py パッケージの main 関数は、Streamlit ページの設定を行い、カスタムCSSを適用します。背景画像の設定、ボタンの装飾、そしてアプリケーション全体のビジュアルの外観を決定します。また、セッション状態の初期化も行います。
def main(): # Set up the Streamlit page configuration st.set_page_config(page_title="QnA Generator", page_icon="🎥", layout="wide") # Custom CSS st.markdown(""" <style> .stApp { background-color: #f0f2f6; } .stButton > button { background-color: #4CAF50; color: white; font-weight: bold; border-radius: 30px; padding: 15px 30px; font-size: 18px; transition: all 0.3s ease 0s; border: none; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } .stButton > button:hover { background-color: #45a049; box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15); transform: translateY(-2px); } .stButton > button:active { transform: translateY(0px); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .stRadio > label { background-color: #e1e5eb; padding: 12px; border-radius: 8px; margin-bottom: 12px; transition: all 0.2s ease 0s; cursor: pointer; } .stRadio > label:hover { background-color: #d0d4d9; transform: translateY(-2px); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } .stExpander { background-color: #ffffff; border-radius: 15px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); margin-bottom: 20px; } h1 { color: #2c3e50; font-size: 36px; font-weight: bold; margin-bottom: 20px; } h2, h3 { color: #34495e; } .stAlert { border-radius: 10px; font-weight: bold; } .stSpinner > div { border-color: #4CAF50 !important; } [data-testid="stAppViewContainer"] { background-image: url("https://img.freepik.com/free-photo/vivid-blurred-colorful-wallpaper-background_58702-3508.jpg?size=626&ext=jpg"); background-size: cover; } [data-testid="stHeader"] { background-color: rgba(0,0,0,0); } [data-testid="stToolbar"] { right: 2rem; background-image: url(""); background-size: cover; } </style> """, unsafe_allow_html=True) # Initialize the page state if not already set if 'page' not in st.session_state: st.session_state.page = "upload" # To show the appropriate page based on the current state if st.session_state.page == "upload": upload_and_index() elif st.session_state.page == "quiz": quiz() if __name__ == "__main__": main()
Streamlit アプリケーションを起動するエントリポイントとして機能する main() 関数は、タイトル付きのページを設定し、スペースを有効活用するためにワイドレイアウトを使用します。カスタムCSSは、背景、ボタン、ラジオボタン、エクスパンダーのスタイルを整え、意図したデザインへと引き締めて視覚的な魅力を向上させます。
アプリの異なるファイル/セクション間のナビゲーションを管理するために、セッション状態変数 'page' が初期化されます。定義されていない場合、デフォルトで "upload" に設定されます。
アプリケーションは、条件分岐に従い、現在の状態に基づいて適切なページを描画します:
"upload" — 動画アップロードインターフェース用の
upload_and_index()関数を呼び出します。"quiz" — 生成されたクイズを表示するために
quiz()関数を呼び出します。
以下は、PCA(主成分分析)に関する動画コンテンツをアップロードし、インデックスを作成した後に自動生成されたデモクイズの様子です:

Twelve Labsが提供するオープンエンドプロンプトと Pegasus 1.1 をさらに試して、探索してみてください。
このチュートリアルからさらに一歩進めるためのアイデア
アプリケーションの仕組みと開発プロセスを理解すれば、革新的なアイデアを形にし、ユーザーのニーズを満たすプロダクトを作成できるようになります。このチュートリアルブログと同様のユースケースを提案します:
📚️ マイペース学習(Self-Paced Learning):生徒が動画レッスンの理解度をテストするための問題を独自に作成できます。
🎓 教育評価(Educational Assessment):教師は講義動画や教材コンテンツに基づく学習クイズを素早く作成できます。
🏢️ 企業研修(Corporate Training):組織は、さまざまな重要ステップに対応する自動評価クイズを組み込むことで、動画ベースの研修プログラムを強化できます。
🎬 コンテンツへのエンゲージメント(Content Engagement):YouTuberなどの動画クリエイターは、動画に連動したクイズを提供することで、視聴者のエンゲージメントを高めることができます。
🧠 記憶定着(Memory Retention):情報動画から生成された質問に回答することで、学習した知識をしっかりと記憶に定着させることができます。
結論
このブログ記事では、Twelve Labsを使用した動画コンテンツクイズジェネレーターの動作手順と開発プロセスについて包括的に解説しました。チュートリアルにお付き合いいただきありがとうございます。ユーザー体験の向上、そして様々な課題を解決するような皆さんの魅力的なアイデアを楽しみにしています。
追加リソース
自動生成タスクに使用されるエンジンの詳細を理解するには、Marengo 2.6(エンベディングエンジン)およびPegasus 1.1(ジェネレーターエンジン)を参照してください。Twelve Labsをさらに深く知り、動画コンテンツ分析の理解を広げるには、以下の情報が役立ちます:
Discordコミュニティ:開発者や熱心なメンバーが集まる活発なコミュニティに参加して、アイデアを議論したり、質問をしたり、プロジェクトを共有したりしましょう。
サンプルアプリ一覧:様々なサンプルアプリケーションを調べて、次のプロジェクトのインスピレーションを得たり、新しい実装テクニックを学びましょう。
チュートリアルを調べる:包括的なチュートリアルを通じて、Twelve Labsで何ができるのか、その機能をさらに深く体験してください。
これらのリソースを積極的に活用し、知識を広げ、Twelve Labsの動画理解技術を活用した革新的なアプリケーションを構築してみてください。
すべての動画がインタラクティブなクイズに変わり、受動的な視聴を能動的な学習へと簡単に変化させる世界を想像してみてください 🎓
このチュートリアルでは、動画コンテンツに関連する学習体験に革命を起こすために設計されたアプリケーション「Video Content Quiz Generator」について説明します。Twelve Labsの技術を活用したこの動画ベースのツールは、動画コンテンツから多肢選択式クイズ(MCQ)を自動的に生成し、学習と評価の双方を向上させます。
迅速な評価方法を求めている教育関係者の方でも、エンゲージメントの向上を目指すコンテンツクリエイターの方でも、Video Content MCQ Generatorは能動的な学習を促進するための強力な味方になります。
アプリケーションのデモはこちらからお試しいただけます:Video Content MCQ Generator。また、こちらのReplitテンプレートから実際に使ってみることができます。
前提条件
Twelve Labs Playgroundにサインアップして、APIキーを生成してください。
ノートブックとこのアプリケーションのリポジトリはGitHubで公開されています。

アプリケーションの仕組み
このセクションでは、Twelve Labsを使用して動画コンテンツクイズ(MCQ)ジェネレーターを開発するためのアプリケーションの処理フローの概要を説明します。
プロセスは、ユーザーが動画や教育用コンテンツをアップロードすることから始まり、それが能動的なクイズ評価へと変換されます。アップロードされた動画は、セットアップ中に作成された特定のインデックスにインデックス登録されます。インデックス登録にはMarengo 2.6(エンベディングエンジン)が使用されます。インデックス登録が完了すると、Pegasus 1.1(生成エンジン)のオープンエンドプロンプト機能を使用して、動画コンテンツが多肢選択式クイズ(MCQ)に変換されます。
プロンプトは、教育用動画アナライザーの役割を割り当て、クイズの問題と正解を作成します。これらは、インデックス登録された動画に基づいて、指定された指示フォーマットに従ってユーザーの回答を評価するために使用されます。ユーザーが回答を送信すると、アプリケーションはスコアと正解を表示します。リセットボタンを押すことで、ユーザーは最初からやり直すことができます。

準備手順
インデックスを作成する方法は2つあります。Twelve Labs Playgroundを使用する方法と、提供されているコードスニペットを使用する方法です。両方の方法について解説します。PlaygroundからインデックスIDを準備するには、以下の手順に従ってください。
Twelve Labs Playgroundに登録し、インデックスを作成します。
インデックスに対して以下の動画理解(Video Understanding)エンジンを有効にします(これらのエンジンは、高度な動画理解の強固な基盤を提供します)。
Marengo 2.6(エンベディングエンジン):動画検索および分類用
Pegasus 1.1(生成エンジン):動画からテキストへの生成用

Twelve Labs PlaygroundからAPIキーを取得します。
ステップ1で作成したインデックスを開き、INDEX_IDを取得します。IDはURLに含まれています:https://playground.twelvelabs.io/indexes/{index_id}
APIキーとINDEX_IDを、メインファイルと一緒に.envファイルに設定します。
Twelvelabs_API=your_api_key_here API_URL=your_api_url_here
コードベースのアプローチをお好みの場合は、以下の手順に従ってください。
Twelve Labs PlaygroundからAPIキーを取得し、環境変数を準備します。
Twelve Labs SDKと環境変数をインポートします。環境変数から取得したTwelve Labs APIキーを使用して、SDKクライアントを初期化します。
from twelvelabs import TwelveLabs from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("API_KEY") client = TwelveLabs(api_key=API_KEY)
生成タスクに使用するエンジンを指定します:
engines = [ { "name": "marengo2.6", "options": ["visual", "conversation", "text_in_video", "logo"] }, { "name": "pegasus1.1", "options": ["visual", "conversation"] } ]
インデックス名とエンジン構成パラメータを指定して
client.index.createを呼び出し、新しいインデックスを作成します。インデックスには、一意で識別しやすい名前を使用してください。
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}")
index.id フィールドは、新しいインデックスの一意の識別子を表します。この識別子は、動画を正しい場所にインデックス登録するために不可欠です。
これらの手順が完了したら、アプリケーションを開発する準備は万端です!
Video Content Quiz Generatorの構成解説
このチュートリアルでは、最小限のフロントエンドを持つStreamlitアプリケーションを構築します。以下のディレクトリ構造に従って作成してください:
. ├── app.py ├── requirements.txt ├── utils.py ├── .env └── .gitignore
前の手順を終えたら、いよいよStreamlitアプリケーションを構築します。このアプリは、動画をアップロードして、それを選択式のクイズ評価に変換するシンプルな方法を提供します。アプリケーションは主に以下の2つのファイルで構成されます:
1 - 動作に必要なユーティリティ関数の設定
このセクションでは、Twelve Labs SDKを使用して、動画コンテンツをインタラクティブな学習体験に変換するためのユーティリティ関数をセットアップする方法を探ります。このAI搭載システムにより、教育者やコンテンツクリエイターは、自動化された動画分析とクイズ生成を用いることで、視覚的コンテンツに基づいたエンゲージングな評価問題を作成できます。このコードは、動画のインデックス作成とカスタムプロンプトエンジニアリングを組み合わせることで、アップロードされたあらゆる動画から関連性の高い選択式クイズを自動生成し、インタラクティブな教材を作成するための汎用的なツールを提供します。
# 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())
まず、json、tempfile、os、および Twelve Labs SDK を含む必要なモジュールを、APIキーおよびインデックスIDの環境変数とともにインポートします。
create_task(file_path)メソッドは、Twelve Labs SDKを利用して新しい動画インデックス登録タスクを作成します。これによりインデックス作成アプリケーション用のタスクオブジェクトが返されます。コールバック関数on_task_update(task: Task)は、インデックス作成タスクのステータス更新を標準出力に表示します。ステータスが「ready」になり、video_id が返されると、generate_mcq(video_id)関数がトリガーされます。generate_mcq(video_id)関数は、Pegasus 1.1を使用して、インデックス登録された動画コンテンツに基づいて多肢選択式の質問を生成します。プロンプトは、モデルの役割、目的、および出力形式を定義します。その後、その結果はparse_json_with_regex(text)を使用してパースされます。calculate_score(user_answers, questions)関数は、ユーザーの解答に基づいてスコアを算出し、次のセクションでユーザーが送信ボタンをクリックしたときに合計点数を返します。
2. Streamlitアプリケーションの処理フロー
2.1 クイズ評価の処理フロー
前述の通り、app.py には utils.py のユーティリティ関数を使用した Streamlit アプリケーションの適切な処理フローが含まれています。このセクションでは、クイズ評価と採点システムの機能およびフローに焦点を当てます。
# 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()
Streamlit アプリケーションのこの部分は、動画コンテンツからのクイズ生成と、クイズ開始後のインタラクション管理を担当します。
upload_and_index() 関数は、Twelve Labs SDK を利用して動画のアップロードとインデックス作成を実行します。インデックス作成が完了すると、クイズ生成の処理が開始されます。
クイズ問題を自動生成するために、関数はインデックスされた動画の 'video_id' を使用します。そして、前述したように generate_mcq() を呼び出した後に parse_json_with_regex() を呼び出します。このプロセスによってクイズの問題が作成されます。生成が成功すると、クイズページが表示されます。
quiz() 関数は生成されたクイズを表示し、解答の選択やクイズの送信といったユーザーの操作を処理します。送信後には、**「最初からやり直す(Start Over)」** オプションが提供されます。クイズのやり取りを管理するために、いくつかのユーティリティ関数が用意されています:
update_answer()は、特定の質問に対するユーザーの回答を更新します。submit_quiz()は、クイズ送信の完了処理とスコア計算を行います。display_results()は、スコアや正解を含むクイズ結果画面を表示します。reset_state()は、クイズを最初からやり直すために、すべてのセッション状態変数をクリアします。
2.2 Streamlitのセッション状態(Session State)とカスタムCSS
app.py パッケージの main 関数は、Streamlit ページの設定を行い、カスタムCSSを適用します。背景画像の設定、ボタンの装飾、そしてアプリケーション全体のビジュアルの外観を決定します。また、セッション状態の初期化も行います。
def main(): # Set up the Streamlit page configuration st.set_page_config(page_title="QnA Generator", page_icon="🎥", layout="wide") # Custom CSS st.markdown(""" <style> .stApp { background-color: #f0f2f6; } .stButton > button { background-color: #4CAF50; color: white; font-weight: bold; border-radius: 30px; padding: 15px 30px; font-size: 18px; transition: all 0.3s ease 0s; border: none; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } .stButton > button:hover { background-color: #45a049; box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15); transform: translateY(-2px); } .stButton > button:active { transform: translateY(0px); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .stRadio > label { background-color: #e1e5eb; padding: 12px; border-radius: 8px; margin-bottom: 12px; transition: all 0.2s ease 0s; cursor: pointer; } .stRadio > label:hover { background-color: #d0d4d9; transform: translateY(-2px); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } .stExpander { background-color: #ffffff; border-radius: 15px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); margin-bottom: 20px; } h1 { color: #2c3e50; font-size: 36px; font-weight: bold; margin-bottom: 20px; } h2, h3 { color: #34495e; } .stAlert { border-radius: 10px; font-weight: bold; } .stSpinner > div { border-color: #4CAF50 !important; } [data-testid="stAppViewContainer"] { background-image: url("https://img.freepik.com/free-photo/vivid-blurred-colorful-wallpaper-background_58702-3508.jpg?size=626&ext=jpg"); background-size: cover; } [data-testid="stHeader"] { background-color: rgba(0,0,0,0); } [data-testid="stToolbar"] { right: 2rem; background-image: url(""); background-size: cover; } </style> """, unsafe_allow_html=True) # Initialize the page state if not already set if 'page' not in st.session_state: st.session_state.page = "upload" # To show the appropriate page based on the current state if st.session_state.page == "upload": upload_and_index() elif st.session_state.page == "quiz": quiz() if __name__ == "__main__": main()
Streamlit アプリケーションを起動するエントリポイントとして機能する main() 関数は、タイトル付きのページを設定し、スペースを有効活用するためにワイドレイアウトを使用します。カスタムCSSは、背景、ボタン、ラジオボタン、エクスパンダーのスタイルを整え、意図したデザインへと引き締めて視覚的な魅力を向上させます。
アプリの異なるファイル/セクション間のナビゲーションを管理するために、セッション状態変数 'page' が初期化されます。定義されていない場合、デフォルトで "upload" に設定されます。
アプリケーションは、条件分岐に従い、現在の状態に基づいて適切なページを描画します:
"upload" — 動画アップロードインターフェース用の
upload_and_index()関数を呼び出します。"quiz" — 生成されたクイズを表示するために
quiz()関数を呼び出します。
以下は、PCA(主成分分析)に関する動画コンテンツをアップロードし、インデックスを作成した後に自動生成されたデモクイズの様子です:

Twelve Labsが提供するオープンエンドプロンプトと Pegasus 1.1 をさらに試して、探索してみてください。
このチュートリアルからさらに一歩進めるためのアイデア
アプリケーションの仕組みと開発プロセスを理解すれば、革新的なアイデアを形にし、ユーザーのニーズを満たすプロダクトを作成できるようになります。このチュートリアルブログと同様のユースケースを提案します:
📚️ マイペース学習(Self-Paced Learning):生徒が動画レッスンの理解度をテストするための問題を独自に作成できます。
🎓 教育評価(Educational Assessment):教師は講義動画や教材コンテンツに基づく学習クイズを素早く作成できます。
🏢️ 企業研修(Corporate Training):組織は、さまざまな重要ステップに対応する自動評価クイズを組み込むことで、動画ベースの研修プログラムを強化できます。
🎬 コンテンツへのエンゲージメント(Content Engagement):YouTuberなどの動画クリエイターは、動画に連動したクイズを提供することで、視聴者のエンゲージメントを高めることができます。
🧠 記憶定着(Memory Retention):情報動画から生成された質問に回答することで、学習した知識をしっかりと記憶に定着させることができます。
結論
このブログ記事では、Twelve Labsを使用した動画コンテンツクイズジェネレーターの動作手順と開発プロセスについて包括的に解説しました。チュートリアルにお付き合いいただきありがとうございます。ユーザー体験の向上、そして様々な課題を解決するような皆さんの魅力的なアイデアを楽しみにしています。
追加リソース
自動生成タスクに使用されるエンジンの詳細を理解するには、Marengo 2.6(エンベディングエンジン)およびPegasus 1.1(ジェネレーターエンジン)を参照してください。Twelve Labsをさらに深く知り、動画コンテンツ分析の理解を広げるには、以下の情報が役立ちます:
Discordコミュニティ:開発者や熱心なメンバーが集まる活発なコミュニティに参加して、アイデアを議論したり、質問をしたり、プロジェクトを共有したりしましょう。
サンプルアプリ一覧:様々なサンプルアプリケーションを調べて、次のプロジェクトのインスピレーションを得たり、新しい実装テクニックを学びましょう。
チュートリアルを調べる:包括的なチュートリアルを通じて、Twelve Labsで何ができるのか、その機能をさらに深く体験してください。
これらのリソースを積極的に活用し、知識を広げ、Twelve Labsの動画理解技術を活用した革新的なアプリケーションを構築してみてください。




