neougurcan commited on
Commit
f965e5a
·
verified ·
1 Parent(s): cf45a0f
Files changed (1) hide show
  1. De +451 -0
De ADDED
@@ -0,0 +1,451 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ %%capture
3
+ !pip install -q torch torchvision torchaudio
4
+ !pip install -q git+https://github.com/openai/whisper.git
5
+ !pip install -q yt-dlp moviepy gradio praw google-api-python-client
6
+ !sudo apt update
7
+ !sudo apt install -y ffmpeg
8
+
9
+ import os
10
+ import shutil
11
+ import concurrent.futures
12
+ import gradio as gr
13
+ import numpy as np
14
+ from PIL import Image, ImageEnhance
15
+ from moviepy.editor import VideoFileClip, CompositeVideoClip, TextClip, AudioFileClip
16
+ import yt_dlp as youtube_dl
17
+ import requests
18
+ import whisper
19
+ import tempfile
20
+ import subprocess
21
+ import logging
22
+ from googleapiclient.discovery import build
23
+ import praw
24
+ import torch
25
+
26
+ # Günlük kaydını azalt
27
+ logging.basicConfig(level=logging.ERROR)
28
+ logger = logging.getLogger()
29
+ logger.setLevel(logging.ERROR)
30
+
31
+ # Colab için özel ayarlar
32
+ OUTPUT_DIR = "/content/processed_videos"
33
+ TEMP_DIR = "/content/temp_video_files"
34
+
35
+ for d in [OUTPUT_DIR, TEMP_DIR]:
36
+ if not os.path.exists(d):
37
+ os.makedirs(d)
38
+
39
+ # Whisper modelini yükle
40
+ print("CUDA kullanılabilir mi?", torch.cuda.is_available())
41
+ model = whisper.load_model("base")
42
+ print("✅ Whisper model başarıyla yüklendi")
43
+
44
+ # ===== FONKSİYONLAR =====
45
+ def get_youtube_trending(youtube_api_key, region_code="TR", max_results=5):
46
+ """YouTube'dan trend videoları al"""
47
+ try:
48
+ youtube = build("youtube", "v3", developerKey=youtube_api_key)
49
+ req = youtube.videos().list(
50
+ part="snippet,contentDetails,statistics",
51
+ chart="mostPopular",
52
+ regionCode=region_code,
53
+ maxResults=max_results
54
+ )
55
+ res = req.execute()
56
+ videos = []
57
+ for item in res.get("items", []):
58
+ videos.append({
59
+ "id": item["id"],
60
+ "title": item["snippet"]["title"]
61
+ })
62
+ return videos
63
+ except Exception as e:
64
+ print(f"❌ YouTube trend hatası: {e}")
65
+ return []
66
+
67
+ def get_reddit_videos(client_id, client_secret, user_agent, subreddit="funny", limit=5):
68
+ """Reddit'ten popüler videoları al"""
69
+ try:
70
+ reddit = praw.Reddit(
71
+ client_id=client_id,
72
+ client_secret=client_secret,
73
+ user_agent=user_agent
74
+ )
75
+ sub = reddit.subreddit(subreddit)
76
+ videos = []
77
+ for post in sub.hot(limit=limit):
78
+ if post.is_video and post.media and 'reddit_video' in post.media:
79
+ media = post.media['reddit_video']
80
+ video_url = media['fallback_url']
81
+
82
+ # Ses dosyası URL'sini oluştur
83
+ audio_url = None
84
+ if media.get('has_audio', False):
85
+ base_url = video_url.split('_')[0]
86
+ audio_url = f"{base_url}_audio.mp4"
87
+
88
+ videos.append({
89
+ "id": post.id,
90
+ "title": post.title,
91
+ "video_url": video_url,
92
+ "audio_url": audio_url
93
+ })
94
+ return videos
95
+ except Exception as e:
96
+ print(f"❌ Reddit video hatası: {e}")
97
+ return []
98
+
99
+ def download_youtube_video(video_id, output_path):
100
+ """YouTube videosunu indir"""
101
+ try:
102
+ url = f"https://www.youtube.com/watch?v={video_id}"
103
+ ydl_opts = {
104
+ 'format': 'best[height<=720]', # 720p çözünürlük
105
+ 'outtmpl': output_path,
106
+ 'quiet': True,
107
+ 'no_warnings': True
108
+ }
109
+ with youtube_dl.YoutubeDL(ydl_opts) as ydl:
110
+ ydl.download([url])
111
+ return True
112
+ except Exception as e:
113
+ print(f"❌ YouTube indirme hatası: {e}")
114
+ return False
115
+
116
+ def download_reddit_video(video_url, audio_url, output_path):
117
+ """Reddit videosunu ve sesini indir ve birleştir"""
118
+ try:
119
+ # Videoyu indir
120
+ video_path = f"{output_path}_video.mp4"
121
+ r = requests.get(video_url, stream=True, timeout=30)
122
+ r.raise_for_status()
123
+ with open(video_path, "wb") as f:
124
+ for chunk in r.iter_content(chunk_size=8192):
125
+ f.write(chunk)
126
+
127
+ # Ses dosyası varsa indir ve birleştir
128
+ if audio_url:
129
+ audio_path = f"{output_path}_audio.mp4"
130
+ r_audio = requests.get(audio_url, stream=True, timeout=30)
131
+ r_audio.raise_for_status()
132
+ with open(audio_path, "wb") as f:
133
+ for chunk in r_audio.iter_content(chunk_size=8192):
134
+ f.write(chunk)
135
+
136
+ # Video ve sesi birleştir
137
+ video_clip = VideoFileClip(video_path)
138
+ audio_clip = AudioFileClip(audio_path)
139
+ final_clip = video_clip.set_audio(audio_clip)
140
+ final_clip.write_videofile(
141
+ output_path,
142
+ codec='libx264',
143
+ audio_codec='aac',
144
+ verbose=False,
145
+ logger=None,
146
+ threads=4 # Colab için daha fazla thread
147
+ )
148
+
149
+ # Geçici dosyaları temizle
150
+ os.remove(video_path)
151
+ os.remove(audio_path)
152
+ else:
153
+ # Ses yoksa videoyu direkt taşı
154
+ os.rename(video_path, output_path)
155
+ return True
156
+ except Exception as e:
157
+ print(f"❌ Reddit indirme hatası: {e}")
158
+ return False
159
+
160
+ def generate_subtitle_text(video_path, language='tr'):
161
+ """Whisper ile altyazı oluştur"""
162
+ try:
163
+ clip = VideoFileClip(video_path)
164
+ audio_path = os.path.join(TEMP_DIR, f"temp_audio.wav")
165
+ clip.audio.write_audiofile(audio_path, verbose=False, logger=None)
166
+ result = model.transcribe(audio_path, language=language)
167
+ os.remove(audio_path)
168
+ return result["text"]
169
+ except Exception as e:
170
+ print(f"❌ Altyazı oluşturma hatası: {e}")
171
+ return ""
172
+
173
+ def process_video_with_subtitle(input_path, output_path, subtitle_text, apply_filter=True):
174
+ """Videoyu işle ve altyazı ekle"""
175
+ try:
176
+ clip = VideoFileClip(input_path)
177
+ target_w, target_h = 720, 1280 # Reels formatı
178
+
179
+ # Reels formatına uygun boyutlandırma
180
+ clip_ratio = clip.w / clip.h
181
+ target_ratio = target_w / target_h
182
+
183
+ if clip_ratio > target_ratio:
184
+ # Yatay video, yüksekliği sabitleyip genişliği kırp
185
+ clip = clip.resize(height=target_h)
186
+ excess_width = clip.w - target_w
187
+ clip = clip.crop(x1=excess_width//2, x2=clip.w - excess_width//2)
188
+ else:
189
+ # Dikey video, genişliği sabitleyip yüksekliği kırp
190
+ clip = clip.resize(width=target_w)
191
+ excess_height = clip.h - target_h
192
+ clip = clip.crop(y1=excess_height//2, y2=clip.h - excess_height//2)
193
+
194
+ # Efekt uygula
195
+ if apply_filter:
196
+ def enhance_frame(get_frame, t):
197
+ frame = get_frame(t)
198
+ img = Image.fromarray(frame)
199
+ # Parlaklık ve renk artırma
200
+ enhancer = ImageEnhance.Brightness(img)
201
+ img = enhancer.enhance(1.1)
202
+ enhancer = ImageEnhance.Color(img)
203
+ img = enhancer.enhance(1.2)
204
+ return np.array(img)
205
+
206
+ clip = clip.fl(enhance_frame)
207
+
208
+ # Altyazı ekle
209
+ if subtitle_text.strip():
210
+ txt_clip = TextClip(
211
+ subtitle_text,
212
+ fontsize=40,
213
+ font='Arial-Bold',
214
+ color='yellow',
215
+ stroke_color='black',
216
+ stroke_width=2,
217
+ method='caption',
218
+ size=(target_w-40, None),
219
+ align='center'
220
+ )
221
+ txt_clip = txt_clip.set_position(('center', target_h - 150)).set_duration(clip.duration)
222
+ final = CompositeVideoClip([clip, txt_clip])
223
+ else:
224
+ final = clip
225
+
226
+ # Videoyu kaydet
227
+ final.write_videofile(
228
+ output_path,
229
+ codec='libx264',
230
+ audio_codec='aac',
231
+ fps=24,
232
+ verbose=False,
233
+ logger=None,
234
+ threads=4 # Colab için daha fazla thread
235
+ )
236
+ return True
237
+ except Exception as e:
238
+ print(f"❌ Video işleme hatası: {e}")
239
+ return False
240
+
241
+ def process_single_youtube(video_id, title):
242
+ """Tek bir YouTube videosunu işle"""
243
+ vid_path = os.path.join(TEMP_DIR, f"yt_{video_id}.mp4")
244
+ out_path = os.path.join(OUTPUT_DIR, f"yt_{video_id}_processed.mp4")
245
+
246
+ print(f"⏬ YouTube indiriliyor: {title}")
247
+ if not download_youtube_video(video_id, vid_path):
248
+ return None
249
+
250
+ print("🔤 Altyazı oluşturuluyor...")
251
+ subtitle = generate_subtitle_text(vid_path)
252
+ print(f"✅ Altyazı tamamlandı ({len(subtitle)} karakter)")
253
+
254
+ print("🎞️ Video işleniyor...")
255
+ if process_video_with_subtitle(vid_path, out_path, subtitle, apply_filter=True):
256
+ print(f"✅ İşlenen video kaydedildi: {out_path}")
257
+ # Geçici dosyayı temizle
258
+ if os.path.exists(vid_path):
259
+ os.remove(vid_path)
260
+ return out_path
261
+ else:
262
+ print(f"❌ Video işleme başarısız: {title}")
263
+ return None
264
+
265
+ def process_single_reddit(video_url, audio_url, post_id, title):
266
+ """Tek bir Reddit videosunu işle"""
267
+ vid_path = os.path.join(TEMP_DIR, f"reddit_{post_id}.mp4")
268
+ out_path = os.path.join(OUTPUT_DIR, f"reddit_{post_id}_processed.mp4")
269
+
270
+ print(f"⏬ Reddit indiriliyor: {title}")
271
+ if not download_reddit_video(video_url, audio_url, vid_path):
272
+ return None
273
+
274
+ print("🔤 Altyazı oluşturuluyor...")
275
+ subtitle = generate_subtitle_text(vid_path)
276
+ print(f"✅ Altyazı tamamlandı ({len(subtitle)} karakter)")
277
+
278
+ print("🎞️ Video işleniyor...")
279
+ if process_video_with_subtitle(vid_path, out_path, subtitle, apply_filter=True):
280
+ print(f"✅ İşlenen video kaydedildi: {out_path}")
281
+ # Geçici dosyayı temizle
282
+ if os.path.exists(vid_path):
283
+ os.remove(vid_path)
284
+ return out_path
285
+ else:
286
+ print(f"❌ Video işleme başarısız: {title}")
287
+ return None
288
+
289
+ # ===== ANA OTOMASYON FONKSİYONU =====
290
+ def run_automation(youtube_api_key, reddit_client_id, reddit_client_secret, reddit_user_agent,
291
+ yt_max=2, reddit_max=2, reddit_subreddit="funny"):
292
+ """Ana otomasyon fonksiyonu"""
293
+ results = []
294
+
295
+ # YouTube trending videoları
296
+ print("📊 YouTube trend videoları alınıyor...")
297
+ yt_videos = get_youtube_trending(youtube_api_key, max_results=yt_max)
298
+ print(f"✅ {len(yt_videos)} YouTube videosu bulundu")
299
+
300
+ # Reddit viral videolar
301
+ print("📊 Reddit popüler videolar alınıyor...")
302
+ reddit_videos = get_reddit_videos(
303
+ reddit_client_id,
304
+ reddit_client_secret,
305
+ reddit_user_agent,
306
+ subreddit=reddit_subreddit,
307
+ limit=reddit_max
308
+ )
309
+ print(f"✅ {len(reddit_videos)} Reddit videosu bulundu")
310
+
311
+ # Paralel işleme (Colab için daha fazla thread)
312
+ with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
313
+ futures = []
314
+
315
+ # YouTube işlemleri
316
+ for v in yt_videos:
317
+ futures.append(
318
+ executor.submit(
319
+ process_single_youtube,
320
+ v["id"],
321
+ v["title"]
322
+ )
323
+ )
324
+
325
+ # Reddit işlemleri
326
+ for v in reddit_videos:
327
+ futures.append(
328
+ executor.submit(
329
+ process_single_reddit,
330
+ v["video_url"],
331
+ v["audio_url"],
332
+ v["id"],
333
+ v["title"]
334
+ )
335
+ )
336
+
337
+ # Sonuçları topla
338
+ for future in concurrent.futures.as_completed(futures):
339
+ try:
340
+ out_path = future.result()
341
+ if out_path:
342
+ results.append(out_path)
343
+ except Exception as e:
344
+ print(f"❌ İşleme hatası: {e}")
345
+
346
+ return results
347
+
348
+ # ===== GRADIO ARAYÜZÜ =====
349
+ def start_process(youtube_api_key, reddit_client_id, reddit_client_secret, reddit_user_agent,
350
+ yt_max, reddit_max, reddit_subreddit):
351
+ """Gradio arayüzü için başlatma fonksiyonu"""
352
+ print("🚀 Otomasyon başlatıldı...")
353
+ outputs = run_automation(
354
+ youtube_api_key,
355
+ reddit_client_id,
356
+ reddit_client_secret,
357
+ reddit_user_agent,
358
+ int(yt_max),
359
+ int(reddit_max),
360
+ reddit_subreddit
361
+ )
362
+
363
+ # Sonuç mesajını oluştur
364
+ result_msg = f"✅ {len(outputs)} video başarıyla işlendi!\n\n"
365
+ for p in outputs:
366
+ filename = os.path.basename(p)
367
+ result_msg += f"• {filename}\n"
368
+
369
+ # Colab'da dosyaları indirme linki oluştur
370
+ if outputs:
371
+ result_msg += "\n📥 İşlenen Videoları İndir:\n"
372
+ for p in outputs:
373
+ filename = os.path.basename(p)
374
+ result_msg += f"<a href='/content/processed_videos/{filename}' download>{filename}</a><br>"
375
+
376
+ return result_msg
377
+
378
+ # Gradio arayüzünü oluştur
379
+ with gr.Blocks(title="YouTube & Reddit Otomasyonu", css=".download-link {color: blue; text-decoration: underline;}") as demo:
380
+ gr.Markdown("# 🎬 Otomatik YouTube & Reddit Video İşleme Sistemi")
381
+ gr.Markdown("Trend videoları indir, altyazı ekle ve Reels formatına dönüştür!")
382
+
383
+ with gr.Row():
384
+ with gr.Column():
385
+ gr.Markdown("### 🔑 API Ayarları")
386
+ youtube_api_key = gr.Textbox(
387
+ label="YouTube API Anahtarı",
388
+ value="AIzaSyAg9ucUlixeslEWVDY7vxdIQukxzrvEHAc"
389
+ )
390
+ reddit_client_id = gr.Textbox(
391
+ label="Reddit Client ID",
392
+ value="LhklcvvwDar42dPUSxjYtg"
393
+ )
394
+ reddit_client_secret = gr.Textbox(
395
+ label="Reddit Client Secret",
396
+ value="dzja3SHDkCbEECSya_nZ7qgUGm-T1w"
397
+ )
398
+ reddit_user_agent = gr.Textbox(
399
+ label="Reddit User Agent",
400
+ value="Specialist-Arm-391"
401
+ )
402
+
403
+ with gr.Column():
404
+ gr.Markdown("### ⚙️ İşlem Ayarları")
405
+ yt_max = gr.Slider(
406
+ 1, 5, value=2, step=1,
407
+ label="YouTube Video Sayısı",
408
+ info="İşlenecek YouTube video sayısı"
409
+ )
410
+ reddit_max = gr.Slider(
411
+ 1, 5, value=2, step=1,
412
+ label="Reddit Video Sayısı",
413
+ info="İşlenecek Reddit video sayısı"
414
+ )
415
+ reddit_subreddit = gr.Textbox(
416
+ label="Reddit Subreddit",
417
+ value="funny",
418
+ placeholder="Örnek: funny, videos, memes"
419
+ )
420
+
421
+ btn = gr.Button("🚀 Otomasyonu Başlat", variant="primary")
422
+ output_html = gr.HTML(label="📋 Sonuçlar") # HTML çıktı için
423
+
424
+ btn.click(
425
+ fn=start_process,
426
+ inputs=[
427
+ youtube_api_key,
428
+ reddit_client_id,
429
+ reddit_client_secret,
430
+ reddit_user_agent,
431
+ yt_max,
432
+ reddit_max,
433
+ reddit_subreddit
434
+ ],
435
+ outputs=output_html
436
+ )
437
+
438
+ gr.Markdown("### 📌 Colab Özel Notlar")
439
+ gr.Markdown("""
440
+ 1. **İlk Çalıştırma:** Bağımlılıklar otomatik kurulur (1-2 dakika)
441
+ 2. **GPU Desteği:** Whisper transkripsiyonu için GPU kullanılır
442
+ 3. **Dosya Konumları:**
443
+ - İşlenen videolar: `/content/processed_videos`
444
+ - Geçici dosyalar: `/content/temp_video_files`
445
+ 4. **İndirme:** İşlem tamamlandığında videoları indirebileceğiniz linkler gösterilir
446
+ 5. **Oturum Sonu:** Colab oturumu kapatıldığında tüm dosyalar silinir
447
+ """)
448
+
449
+ # ===== UYGULAMAYI BAŞLAT =====
450
+ print("🔥 Uygulama başlatılıyor...")
451
+ demo.launch(share=True, debug=True)