Spaces:
Paused
Paused
from flask import Flask, render_template, request, send_file, jsonify | |
from yt_dlp import YoutubeDL | |
import instaloader | |
import os | |
import uuid | |
import shutil | |
from waitress import serve | |
import ssl | |
import certifi | |
# Disable SSL verification warnings | |
ssl._create_default_https_context = ssl._create_unverified_context | |
app = Flask(__name__) | |
# Create downloads directory | |
os.makedirs('downloads', exist_ok=True) | |
def home(): | |
return render_template('index.html') | |
def download(): | |
url = request.form.get('url') | |
if not url: | |
return jsonify({'error': 'No URL provided'}), 400 | |
try: | |
if 'youtube.com' in url or 'youtu.be' in url: | |
return download_youtube(url) | |
elif 'instagram.com' in url: | |
return download_instagram(url) | |
elif 'tiktok.com' in url: | |
return download_tiktok(url) | |
else: | |
return jsonify({'error': 'Please enter a valid YouTube, Instagram, or TikTok URL'}), 400 | |
except Exception as e: | |
return jsonify({'error': str(e)}), 500 | |
def download_youtube(url): | |
try: | |
filename = f"youtube_{uuid.uuid4().hex}.mp4" | |
filepath = os.path.join('downloads', filename) | |
ydl_opts = { | |
'format': 'best', | |
'outtmpl': filepath, | |
'nocheckcertificate': True, | |
'no_check_certificates': True, | |
'quiet': True, | |
'no_warnings': True, | |
'ignoreerrors': True, | |
'extract_flat': True, | |
'force_generic_extractor': True, | |
'http_headers': { | |
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' | |
} | |
} | |
with YoutubeDL(ydl_opts) as ydl: | |
info = ydl.extract_info(url, download=True) | |
if info: | |
return send_file( | |
filepath, | |
as_attachment=True, | |
download_name=f"{info.get('title', 'video')}.mp4" | |
) | |
else: | |
raise Exception("Failed to extract video information") | |
except Exception as e: | |
return jsonify({'error': f'YouTube download failed: {str(e)}'}), 500 | |
finally: | |
if os.path.exists(filepath): | |
try: | |
os.remove(filepath) | |
except: | |
pass | |
def download_instagram(url): | |
try: | |
L = instaloader.Instaloader() | |
temp_dir = f"downloads/insta_{uuid.uuid4().hex}" | |
os.makedirs(temp_dir, exist_ok=True) | |
try: | |
if "/reel/" in url: | |
shortcode = url.split("/reel/")[1].split("/")[0] | |
elif "/p/" in url: | |
shortcode = url.split("/p/")[1].split("/")[0] | |
else: | |
raise ValueError("Invalid Instagram URL") | |
post = instaloader.Post.from_shortcode(L.context, shortcode) | |
L.download_post(post, target=temp_dir) | |
for file in os.listdir(temp_dir): | |
if file.endswith('.mp4'): | |
filepath = os.path.join(temp_dir, file) | |
return send_file( | |
filepath, | |
as_attachment=True, | |
download_name=f"instagram_{shortcode}.mp4" | |
) | |
raise Exception("No video found in this post") | |
finally: | |
if os.path.exists(temp_dir): | |
shutil.rmtree(temp_dir, ignore_errors=True) | |
except Exception as e: | |
return jsonify({'error': f'Instagram download failed: {str(e)}'}), 500 | |
def download_tiktok(url): | |
try: | |
filename = f"tiktok_{uuid.uuid4().hex}.mp4" | |
filepath = os.path.join('downloads', filename) | |
ydl_opts = { | |
'format': 'best', | |
'outtmpl': filepath, | |
'quiet': True, | |
'no_warnings': True, | |
'nocheckcertificate': True | |
} | |
with YoutubeDL(ydl_opts) as ydl: | |
ydl.download([url]) | |
if os.path.exists(filepath): | |
return send_file( | |
filepath, | |
as_attachment=True, | |
download_name=f"tiktok_video.mp4" | |
) | |
else: | |
raise Exception("Failed to download video") | |
except Exception as e: | |
return jsonify({'error': f'TikTok download failed: {str(e)}'}), 500 | |
finally: | |
if os.path.exists(filepath): | |
try: | |
os.remove(filepath) | |
except: | |
pass | |
def cleanup(response): | |
try: | |
for file in os.listdir('downloads'): | |
filepath = os.path.join('downloads', file) | |
if os.path.isfile(filepath): | |
os.remove(filepath) | |
except: | |
pass | |
return response | |
if __name__ == "__main__": | |
port = int(os.environ.get("PORT", 7860)) | |
serve(app, host="0.0.0.0", port=port) | |