Skip to main content

Educational video to questionnaire generator - transcribe, summarize, and generate interactive quizzes from video content

Project description

YtQGen: YouTube to Questionnaire Generator

YtQGen is a Python library and CLI that turns educational YouTube videos into clean, printable questionnaires. It downloads audio, transcribes speech, summarizes content, and generates balanced questions, then exports a PDF.

Highlights

  • Multiple AI providers: OpenAI, Mistral, and Groq for both LLM tasks and transcription
  • No external ffmpeg required: audio handled via PyAV and yt-dlp
  • Robust on long inputs: automatic audio chunking and summary chunking
  • Configurable outputs: control question count, type mix, difficulty, and style
  • Plain-text safe for PDFs: prompts enforce ASCII-safe formatting for reliable PDF rendering
  • CLI and Python API, with YAML config and .env support

Requirements

Installation

Install from PyPI using extras for your provider:

# Core package only
pip install ytqgen

# With a specific provider
pip install "ytqgen[openai]"
pip install "ytqgen[mistral]"
pip install "ytqgen[groq]"

# With all providers
pip install "ytqgen[all]"

# For development and tests
pip install -e ".[dev]"

The package entry point installs a command named ytqgen.

Quickstart

CLI

# Minimal: provide a YouTube URL and choose an LLM provider
ytqgen process --input "https://www.youtube.com/watch?v=VIDEO_ID" --provider openai --output quiz.pdf

# With a config file that includes keys and defaults
ytqgen process --config examples/config.yml --input "https://www.youtube.com/watch?v=VIDEO_ID"

# Override generation settings at the CLI
ytqgen process \
  --input "https://www.youtube.com/watch?v=VIDEO_ID" \
  --num-questions 20 \
  --mcq-percentage 40 \
  --subjective-percentage 60

CLI precedence: CLI arguments override YAML config, which overrides .env, which overrides existing environment variables.

Notes

  • The CLI currently accepts only YouTube URLs for --input.
  • YouTube downloads are best run on a local machine. Some cloud or hosted environments may block downloads.

Python API

import os
from ytqgen import process_stream

# Configure providers and keys via environment
os.environ["LLM_PROVIDER"] = "openai"  # or "mistral" or "groq"
os.environ["TRANSCRIPTION_PROVIDER"] = "openai"  # or "mistral" or "groq"
os.environ["OPENAI_API_KEY"] = "your-openai-key"

pdf_path = process_stream("https://www.youtube.com/watch?v=VIDEO_ID", output_pdf="questionnaire.pdf")
print(pdf_path)

Configuration

You can configure YtQGen with a YAML file, environment variables, or CLI arguments. A sample is provided in examples/config_template.yml.

Supported keys in YAML

  • provider: LLM provider for summarization and question generation. One of openai, mistral, groq
  • transcription_provider: provider for audio transcription. One of openai, mistral, groq
  • keys: API keys per provider
    • openai: string
    • mistral: string
    • groq: string
  • models: optional override of model names per provider
    • openai: for example gpt-4o-mini, gpt-4o, gpt-4, gpt-3.5-turbo
    • mistral: for example mistral-small-latest, mistral-medium-latest, mistral-large-latest
    • groq: for example llama-3.1-70b-versatile, llama-3.3-70b-versatile, mixtral-8x7b-32768
  • generation: questionnaire settings
    • num_questions: integer greater than 0
    • question_types: percentages that sum to 100
      • mcq_percentage
      • subjective_percentage
    • difficulty: percentages that sum to 100
      • easy_percentage
      • medium_percentage
      • hard_percentage
    • style: percentages that sum to 100 (applied to subjective)
      • scenario_percentage
      • theoretical_percentage

Example

input: https://www.youtube.com/watch?v=dQw4w9WgXcQ
output: my_questionnaire.pdf

provider: openai
transcription_provider: openai

keys:
  openai: YOUR_OPENAI_API_KEY

models:
  openai: gpt-4o-mini

generation:
  num_questions: 10
  question_types:
    mcq_percentage: 20
    subjective_percentage: 80
  difficulty:
    easy_percentage: 30
    medium_percentage: 50
    hard_percentage: 20
  style:
    scenario_percentage: 40
    theoretical_percentage: 60

