Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
O comando permanece em uma só linha. Role horizontalmente para revisá-lo antes de copiar.
Prefere uma cópia local? Baixe os arquivos disponíveis atualmente no SkillsMP.
Explorador de arquivos
9 arquivos
Exibindo SKILL.md
SKILL.md
Instruções da origem · Visualização somente leitura
name
youtube-transcript-to-lecture-notes
description
Transform YouTube transcripts into comprehensive lecture notes with PDF and HTML outputs
YouTube Transcript to Lecture Notes Skill
Overview
This skill transforms YouTube transcripts into comprehensive, academic-quality lecture notes that serve as standalone learning materials. The skill produces both PDF and HTML versions with identical content, ensuring students can learn all key topics and nuances without attending the original lecture.
Mathematical Foundation
Text Processing Pipeline
The transformation process follows a multi-stage pipeline:
$f_{clean}$ = Cleaning function removing artifacts
$f_{structure}$ = Structuring function for logical organization
$f_{enhance}$ = Enhancement function adding educational value
$f_{format}$ = Formatting function for output generation
Core Components
1. Transcript Cleaning Algorithm
The cleaning process removes conversational artifacts while preserving educational content:
import re
from typing importList, Dict, TupleclassTranscriptCleaner:
"""
Implements sophisticated cleaning algorithms for YouTube transcripts.
The cleaning process uses pattern matching with complexity O(n*m) where:
- n = length of transcript
- m = number of patterns to match
"""
():
.filler_patterns = [
(, ),
(, ),
(, ),
(, ),
(, ),
(, ),
]
() -> :
cleaned_text = text
pattern, confidence .filler_patterns:
confidence > :
cleaned_text = re.sub(pattern, , cleaned_text, flags=re.IGNORECASE)
cleaned_text = re.sub(, , cleaned_text)
cleaned_text = re.sub(, , cleaned_text)
cleaned_text.strip()
def
__init__
self
# Define patterns for removal with confidence scores
self
r'\b(um+|uh+|ah+|er+|hmm+)\b'
0.95
# Filler words
r'\[.*?\]'
0.90
# Timestamps and annotations
r'\(.*?inaudible.*?\)'
0.99
# Inaudible markers
r'\b(you know|I mean|like|sort of|kind of)\b'
0.70
# Hedging phrases
r'\.{3,}'
0.85
# Multiple dots
r'\s+'
1.0
# Normalize whitespace
def
clean_transcript
self, text: str
str
"""
Apply multi-pass cleaning with confidence thresholds.
Mathematical model for cleaning decision:
P(remove) = Σ(w_i * c_i) / Σ(w_i)
Where:
- w_i = weight of pattern i
- c_i = confidence score for pattern i
"""
for
in
self
if
0.8
# Only apply high-confidence removals
' '
# Normalize spacing and punctuation
r'\s+'
' '
r'\s*([.,!?;:])\s*'
r'\1 '
return
2. Intelligent Content Structuring
The structuring algorithm uses natural language processing to identify logical sections:
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
classContentStructurer:
"""
Implements topic segmentation using TF-IDF and cosine similarity.
Mathematical foundation:
TF-IDF(t,d,D) = TF(t,d) × IDF(t,D)
Where:
- TF(t,d) = frequency of term t in document d
- IDF(t,D) = log(|D| / |{d ∈ D : t ∈ d}|)
"""def__init__(self, window_size: int = 5, threshold: float = 0.3):
self.window_size = window_size
self.threshold = threshold
self.vectorizer = TfidfVectorizer(max_features=100, stop_words='english')
defsegment_content(self, sentences: List[str]) -> List[Tuple[int, int]]:
"""
Identify topic boundaries using sliding window similarity.
Algorithm:
1. Convert sentences to TF-IDF vectors
2. Calculate similarity between adjacent windows
3. Identify boundaries where similarity < threshold
Complexity: O(n * w * f) where:
- n = number of sentences
- w = window size
- f = number of features
"""# Create sentence windows
windows = []
for i inrange(len(sentences) - self.window_size + 1):
window_text = ' '.join(sentences[i:i + self.window_size])
windows.append(window_text)
# Vectorize windows
tfidf_matrix = self.vectorizer.fit_transform(windows)
# Calculate similarities between adjacent windows
boundaries = [0] # Start with first sentencefor i inrange(len(windows) - 1):
similarity = cosine_similarity(
tfidf_matrix[i:i+1],
tfidf_matrix[i+1:i+2]
)[0][0]
# Boundary detection conditionif similarity < self.threshold:
boundaries.append(i + self.window_size)
boundaries.append(len(sentences)) # End with last sentence# Create segments
segments = []
for i inrange(len(boundaries) - 1):
segments.append((boundaries[i], boundaries[i+1]))
return segments
3. Content Enhancement Engine
The enhancement engine adds educational value through elaboration and clarification:
classContentEnhancer:
"""
Enhances lecture content with explanations, examples, and context.
Uses a knowledge graph approach:
G = (V, E) where:
- V = set of concepts
- E = relationships between concepts
"""def__init__(self):
self.concept_graph = {}
self.importance_scores = {}
defextract_key_concepts(self, text: str) -> List[Dict[str, any]]:
"""
Extract and rank key concepts using TextRank algorithm.
Mathematical model:
PR(v_i) = (1-d) + d * Σ(PR(v_j) * w_ji / Σw_jk)
Where:
- PR(v_i) = PageRank of vertex i
- d = damping factor (typically 0.85)
- w_ji = weight of edge from j to i
"""# Simplified concept extraction
concepts = []
# Extract noun phrases as potential conceptsimport nltk
from nltk import pos_tag, word_tokenize
from nltk.chunk import ne_chunk, tree2conlltags
tokens = word_tokenize(text)
pos_tags = pos_tag(tokens)
# Extract noun phrases
noun_phrases = []
current_phrase = []
for word, tag in pos_tags:
if tag.startswith('NN'): # Noun
current_phrase.append(word)
elif current_phrase:
iflen(current_phrase) > 1:
noun_phrases.append(' '.join(current_phrase))
current_phrase = []
# Score concepts by frequency and positionfor i, phrase inenumerate(noun_phrases):
score = noun_phrases.count(phrase) * (1 - i/len(noun_phrases))
concepts.append({
'term': phrase,
'score': score,
'definition': self.generate_definition(phrase),
'examples': self.generate_examples(phrase)
})
returnsorted(concepts, key=lambda x: x['score'], reverse=True)[:10]
defgenerate_definition(self, term: str) -> str:
"""Generate educational definition for a term."""# In production, this would use an LLM or knowledge basereturnf"A comprehensive explanation of {term} in the context of this lecture."defgenerate_examples(self, term: str) -> List[str]:
"""Generate illustrative examples."""# In production, this would generate contextual examplesreturn [
f"Example 1: Practical application of {term}",
f"Example 2: Theoretical illustration of {term}",
f"Example 3: Real-world scenario involving {term}"
]
4. Multi-Format Output Generator
The output generator creates both PDF and HTML with identical content:
classLectureNotesProcessor:
"""
Main processor that coordinates all components.
Processing flow:
Input → Clean → Structure → Enhance → Format → Output
"""def__init__(self):
self.cleaner = TranscriptCleaner()
self.structurer = ContentStructurer()
self.enhancer = ContentEnhancer()
self.generator = OutputGenerator()
defprocess_transcript(self, transcript_text: str, lecture_title: str = None) -> Dict:
"""
Complete processing pipeline with error handling and logging.
Time Complexity: O(n²) in worst case for structure detection
Space Complexity: O(n) for storing processed content
"""try:
# Step 1: Clean transcriptprint("Step 1: Cleaning transcript...")
cleaned_text = self.cleaner.clean_transcript(transcript_text)
# Step 2: Sentence segmentationprint("Step 2: Segmenting sentences...")
sentences = self._segment_sentences(cleaned_text)
# Step 3: Identify structureprint("Step 3: Identifying content structure...")
segments = self.structurer.segment_content(sentences)
# Step 4: Build sectionsprint("Step 4: Building sections...")
sections = self._build_sections(sentences, segments)
# Step 5: Enhance contentprint("Step 5: Enhancing content...")
enhanced_sections = self._enhance_sections(sections)
# Step 6: Prepare final contentprint("Step 6: Preparing final content...")
structured_content = {
'title': lecture_title orself._extract_title(cleaned_text),
'sections': enhanced_sections
}
# Step 7: Generate outputsprint("Step 7: Generating PDF and HTML outputs...")
pdf_bytes, html_str = self.generator.generate_outputs(structured_content)
return {
'success': True,
'pdf': pdf_bytes,
'html': html_str,
'structured_content': structured_content
}
except Exception as e:
return {
'success': False,
'error': str(e)
}
def_segment_sentences(self, text: str) -> List[str]:
"""
Intelligent sentence segmentation using NLTK.
Handles edge cases:
- Abbreviations (Dr., Mr., etc.)
- Decimal numbers
- URLs and emails
"""import nltk
nltk.download('punkt', quiet=True)
# Use NLTK's pre-trained sentence tokenizer
sentences = nltk.sent_tokenize(text)
# Post-process to merge incorrectly split sentences
merged_sentences = []
buffer = ""for sentence in sentences:
if buffer and (
len(sentence.split()) < 3or# Very short sentence
sentence[0].islower() # Starts with lowercase
):
buffer += " " + sentence
else:
if buffer:
merged_sentences.append(buffer)
buffer = sentence
if buffer:
merged_sentences.append(buffer)
return merged_sentences
def_build_sections(self, sentences: List[str], segments: List[Tuple[int, int]]) -> List[Dict]:
"""
Build hierarchical section structure.
Uses heuristics to identify:
- Main sections (major topic changes)
- Subsections (subtopic elaborations)
"""
sections = []
for start, end in segments:
segment_sentences = sentences[start:end]
# Determine if this is a main section or subsection# Heuristic: First sentence length and capitalization
first_sentence = segment_sentences[0] if segment_sentences else""
is_main_section = (
len(first_sentence.split()) < 10and
first_sentence[0].isupper()
)
section_data = {
'title': self._generate_section_title(segment_sentences),
'paragraphs': self._group_into_paragraphs(segment_sentences),
'is_main': is_main_section
}
sections.append(section_data)
# Organize into hierarchical structure
hierarchical_sections = []
current_main = Nonefor section in sections:
if section['is_main']:
if current_main:
hierarchical_sections.append(current_main)
current_main = {
'title': section['title'],
'paragraphs': section['paragraphs'],
'subsections': []
}
else:
if current_main:
current_main['subsections'].append({
'title': section['title'],
'paragraphs': section['paragraphs']
})
else:
# Orphan subsection becomes main section
hierarchical_sections.append({
'title': section['title'],
'paragraphs': section['paragraphs'],
'subsections': []
})
if current_main:
hierarchical_sections.append(current_main)
return hierarchical_sections
def_generate_section_title(self, sentences: List[str]) -> str:
"""
Generate descriptive section title using keyword extraction.
Algorithm:
1. Extract keywords using TF-IDF
2. Identify most important 2-3 words
3. Create grammatical title
"""ifnot sentences:
return"Untitled Section"# Combine first few sentences for context
context = ' '.join(sentences[:min(3, len(sentences))])
# Simple keyword extractionfrom collections import Counter
import string
# Remove punctuation and convert to lowercase
words = context.translate(str.maketrans('', '', string.punctuation)).lower().split()
# Remove common words
stop_words = {'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
'of', 'with', 'by', 'from', 'up', 'about', 'into', 'through', 'during',
'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had',
'do', 'does', 'did', 'will', 'would', 'should', 'could', 'may', 'might'}
keywords = [w for w in words if w notin stop_words andlen(w) > 3]
# Get top keywords
keyword_counts = Counter(keywords)
top_keywords = [word for word, _ in keyword_counts.most_common(3)]
if top_keywords:
# Capitalize and format
title = ' '.join(word.capitalize() for word in top_keywords)
else:
title = "Continued Discussion"return title
def_group_into_paragraphs(self, sentences: List[str]) -> List[str]:
"""
Group sentences into coherent paragraphs.
Uses semantic similarity to determine paragraph boundaries.
Optimal paragraph length: 3-7 sentences
"""iflen(sentences) <= 5:
return [' '.join(sentences)]
paragraphs = []
current_paragraph = []
for i, sentence inenumerate(sentences):
current_paragraph.append(sentence)
# Check if we should start a new paragraphif (len(current_paragraph) >= 3and
(len(current_paragraph) >= 7orself._is_paragraph_boundary(current_paragraph, sentences[i+1:i+2]))):
paragraphs.append(' '.join(current_paragraph))
current_paragraph = []
if current_paragraph:
paragraphs.append(' '.join(current_paragraph))
return paragraphs
def_is_paragraph_boundary(self, current: List[str], next_sentences: List[str]) -> bool:
"""
Determine if there should be a paragraph break.
Heuristics:
- Topic shift (low similarity)
- Transition words
- Significant length difference
"""ifnot next_sentences:
returnTrue# Check for transition indicators
transition_words = ['however', 'moreover', 'furthermore', 'additionally',
'in conclusion', 'to summarize', 'first', 'second', 'finally',
'on the other hand', 'in contrast', 'nevertheless']
next_lower = next_sentences[0].lower()
for transition in transition_words:
if next_lower.startswith(transition):
returnTrue# Check length difference
avg_current_length = sum(len(s.split()) for s in current) / len(current)
next_length = len(next_sentences[0].split())
ifabs(avg_current_length - next_length) > 15:
returnTruereturnFalsedef_enhance_sections(self, sections: List[Dict]) -> List[Dict]:
"""
Enhance sections with educational features.
Enhancements:
- Key concept identification
- Example generation
- Cross-references
- Summary points
"""
enhanced = []
for section in sections:
# Extract concepts from section content
section_text = ' '.join(section['paragraphs'])
concepts = self.enhancer.extract_key_concepts(section_text)[:3] # Top 3 concepts
enhanced_section = {
**section,
'concepts': concepts
}
# Enhance subsections similarlyif'subsections'in section:
enhanced_subsections = []
for subsection in section['subsections']:
subsection_text = ' '.join(subsection['paragraphs'])
subsection_concepts = self.enhancer.extract_key_concepts(subsection_text)[:2]
enhanced_subsections.append({
**subsection,
'concepts': subsection_concepts
})
enhanced_section['subsections'] = enhanced_subsections
enhanced.append(enhanced_section)
return enhanced
def_extract_title(self, text: str) -> str:
"""
Extract or generate lecture title from content.
Strategies:
1. Look for explicit title mentions
2. Use first significant topic
3. Generate from main themes
"""# Try to find explicit title patterns
title_patterns = [
r"(?:lecture|lesson|chapter|module)\s*(?:on|about|title:|:)?\s*([^.]+)",
r"(?:today|this)\s+(?:lecture|lesson|session)\s+(?:is about|covers|on)\s+([^.]+)",
r"welcome to\s+([^.]+)"
]
for pattern in title_patterns:
match = re.search(pattern, text[:500], re.IGNORECASE)
ifmatch:
title = match.group(1).strip()
# Clean and capitalize
title = ' '.join(word.capitalize() for word in title.split())
return title
# Fallback: Use key concepts
concepts = self.enhancer.extract_key_concepts(text[:1000])
if concepts:
top_concepts = [c['term'] for c in concepts[:3]]
returnf"Lecture on {', '.join(top_concepts)}"return"Lecture Notes"
Usage Instructions
Step 1: Upload Transcript
# Read the transcript filewithopen('/path/to/transcript.txt', 'r', encoding='utf-8') as f:
transcript_text = f.read()
Step 2: Process Transcript
# Initialize processor
processor = LectureNotesProcessor()
# Process with optional title
result = processor.process_transcript(
transcript_text,
lecture_title="Advanced Machine Learning Concepts"
)
Step 3: Save Outputs
if result['success']:
# Save PDFwithopen('/output/lecture_notes.pdf', 'wb') as f:
f.write(result['pdf'])
# Save HTMLwithopen('/output/lecture_notes.html', 'w', encoding='utf-8') as f:
f.write(result['html'])
print("✓ Lecture notes generated successfully!")
else:
print(f"✗ Error: {result['error']}")
Advanced Configuration
Customization Parameters
classAdvancedConfig:
"""
Configuration parameters for fine-tuning the processing.
Each parameter affects the output quality/processing time tradeoff:
Q(output) ∝ √(processing_time) for most parameters
"""# Cleaning parameters
REMOVE_FILLER_WORDS = True
FILLER_CONFIDENCE_THRESHOLD = 0.75# Structuring parameters
TOPIC_WINDOW_SIZE = 5# Sentences per window
TOPIC_SIMILARITY_THRESHOLD = 0.3# Lower = more sections
MIN_SECTION_LENGTH = 3# Minimum sentences per section# Enhancement parameters
MAX_CONCEPTS_PER_SECTION = 5
GENERATE_EXAMPLES = True
EXAMPLES_PER_CONCEPT = 3# Output parameters
PDF_PAGE_SIZE = 'letter'# or 'A4'
HTML_THEME = 'academic'# or 'modern', 'classic'
INCLUDE_PAGE_NUMBERS = True
INCLUDE_TIMESTAMP = True# Processing options
PARALLEL_PROCESSING = True
MAX_WORKERS = 4
CACHE_INTERMEDIATE_RESULTS = True
Error Handling and Logging
import logging
from typing importOptionalclassRobustProcessor(LectureNotesProcessor):
"""
Enhanced processor with comprehensive error handling.
"""def__init__(self, log_level: str = 'INFO'):
super().__init__()
self.logger = self._setup_logging(log_level)
def_setup_logging(self, level: str) -> logging.Logger:
"""Configure structured logging."""
logger = logging.getLogger('LectureNotes')
logger.setLevel(getattr(logging, level))
# Console handler
console_handler = logging.StreamHandler()
console_format = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
console_handler.setFormatter(console_format)
logger.addHandler(console_handler)
# File handler
file_handler = logging.FileHandler('lecture_processing.log')
file_format = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s'
)
file_handler.setFormatter(file_format)
logger.addHandler(file_handler)
return logger
defprocess_with_validation(self, transcript_text: str) -> Dict:
"""
Process with input validation and error recovery.
"""# Input validationifnot transcript_text:
self.logger.error("Empty transcript provided")
return {'success': False, 'error': 'Empty transcript'}
iflen(transcript_text) < 100:
self.logger.warning("Very short transcript - may not produce good results")
try:
# Process with timeoutimport signal
from contextlib import contextmanager
@contextmanagerdeftimeout(seconds):
defsignal_handler(signum, frame):
raise TimeoutError("Processing timeout")
signal.signal(signal.SIGALRM, signal_handler)
signal.alarm(seconds)
try:
yieldfinally:
signal.alarm(0)
with timeout(300): # 5 minute timeout
result = self.process_transcript(transcript_text)
# Validate outputif result['success']:
iflen(result['pdf']) < 1000:
self.logger.warning("Generated PDF seems too small")
iflen(result['html']) < 1000:
self.logger.warning("Generated HTML seems too small")
return result
except TimeoutError as e:
self.logger.error(f"Processing timeout: {e}")
return {'success': False, 'error': 'Processing took too long'}
except Exception as e:
self.logger.error(f"Unexpected error: {e}", exc_info=True)
return {'success': False, 'error': str(e)}
Performance Metrics
Quality Metrics
classQualityMetrics:
"""
Metrics for evaluating lecture notes quality.
Quality Score Q = w₁*Completeness + w₂*Coherence + w₃*Structure + w₄*Clarity
""" @staticmethoddefcalculate_completeness(original: str, notes: str) -> float:
"""
Measure how much content is preserved.
Completeness = |concepts_notes ∩ concepts_original| / |concepts_original|
"""# Extract concepts from both
original_concepts = set(original.lower().split())
notes_concepts = set(notes.lower().split())
ifnot original_concepts:
return0.0
overlap = original_concepts.intersection(notes_concepts)
returnlen(overlap) / len(original_concepts)
@staticmethoddefcalculate_coherence(paragraphs: List[str]) -> float:
"""
Measure semantic coherence between paragraphs.
Coherence = mean(similarity(p_i, p_{i+1})) for all adjacent paragraphs
"""iflen(paragraphs) < 2:
return1.0from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
vectorizer = TfidfVectorizer()
vectors = vectorizer.fit_transform(paragraphs)
coherence_scores = []
for i inrange(len(paragraphs) - 1):
similarity = cosine_similarity(
vectors[i:i+1],
vectors[i+1:i+2]
)[0][0]
coherence_scores.append(similarity)
returnsum(coherence_scores) / len(coherence_scores)
@staticmethoddefcalculate_structure_score(content: Dict) -> float:
"""
Evaluate structural organization.
Factors:
- Section balance
- Hierarchy depth
- Concept distribution
"""
sections = content.get('sections', [])
ifnot sections:
return0.0# Calculate section balance
section_lengths = [
len(' '.join(s['paragraphs']))
for s in sections
]
ifnot section_lengths:
return0.0
avg_length = sum(section_lengths) / len(section_lengths)
variance = sum((l - avg_length) ** 2for l in section_lengths) / len(section_lengths)
std_dev = variance ** 0.5# Lower coefficient of variation = better balance
cv = std_dev / avg_length if avg_length > 0else1.0
balance_score = max(0, 1 - cv)
# Check hierarchy
has_subsections = any('subsections'in s for s in sections)
hierarchy_score = 1.0if has_subsections else0.7# Check concepts
has_concepts = any('concepts'in s for s in sections)
concept_score = 1.0if has_concepts else0.8return (balance_score + hierarchy_score + concept_score) / 3
TextRank for Concept Importance:
$$PR(v_i) = (1-d) + d \times \sum_{v_j \in In(v_i)} \frac{w_{ji}}{\sum_{v_k \in Out(v_j)} w_{jk}} PR(v_j)$$
Conclusion
This skill provides a comprehensive solution for converting YouTube transcripts into professional lecture notes. The dual output format (PDF and HTML) ensures accessibility and usability across different platforms, while the intelligent processing preserves and enhances educational content.
The system's modular architecture allows for easy customization and extension, making it suitable for various educational contexts and content types.