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
97 lines
3.3 KiB
Python
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!")
|