Environment variables

  • LLM_PROVIDER, TRANSCRIPTION_PROVIDER
  • OPENAI_API_KEY, MISTRAL_API_KEY, GROQ_API_KEY
  • YTQGEN_OPENAI_MODEL, YTQGEN_MISTRAL_MODEL, YTQGEN_GROQ_MODEL
  • YTQGEN_NUM_QUESTIONS, YTQGEN_MCQ_PERCENTAGE, YTQGEN_SUBJECTIVE_PERCENTAGE
  • YTQGEN_EASY_PERCENTAGE, YTQGEN_MEDIUM_PERCENTAGE, YTQGEN_HARD_PERCENTAGE
  • YTQGEN_SCENARIO_PERCENTAGE, YTQGEN_THEORETICAL_PERCENTAGE

Providers and models

Transcription

  • OpenAI: Whisper model whisper-1
  • Groq: Whisper model whisper-large-v3
  • Mistral: Voxtral endpoint voxtral-mini-latest

LLM summarization and question generation

  • OpenAI: defaults to gpt-4o-mini unless overridden
  • Mistral: defaults to mistral-small-latest unless overridden
  • Groq: set with YTQGEN_GROQ_MODEL. Common choices include llama-3.1-70b-versatile, openai/gpt-oss-120b, and openai/gpt-oss-20b

Set explicit model names in your YAML or environment when in doubt.

If you are lost regarding models, check out the respective documentations.

How it works

Pipeline steps

  1. Download audio with yt-dlp and convert to MP3 with PyAV
  2. Transcribe audio with the selected provider. Long audio is automatically split into 10 minute chunks
  3. Summarize the transcription using the selected LLM. Long summaries are created via chunked summarization and a final synthesis pass
  4. Generate a balanced questionnaire from the summary using configurable distributions
  5. Render a plain text PDF with PyMuPDF for broad compatibility

Key modules

  • ytqgen.audio_processor: audio download and conversion with PyAV
  • ytqgen.transcription: transcription with OpenAI, Groq, or Mistral, with chunking
  • ytqgen.summarizer: chunked summarization using provider LLMs
  • ytqgen.questionnaire_generator: dynamic prompts and distribution controls
  • ytqgen.pdf_generator: plain text PDF writer using PyMuPDF
  • ytqgen.cli: CLI implementation with YAML config and validation
  • ytqgen.pipeline: orchestrates the end to end flow

Examples

  • examples/config_template.yml: copy to your project and fill in keys
  • examples/example_youtube.py: simple programmatic usage with a YouTube URL

Note: A sample examples/example_local_file.py exists in the repository but the current pipeline expects a YouTube URL. Local file processing is not yet supported by the default pipeline.

Troubleshooting

Common issues

  • Missing API key: set the corresponding environment variable or place it in YAML under keys
  • Invalid input: the CLI accepts only YouTube URLs
  • yt-dlp blocked: some hosted environments block downloads. Run locally or provide a different network
  • Audio conversion errors: ensure the av package is installed and up to date
  • PDF output looks odd: the generator enforces ASCII in prompts, but if your model returns formatted text, reduce creativity or re-run

Update tools

pip install --upgrade yt-dlp av PyMuPDF

Development and testing

Install dev dependencies and run the test suite

pip install -e ".[dev]"
pytest tests/ -v

Useful targets

  • Run import checks: python test_imports.py
  • Try a fast configuration: ytqgen process --input "https://youtube.com/watch?v=VIDEO_ID" --config test_config.yml --output test_output.pdf

License

MIT License. See LICENSE for details.

Contributing

Contributions are welcome. Please open an issue or a pull request with a clear description and steps to reproduce for bugs.

Security and privacy

Downloaded audio is stored in the system temporary directory and removed after processing. API keys are read from environment variables or YAML at runtime and are not persisted by the library.

Advanced usage (library)

YtQGen can be used as both a CLI and a Python library. The following examples show how to use individual components programmatically.

Transcription (audio to text)

from ytqgen.transcription import transcribe_audio
import os

