Spaces:
Sleeping
Sleeping
File size: 5,911 Bytes
3036801 c2e808d ef7b107 923f3ac ef7b107 923f3ac 3036801 ef7b107 3036801 ef7b107 3036801 ef7b107 3036801 c2e808d 3036801 ef7b107 3036801 ef7b107 3036801 c2e808d ef7b107 c2e808d ef7b107 3036801 ef7b107 c2e808d ef7b107 c2e808d ef7b107 c2e808d 3036801 ef7b107 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 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# 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_youtube_url(url):
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 None
def download_audio(youtube_url):
try:
print(f"โถ๏ธ Original URL: {youtube_url}")
output_template = "/tmp/downloaded_audio.%(ext)s"
# Cleanup old files
for f in glob.glob("/tmp/downloaded_audio.*"):
os.remove(f)
# โ
Try yt-dlp first
command = [
"yt-dlp",
"-f", "bestaudio",
"--extract-audio", "--audio-format", "mp3",
"--audio-quality", "0",
"-o", output_template,
youtube_url
]
print("๐ก Running yt-dlp...")
result = subprocess.run(command, capture_output=True, text=True)
print("๐ yt-dlp stdout:", result.stdout)
print("๐ yt-dlp stderr:", result.stderr)
if result.returncode == 0:
files = glob.glob("/tmp/downloaded_audio.*")
if files:
print("โ
yt-dlp success.")
return files[0]
# ๐ Fallback: try pytube with cleaned URL
print("๐ yt-dlp failed. Trying pytube...")
clean_url = clean_youtube_url(youtube_url)
if not clean_url:
raise ValueError("Unable to extract video ID for pytube fallback.")
print(f"๐งฝ Cleaned URL for pytube: {clean_url}")
yt = YouTube(clean_url)
stream = yt.streams.filter(only_audio=True).first()
if not stream:
raise ValueError("No audio stream found via pytube.")
output_path = "/tmp/fallback_audio.mp4"
stream.download(filename=output_path)
print("โ
pytube download success.")
return output_path
except Exception as e:
print("โ Final Download error:", 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()
|