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
- Python 3.10 or newer
- API key for at least one provider
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
- Download audio with yt-dlp and convert to MP3 with PyAV
- Transcribe audio with the selected provider. Long audio is automatically split into 10 minute chunks
- Summarize the transcription using the selected LLM. Long summaries are created via chunked summarization and a final synthesis pass
- Generate a balanced questionnaire from the summary using configurable distributions
- Render a plain text PDF with PyMuPDF for broad compatibility
Key modules
ytqgen.audio_processor: audio download and conversion with PyAVytqgen.transcription: transcription with OpenAI, Groq, or Mistral, with chunkingytqgen.summarizer: chunked summarization using provider LLMsytqgen.questionnaire_generator: dynamic prompts and distribution controlsytqgen.pdf_generator: plain text PDF writer using PyMuPDFytqgen.cli: CLI implementation with YAML config and validationytqgen.pipeline: orchestrates the end to end flow
Examples
examples/config_template.yml: copy to your project and fill in keysexamples/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
avpackage 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 URLoutput_pdf(str): Output PDF filename
Returns
str: Path to generated PDF, orNoneif 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 filechunk_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, orMISTRAL_API_KEY
summarize_text(transcription, max_tokens=MAX_TOKENS)
Summarize long transcription text.
Parameters
transcription(str): Input text to summarizemax_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_QUESTIONSYTQGEN_MCQ_PERCENTAGE,YTQGEN_SUBJECTIVE_PERCENTAGEYTQGEN_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 savefilename(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 objectmodel_name(str): Model being usedprovider(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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f2ecc0926bb50d92bd0028c535aec91547956c9d011d4a8330e1213e42973d4
|
|
| MD5 |
8ccf193f55dc71d5729169082d029ad6
|
|
| BLAKE2b-256 |
63f27082318a10a7f2a080c9031aca11892baf5893fd7cfed550b8d42fc771a6
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9b9fe29fc2708faabb0ca1328f07d2ee876c4698c3e5ddbb86a65c4dca498ea
|
|
| MD5 |
be75465592b2786d76de780037fb7eaa
|
|
| BLAKE2b-256 |
04c744c4e0aa9586a40cb5241f648ebcbd83ba587473bd01182ae57b63755e29
|