# Configure transcription provider
os.environ['TRANSCRIPTION_PROVIDER'] = 'openai'  # or 'groq', 'mistral'
os.environ['OPENAI_API_KEY'] = 'your-key'

# Transcribe audio file (automatically handles chunking for long files)
transcript = transcribe_audio(
  audio_file_path='lecture.mp3',
  chunk_duration_minutes=10  # Optional: chunk size for long audio
)

print(f"Transcript: {transcript[:200]}...")

Features

  • Supports OpenAI Whisper, Groq Whisper, Mistral Voxtral
  • Automatic chunking for audio longer than 10 minutes
  • Returns full transcription as text

Summarization (long text to summary)

from ytqgen.summarizer import summarize_text
import os

# Configure LLM provider
os.environ['LLM_PROVIDER'] = 'groq'
os.environ['GROQ_API_KEY'] = 'your-key'

# Summarize long transcription
summary = summarize_text(
  transcription=transcript,
  max_tokens=2048  # Optional: control summary length
)

print(f"Summary: {summary}")

Features

  • Automatic chunking for very long texts (>1000 words)
  • Hierarchical summarization (chunk, combine, final)
  • Token-based length control

Question generation

from ytqgen.questionnaire_generator import generate_questionnaire
import os

# Configure LLM provider (if not already set)
os.environ['LLM_PROVIDER'] = 'openai'
os.environ['OPENAI_API_KEY'] = 'your-key'

# Configure question distribution (optional)
os.environ['YTQGEN_NUM_QUESTIONS'] = '20'
os.environ['YTQGEN_MCQ_PERCENTAGE'] = '70'
os.environ['YTQGEN_SUBJECTIVE_PERCENTAGE'] = '30'

# Generate questionnaire from summary
questionnaire = generate_questionnaire(summary=summary)

print(questionnaire)

Features

  • MCQ (multiple choice) and subjective questions
  • Configurable question counts and difficulty distribution
  • Scenario-based and theoretical questions

PDF generation

from ytqgen.pdf_generator import save_text_as_pdf

# Save questionnaire as PDF
save_text_as_pdf(
  text=questionnaire,
  filename='my_quiz.pdf'
)

print("PDF saved successfully.")

LLM client (direct access)

from ytqgen.model_loader import get_llm_client
import os

os.environ['LLM_PROVIDER'] = 'mistral'
os.environ['MISTRAL_API_KEY'] = 'your-key'

# Get initialized LLM client
client, model_name, provider = get_llm_client()

print(f"Using {provider} with model {model_name}")

# Use client directly for custom tasks
if provider == 'mistral':
  response = client.chat.complete(
    model=model_name,
    messages=[{"role": "user", "content": "Explain AI"}]
  )
else:  # OpenAI or Groq
  response = client.chat.completions.create(
    model=model_name,
    messages=[{"role": "user", "content": "Explain AI"}]
  )

Complete custom workflow example

import os
from ytqgen.transcription import transcribe_audio
from ytqgen.summarizer import summarize_text
from ytqgen.questionnaire_generator import generate_questionnaire
from ytqgen.pdf_generator import save_text_as_pdf

# 1. Configure environment
os.environ['LLM_PROVIDER'] = 'groq'
os.environ['GROQ_API_KEY'] = 'gsk_...'
os.environ['TRANSCRIPTION_PROVIDER'] = 'groq'
os.environ['YTQGEN_NUM_QUESTIONS'] = '15'

# 2. Transcribe
print("Step 1: Transcribing...")
transcript = transcribe_audio('lecture.mp3')

# 3. Summarize
print("Step 2: Summarizing...")
summary = summarize_text(transcript, max_tokens=2048)

# 4. Generate questions
print("Step 3: Generating questions...")
questionnaire = generate_questionnaire(summary)

# 5. Save as PDF
print("Step 4: Creating PDF...")
save_text_as_pdf(questionnaire, 'custom_quiz.pdf')

print("Complete. Your quiz is ready.")

Configuration via environment variables

All configuration can be done via environment variables:

import os

