Files
wehub-resource-sync 97e91a83f3
Ruff / Ruff (push) Waiting to run
Test / Core Tests (push) Waiting to run
Test / Offline Coverage Tests (Python 3.10) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.11) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.12) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.13) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.9) (push) Waiting to run
Test / Full Coverage (Python 3.11) (push) Waiting to run
Test / Core Provider Tests (OpenAI) (push) Blocked by required conditions
Test / Core Provider Tests (Anthropic) (push) Blocked by required conditions
Test / Core Provider Tests (Google) (push) Blocked by required conditions
Test / Core Provider Tests (Other) (push) Blocked by required conditions
Test / Anthropic Tests (push) Blocked by required conditions
Test / Gemini Tests (push) Blocked by required conditions
Test / Google GenAI Tests (push) Blocked by required conditions
Test / Vertex AI Tests (push) Blocked by required conditions
Test / OpenAI Tests (push) Blocked by required conditions
Test / Writer Tests (push) Blocked by required conditions
Test / Auto Client Tests (push) Blocked by required conditions
ty / type-check (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:36:38 +08:00

97 lines
3.3 KiB
Python

import instructor
from openai import OpenAI
from pydantic import BaseModel, Field
from youtube_transcript_api import YouTubeTranscriptApi
from rich.console import Console
from rich.table import Table
from rich.live import Live
client = instructor.from_openai(OpenAI())
class Chapter(BaseModel):
start_ts: float = Field(
...,
description="The start timestamp indicating when the chapter starts in the video.",
)
end_ts: float = Field(
...,
description="The end timestamp indicating when the chapter ends in the video.",
)
title: str = Field(
..., description="A concise and descriptive title for the chapter."
)
summary: str = Field(
...,
description="A brief summary of the chapter's content, don't use words like 'the speaker'",
)
def get_youtube_transcript(video_id: str) -> str:
try:
transcript = YouTubeTranscriptApi.get_transcript(video_id)
return " ".join(
[f"ts={entry['start']} - {entry['text']}" for entry in transcript]
)
except Exception as e:
print(f"Error fetching transcript: {e}")
return ""
def extract_chapters(transcript: str):
class Chapters(BaseModel):
chapters: list[Chapter]
return client.chat.completions.create_partial(
model="gpt-4o", # You can experiment with different models
response_model=Chapters,
messages=[
{
"role": "system",
"content": "Analyze the given YouTube transcript and extract chapters. For each chapter, provide a start timestamp, end timestamp, title, and summary.",
},
{"role": "user", "content": transcript},
],
)
if __name__ == "__main__":
video_id = input("Enter a Youtube Url: ")
video_id = video_id.split("v=")[1]
console = Console()
with console.status("[bold green]Processing YouTube URL...") as status:
transcripts = get_youtube_transcript(video_id)
status.update("[bold blue]Generating Clips...")
chapters = extract_chapters(transcripts)
table = Table(title="Video Chapters")
table.add_column("Title", style="magenta")
table.add_column("Description", style="green")
table.add_column("Start", style="cyan")
table.add_column("End", style="cyan")
with Live(refresh_per_second=4) as live:
for extraction in chapters:
if not extraction.chapters:
continue
new_table = Table(title="Video Chapters")
new_table.add_column("Title", style="magenta")
new_table.add_column("Description", style="green")
new_table.add_column("Start", style="cyan")
new_table.add_column("End", style="cyan")
for chapter in extraction.chapters:
new_table.add_row(
chapter.title,
chapter.summary,
f"{chapter.start_ts:.2f}" if chapter.start_ts else "",
f"{chapter.end_ts:.2f}" if chapter.end_ts else "",
)
new_table.add_row("", "", "", "") # Add an empty row for spacing
live.update(new_table)
console.print("\nChapter extraction complete!")