Spaces:
Running
Running
import gradio as gr | |
from google import genai | |
from youtube_transcript_api import YouTubeTranscriptApi | |
from youtube_transcript_api._errors import TranscriptsDisabled, NoTranscriptFound, VideoUnavailable | |
import re | |
import time | |
import requests | |
from urllib.parse import urlparse, parse_qs | |
import socket | |
def find_free_port(start_port=7860, max_port=7960): | |
"""Boş bir port bul""" | |
for port in range(start_port, max_port): | |
try: | |
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | |
s.bind(('', port)) | |
return port | |
except OSError: | |
continue | |
return None | |
#https://www.youtube.com/watch?v=bhR274lZNLo | |
def is_valid_youtube_url(url): | |
try: | |
parsed_url = urlparse(url) | |
if 'youtube.com' in parsed_url.netloc or 'youtu.be' in parsed_url.netloc: | |
return True | |
return False | |
except: | |
return False | |
def extract_video_id(url): | |
if not url: | |
return None | |
try: | |
if 'youtu.be' in url: | |
return url.split('youtu.be/')[-1].split('?')[0] | |
parsed_url = urlparse(url) | |
if 'youtube.com' in parsed_url.netloc: | |
query = parse_qs(parsed_url.query) | |
return query.get('v', [None])[0] | |
except Exception: | |
return None | |
return None | |
def get_transcript(video_url): | |
if not video_url: | |
return "Lütfen bir YouTube URL'si girin." | |
if not is_valid_youtube_url(video_url): | |
return "Geçersiz YouTube URL'si. Lütfen doğru bir URL girin." | |
video_id = extract_video_id(video_url) | |
if not video_id: | |
return "Video ID çıkarılamadı. Lütfen geçerli bir YouTube URL'si girin." | |
max_retries = 3 | |
retry_delay = 2 | |
for attempt in range(max_retries): | |
try: | |
# Önce video erişilebilirliğini kontrol et | |
check_url = f"https://www.youtube.com/oembed?url=http://www.youtube.com/watch?v={video_id}" | |
response = requests.get(check_url) | |
if response.status_code != 200: | |
return "Video bulunamadı veya erişilemez durumda." | |
# Transkript almayı dene | |
transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['en', 'tr']) | |
if not transcript: | |
return "Transkript bulunamadı." | |
raw_text = " ".join([entry['text'] for entry in transcript]) | |
if not raw_text.strip(): | |
return "Transkript boş görünüyor." | |
return raw_text | |
except requests.exceptions.RequestException: | |
if attempt < max_retries - 1: | |
time.sleep(retry_delay) | |
continue | |
return "Bağlantı hatası oluştu. Lütfen internet bağlantınızı kontrol edin." | |
except TranscriptsDisabled: | |
return "Bu video için altyazılar devre dışı bırakılmış." | |
except NoTranscriptFound: | |
return "Bu video için transkript bulunamadı. Video başka bir dilde olabilir." | |
except VideoUnavailable: | |
return "Video bulunamadı veya erişilemez durumda." | |
except Exception as e: | |
if attempt < max_retries - 1: | |
time.sleep(retry_delay) | |
continue | |
return f"Bir hata oluştu: {str(e)}" | |
return "Maksimum deneme sayısına ulaşıldı. Lütfen daha sonra tekrar deneyin." | |
def fn_sum_text(transkript_text, word_count, model_sel, lang_sel, action_sel, GEMINI_API_KEY): | |
if not GEMINI_API_KEY: | |
return "Lütfen Gemini API anahtarını girin." | |
if not transkript_text: | |
return "Önce transkript alınmalıdır." | |
try: | |
client = genai.Client(api_key=GEMINI_API_KEY) | |
prompt = f"{transkript_text} metni {word_count} sayıda kelimeyle {lang_sel} dilinde {action_sel}" | |
max_retries = 3 | |
retry_delay = 2 | |
for attempt in range(max_retries): | |
try: | |
response = client.models.generate_content( | |
model=model_sel, | |
contents=[prompt] | |
) | |
return response.text | |
except Exception as e: | |
if attempt < max_retries - 1: | |
time.sleep(retry_delay) | |
continue | |
return f"API hatası: {str(e)}" | |
except Exception as e: | |
return f"Özet oluşturulurken hata: {str(e)}" | |
with gr.Blocks() as demo: | |
gr.Markdown("## YouTube Video Transkript ve Özet Aracı") | |
with gr.Row(): | |
with gr.Column(): | |
video_url = gr.Textbox( | |
label="YouTube Video URL", | |
placeholder="https://www.youtube.com/watch?v=...", | |
show_label=True | |
) | |
trs_btn = gr.Button('Transkripti Al', variant="primary") | |
with gr.Group(): | |
GEMINI_API_KEY = gr.Textbox( | |
label="GEMINI API KEY", | |
placeholder="Gemini API anahtarınızı girin", | |
type="password", | |
show_label=True | |
) | |
word_count = gr.Slider( | |
minimum=50, | |
maximum=1000, | |
value=200, | |
step=10, | |
label="Özet Kelime Sayısı" | |
) | |
model_sel = gr.Dropdown( | |
choices=['gemini-2.0-flash', 'gemini-2.0-flash-lite', 'gemini-1.5-pro'], | |
value='gemini-2.0-flash', | |
label="Model Seçimi" | |
) | |
lang_sel = gr.Dropdown( | |
choices=['Türkçe', 'İngilizce', 'Almanca'], | |
value='Türkçe', | |
label="Dil Seçimi" | |
) | |
action_sel = gr.Dropdown( | |
choices=['Özetle', 'tam çeviri yap.'], | |
value='Özetle', | |
label="İşlem" | |
) | |
sum_btn = gr.Button('Özetle', variant="primary") | |
with gr.Column(): | |
transkript_text = gr.Textbox( | |
label='Transkript', | |
lines=10, | |
show_label=True | |
) | |
sum_text = gr.Textbox( | |
label='Özet', | |
lines=10, | |
show_label=True | |
) | |
trs_btn.click( | |
fn=get_transcript, | |
inputs=video_url, | |
outputs=transkript_text, | |
api_name="get_transcript" | |
) | |
sum_btn.click( | |
fn=fn_sum_text, | |
inputs=[transkript_text, word_count, model_sel, lang_sel, action_sel, GEMINI_API_KEY], | |
outputs=sum_text, | |
api_name="summarize" | |
) | |
if __name__ == '__main__': | |
# Boş port bul | |
port = find_free_port() | |
if port is None: | |
print("Kullanılabilir port bulunamadı. Lütfen farklı bir port aralığı deneyin.") | |
exit(1) | |
print(f"Uygulama {port} portunda başlatılıyor...") | |
demo.launch( | |
server_name="127.0.0.1", # Localhost'a değiştirdik | |
server_port=port, | |
show_error=True, | |
share=False | |
) | |