# Provider selection
os.environ['LLM_PROVIDER'] = 'groq'  # openai, mistral, groq
os.environ['TRANSCRIPTION_PROVIDER'] = 'groq'

# API keys
os.environ['OPENAI_API_KEY'] = 'sk-...'
os.environ['MISTRAL_API_KEY'] = 'mistral-...'
os.environ['GROQ_API_KEY'] = 'gsk_...'

# Model selection (optional)
os.environ['YTQGEN_OPENAI_MODEL'] = 'gpt-4o'
os.environ['YTQGEN_MISTRAL_MODEL'] = 'mistral-large-latest'
os.environ['YTQGEN_GROQ_MODEL'] = 'llama-3.3-70b-versatile'

# Question generation settings
os.environ['YTQGEN_NUM_QUESTIONS'] = '20'
os.environ['YTQGEN_MCQ_PERCENTAGE'] = '70'
os.environ['YTQGEN_SUBJECTIVE_PERCENTAGE'] = '30'
os.environ['YTQGEN_EASY_PERCENTAGE'] = '30'
os.environ['YTQGEN_MEDIUM_PERCENTAGE'] = '50'
os.environ['YTQGEN_HARD_PERCENTAGE'] = '20'

# Summary settings
os.environ['YTQGEN_SUMMARY_MAX_LENGTH'] = '500'  # words
os.environ['YTQGEN_SUMMARY_MIN_LENGTH'] = '100'  # words

Error handling

from ytqgen.transcription import transcribe_audio

try:
  transcript = transcribe_audio('lecture.mp3')
except ValueError as e:
  print(f"Configuration error: {e}")
  # Handle missing API keys, invalid providers, etc.
except Exception as e:
  print(f"Transcription failed: {e}")
  # Handle API errors, file errors, etc.

Common errors

  • ValueError: Missing API keys, invalid provider names
  • FileNotFoundError: Audio file does not exist
  • API errors: rate limits, invalid keys, network issues

Use cases

Batch processing multiple files

import os
from ytqgen import process_stream

os.environ['LLM_PROVIDER'] = 'groq'
os.environ['GROQ_API_KEY'] = 'your-key'
os.environ['TRANSCRIPTION_PROVIDER'] = 'groq'

files = ['lecture1.mp4', 'lecture2.mp4', 'lecture3.mp4']

for i, file in enumerate(files, 1):
  print(f"\nProcessing {i}/{len(files)}: {file}")
  output = f'quiz_{i}.pdf'
  try:
    process_stream(file, output)
    print(f"Saved to {output}")
  except Exception as e:
    print(f"Failed: {e}")

Custom question distribution

import os
from ytqgen.questionnaire_generator import generate_questionnaire

# More MCQs, fewer subjective
os.environ['YTQGEN_NUM_QUESTIONS'] = '25'
os.environ['YTQGEN_MCQ_PERCENTAGE'] = '80'
os.environ['YTQGEN_SUBJECTIVE_PERCENTAGE'] = '20'

# Harder questions
os.environ['YTQGEN_EASY_PERCENTAGE'] = '20'
os.environ['YTQGEN_MEDIUM_PERCENTAGE'] = '40'
os.environ['YTQGEN_HARD_PERCENTAGE'] = '40'

questionnaire = generate_questionnaire(summary)

Multi-provider workflow

import os
from ytqgen.transcription import transcribe_audio
from ytqgen.summarizer import summarize_text
from ytqgen.questionnaire_generator import generate_questionnaire

# Use Groq for transcription
os.environ['TRANSCRIPTION_PROVIDER'] = 'groq'
os.environ['GROQ_API_KEY'] = 'gsk_...'

transcript = transcribe_audio('lecture.mp3')

# Use OpenAI for summarization and questions
os.environ['LLM_PROVIDER'] = 'openai'
os.environ['OPENAI_API_KEY'] = 'sk-...'
os.environ['YTQGEN_OPENAI_MODEL'] = 'gpt-4o'

summary = summarize_text(transcript)
questionnaire = generate_questionnaire(summary)

API reference

process_stream(video_url, output_pdf)

Full pipeline to process video/audio and generate a questionnaire.

