Spaces:
Sleeping
Sleeping
File size: 5,284 Bytes
3036801 c2e808d 923f3ac 3036801 923f3ac 3036801 c2e808d 3036801 c2e808d 923f3ac 3036801 923f3ac c2e808d 3036801 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# app.py
import os
import subprocess
import glob
import re
import traceback
import gradio as gr
from openai import OpenAI
# Load OpenAI key from environment (Hugging Face Spaces -> Settings -> Secrets)
openai_api_key = os.getenv("OPENAI_API_KEY")
openai = OpenAI(api_key=openai_api_key)
# def download_audio(youtube_url):
# try:
# output_template = "/tmp/downloaded_audio.%(ext)s"
# # Remove any old files
# for f in glob.glob("/tmp/downloaded_audio.*"):
# os.remove(f)
# command = [
# "yt-dlp", "-f", "bestaudio",
# "--extract-audio", "--audio-format", "mp3",
# "--audio-quality", "0",
# "-o", output_template,
# youtube_url
# ]
# result = subprocess.run(command, capture_output=True, text=True)
# print("stdout:\n", result.stdout)
# print("stderr:\n", result.stderr)
# if result.returncode != 0:
# raise RuntimeError(f"yt-dlp failed: {result.stderr}")
# files = glob.glob("/tmp/downloaded_audio.*")
# if not files:
# raise FileNotFoundError("No audio file downloaded.")
# return files[0]
# except Exception as e:
# raise RuntimeError(f"Download error: {e}")
from pytube import YouTube
def clean_url(url):
# Extract just the video ID
match = re.search(r"(?:v=|shorts/)([a-zA-Z0-9_-]{11})", url)
video_id = match.group(1) if match else None
return f"https://www.youtube.com/watch?v={video_id}" if video_id else url
def download_audio(youtube_url):
try:
# Try yt-dlp first
output_template = "/tmp/downloaded_audio.%(ext)s"
for f in glob.glob("/tmp/downloaded_audio.*"):
os.remove(f)
command = [
"yt-dlp",
"-f", "bestaudio",
"--extract-audio", "--audio-format", "mp3",
"--audio-quality", "0",
"-o", output_template,
youtube_url
]
result = subprocess.run(command, capture_output=True, text=True)
if result.returncode == 0:
files = glob.glob("/tmp/downloaded_audio.*")
if files:
return files[0]
# ๐ Fallback to pytube
print("๐ yt-dlp failed, trying pytube...")
safe_url = clean_url(youtube_url)
yt = YouTube(safe_url)
stream = yt.streams.filter(only_audio=True).first()
output_path = "/tmp/fallback_audio.mp4"
stream.download(filename=output_path)
return output_path
except Exception as e:
raise RuntimeError(f"Download error: {e}")
def transcribe_audio(file_path):
try:
with open(file_path, "rb") as f:
result = openai.audio.transcriptions.create(
model="whisper-1",
file=f,
response_format="verbose_json"
)
return result["text"], result["language"]
except Exception as e:
raise RuntimeError(f"Transcription error: {e}")
def summarize_text(text, lang):
lang = lang.lower()
if lang.startswith("zh") or "chinese" in lang:
prompt = "ไฝ ๆฏไธไฝ่ฐๆ็ๅฉๆ๏ผ่ฝๅค ็จ็น้ซไธญๆๆธ
ๆฅไธๅฎๆดๅฐๆ่ฆๅฝฑ็ๅ
งๅฎนใ"
elif lang.startswith("ja") or "japanese" in lang:
prompt = "ใใชใใฏๆฅๆฌ่ชใง่ฆ็นใ็ฐกๆฝใใคๅใใใใใ่ฆ็ดใใๆ่ฝใชใขใทในใฟใณใใงใใ"
else:
prompt = "You are a helpful assistant that summarizes transcripts clearly and concisely."
response = openai.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": prompt},
{"role": "user", "content": f"Summarize the following transcript:\n\n{text}"}
]
)
summary = response.choices[0].message.content
debug_info = f"๐ Detected Language: {lang}\n๐ง Prompt Used: {prompt}"
return summary, debug_info
def extract_video_id(url):
match = re.search(r"(?:v=|shorts/)([a-zA-Z0-9_-]{11})", url)
return match.group(1) if match else None
def full_process(youtube_url):
try:
video_id = extract_video_id(youtube_url)
thumbnail_url = f"https://img.youtube.com/vi/{video_id}/maxresdefault.jpg" if video_id else None
audio_path = download_audio(youtube_url)
transcript, lang = transcribe_audio(audio_path)
summary, debug = summarize_text(transcript, lang)
return summary, debug, thumbnail_url
except Exception as e:
return f"โ Error: {str(e)}", "", None
with gr.Blocks() as demo:
gr.Markdown("## ๐ง YouTube AI Summarizer\nEasily extract summaries from YouTube videos using Whisper + GPT. Supports English/Japanese/Chinese.")
with gr.Row():
youtube_input = gr.Textbox(label="๐ฅ Enter YouTube Video Link")
submit_btn = gr.Button("๐ Summarize")
summary_output = gr.Textbox(label="๐ AI Video Summary", lines=6)
info_output = gr.Textbox(label="๐ Language & Model Info", lines=4)
thumbnail_output = gr.Image(label="๐๏ธ Video Thumbnail", visible=True)
submit_btn.click(fn=full_process, inputs=youtube_input, outputs=[summary_output, info_output, thumbnail_output])
if __name__ == "__main__":
demo.launch()
|