Parameters

  • video_url (str): Path to local file or YouTube URL
  • output_pdf (str): Output PDF filename

Returns

  • str: Path to generated PDF, or None if error

Environment variables used

  • LLM_PROVIDER, TRANSCRIPTION_PROVIDER
  • API keys for selected providers
  • All YTQGEN_* configuration variables

transcribe_audio(audio_file_path, chunk_duration_minutes=10)

Transcribe audio to text using API services.

Parameters

  • audio_file_path (str): Path to audio/video file
  • chunk_duration_minutes (int): Chunk size for long audio (default: 10)

Returns

  • str: Transcribed text

Environment variables used

  • TRANSCRIPTION_PROVIDER (default: 'openai')
  • OPENAI_API_KEY, GROQ_API_KEY, or MISTRAL_API_KEY

summarize_text(transcription, max_tokens=MAX_TOKENS)

Summarize long transcription text.

Parameters

  • transcription (str): Input text to summarize
  • max_tokens (int): Maximum tokens for summary (default: 2048)

Returns

  • str: Summarized text

Environment variables used

  • LLM_PROVIDER
  • API key for selected provider
  • YTQGEN_SUMMARY_MAX_LENGTH, YTQGEN_SUMMARY_MIN_LENGTH

generate_questionnaire(summary)

Generate a structured questionnaire from a summary.

Parameters

  • summary (str): Summarized content

Returns

  • str: Formatted questionnaire with questions and answers

Environment variables used

  • LLM_PROVIDER
  • API key for selected provider
  • YTQGEN_NUM_QUESTIONS
  • YTQGEN_MCQ_PERCENTAGE, YTQGEN_SUBJECTIVE_PERCENTAGE
  • YTQGEN_EASY_PERCENTAGE, YTQGEN_MEDIUM_PERCENTAGE, YTQGEN_HARD_PERCENTAGE

save_text_as_pdf(text, filename)

Save text content as a formatted PDF.

Parameters

  • text (str): Content to save
  • filename (str): Output PDF path

Returns

  • None

get_llm_client()

Get an initialized LLM client for the selected provider.

Returns

  • tuple: (client, model_name, provider)
    • client: Initialized API client object
    • model_name (str): Model being used
    • provider (str): Provider name ('openai', 'mistral', 'groq')

Environment variables used

  • LLM_PROVIDER
  • API key for selected provider
  • YTQGEN_OPENAI_MODEL, YTQGEN_MISTRAL_MODEL, YTQGEN_GROQ_MODEL

When to use library vs CLI

Use CLI when

  • Quick one-off processing
  • Simple workflows
  • YAML configuration preferred
  • Running from terminal or scripts

Use Python library when

  • Custom processing pipelines
  • Integration with existing Python applications
  • Batch processing multiple files
  • Need fine-grained control over each step
  • Building applications on top of YtQGen
  • Programmatic configuration required

Questions or issues?

Open an issue on GitHub or contact us at team@jbac.dev.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ytqgen-0.1.2.tar.gz (41.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ytqgen-0.1.2-py3-none-any.whl (28.4 kB view details)

Uploaded Python 3

File details

Details for the file ytqgen-0.1.2.tar.gz.

File metadata

  • Download URL: ytqgen-0.1.2.tar.gz
  • Upload date:
  • Size: 41.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.4

File hashes

Hashes for ytqgen-0.1.2.tar.gz
Algorithm Hash digest
SHA256 1f2ecc0926bb50d92bd0028c535aec91547956c9d011d4a8330e1213e42973d4
MD5 8ccf193f55dc71d5729169082d029ad6
BLAKE2b-256 63f27082318a10a7f2a080c9031aca11892baf5893fd7cfed550b8d42fc771a6

See more details on using hashes here.

File details

Details for the file ytqgen-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: ytqgen-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 28.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.4

File hashes

Hashes for ytqgen-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c9b9fe29fc2708faabb0ca1328f07d2ee876c4698c3e5ddbb86a65c4dca498ea
MD5 be75465592b2786d76de780037fb7eaa
BLAKE2b-256 04c744c4e0aa9586a40cb5241f648ebcbd83ba587473bd01182ae57b63755e29

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page