lexicalspace commited on
Commit
de8af1a
·
verified ·
1 Parent(s): ce39081

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -81
app.py CHANGED
@@ -1,8 +1,9 @@
1
  import streamlit as st
2
- import streamlit.components.v1 as components
 
 
3
  from bs4 import BeautifulSoup
4
  import markdown
5
- import re
6
 
7
  # --- PAGE CONFIG ---
8
  st.set_page_config(
@@ -12,7 +13,7 @@ st.set_page_config(
12
  initial_sidebar_state="expanded"
13
  )
14
 
15
- # --- SIDEBAR ---
16
  st.sidebar.title("Navigation")
17
  query_params = st.query_params
18
  default_index = 1 if query_params.get("mode") == "downloader" else 0
@@ -23,91 +24,127 @@ app_mode = st.sidebar.radio(
23
  index=default_index
24
  )
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  # ==========================================
27
- # VIEW 1: YOUTUBE DOWNLOADER (Swarm Mode)
28
  # ==========================================
29
  if app_mode == "YouTube Downloader":
30
- # main.py
31
- # Hugging Face Space: YouTube MP3 API + UI
32
- # Works on CPU, no API key, no login
33
-
34
- import os
35
- import uuid
36
- from fastapi import FastAPI
37
- from fastapi.responses import FileResponse
38
- import yt_dlp
39
- import gradio as gr
40
-
41
- OUTPUT_DIR = "downloads"
42
- os.makedirs(OUTPUT_DIR, exist_ok=True)
43
-
44
- app = FastAPI()
45
-
46
-
47
- def download_mp3(youtube_url: str):
48
- uid = str(uuid.uuid4())
49
- out_file = os.path.join(OUTPUT_DIR, f"{uid}.mp3")
50
-
51
- ydl_opts = {
52
- 'format': 'bestaudio/best',
53
- 'outtmpl': out_file.replace('.mp3', '.%(ext)s'),
54
- 'postprocessors': [{
55
- 'key': 'FFmpegExtractAudio',
56
- 'preferredcodec': 'mp3',
57
- 'preferredquality': '192',
58
- }],
59
- 'quiet': True,
60
- 'noplaylist': True,
61
- }
62
-
63
- with yt_dlp.YoutubeDL(ydl_opts) as ydl:
64
- ydl.download([youtube_url])
65
-
66
- return out_file
67
-
68
-
69
- # ---------- API ENDPOINT ----------
70
- @app.get("/mp3")
71
- def mp3_api(url: str):
72
- mp3_path = download_mp3(url)
73
- return FileResponse(mp3_path, filename="audio.mp3", media_type="audio/mpeg")
74
-
75
-
76
- # ---------- UI ----------
77
- def ui_download(url):
78
- mp3_path = download_mp3(url)
79
- return mp3_path
80
-
81
- ui = gr.Interface(
82
- fn=ui_download,
83
- inputs=gr.Textbox(label="YouTube URL"),
84
- outputs=gr.File(label="Download MP3"),
85
- title="YouTube → MP3 Converter",
86
- description="Paste YouTube link and get MP3 audio"
87
- )
88
-
89
-
90
- if __name__ == "__main__":
91
- ui.launch(server_name="0.0.0.0", server_port=7860)
92
-
93
- # -----------------------------
94
- # requirements.txt (create this file manually):
95
- # fastapi
96
- # uvicorn
97
- # yt-dlp
98
- # gradio
99
- # ffmpeg-python
100
-
101
 
102
- components.html(html_code, height=350)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  # ==========================================
105
- # VIEW 2: WEBMASTER TOOLKIT (Server Side)
106
  # ==========================================
107
  elif app_mode == "Webmaster Toolkit":
108
  st.title("⚡ Webmaster's Toolkit")
109
- # ... (Keep your existing toolkit logic here if needed) ...
110
- tab1, tab2 = st.tabs(["📝 Text Cleaner", "🖼️ Media Optimizer"])
111
- # Just a placeholder for the logic you already have
112
  with tab1:
113
- st.write("Text Cleaner Active")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ import requests
3
+ import json
4
+ import re
5
  from bs4 import BeautifulSoup
6
  import markdown
 
7
 
8
  # --- PAGE CONFIG ---
9
  st.set_page_config(
 
13
  initial_sidebar_state="expanded"
14
  )
15
 
16
+ # --- SIDEBAR & SERVER SELECTOR ---
17
  st.sidebar.title("Navigation")
18
  query_params = st.query_params
19
  default_index = 1 if query_params.get("mode") == "downloader" else 0
 
24
  index=default_index
25
  )
26
 
27
+ # List of Public Cobalt v10 Instances (Community Hosted)
28
+ # If one fails, the user can switch to another.
29
+ SERVERS = {
30
+ "Auto (US)": "https://co.wuk.sh",
31
+ "Backup (EU)": "https://cobalt.api.timelessnesses.me",
32
+ "Backup (Asia)": "https://api.cobalt.750.moe",
33
+ "Backup (US-East)": "https://cobalt-api.hyper.lol"
34
+ }
35
+
36
+ if app_mode == "YouTube Downloader":
37
+ st.sidebar.markdown("---")
38
+ st.sidebar.subheader("⚙️ Server Settings")
39
+ selected_server_name = st.sidebar.selectbox("Processing Server", list(SERVERS.keys()))
40
+ api_base_url = SERVERS[selected_server_name]
41
+
42
  # ==========================================
43
+ # VIEW 1: YOUTUBE DOWNLOADER (v10 API)
44
  # ==========================================
45
  if app_mode == "YouTube Downloader":
46
+ st.title("🎥 YouTube Media Extractor")
47
+ st.caption(f"Powered by Cobalt v10 Server: {selected_server_name}")
48
+
49
+ url = st.text_input("Paste YouTube URL", placeholder="https://youtube.com/watch?v=...")
50
+
51
+ col1, col2 = st.columns(2)
52
+ with col1:
53
+ format_type = st.radio("Format", ["Video (MP4)", "Audio Only (MP3)"])
54
+
55
+ if url and st.button("🚀 Process Media"):
56
+ status_area = st.empty()
57
+ status_area.info("⏳ Contacting remote server...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
+ try:
60
+ # v10 API Payload Structure
61
+ headers = {
62
+ "Accept": "application/json",
63
+ "Content-Type": "application/json",
64
+ "User-Agent": "LexicalTools/1.0"
65
+ }
66
+
67
+ payload = {
68
+ "url": url,
69
+ # v10 uses 'downloadMode' instead of 'isAudioOnly'
70
+ "downloadMode": "audio" if "Audio" in format_type else "auto",
71
+ "videoQuality": "1080",
72
+ "filenameStyle": "basic"
73
+ }
74
+
75
+ # Send Request to selected instance
76
+ response = requests.post(f"{api_base_url}", headers=headers, json=payload)
77
+
78
+ try:
79
+ data = response.json()
80
+ except:
81
+ st.error(f"Server Error: {response.text}")
82
+ st.stop()
83
+
84
+ # Handle Success
85
+ if "url" in data:
86
+ download_link = data["url"]
87
+ status_area.success("✅ Media Ready!")
88
+
89
+ # Direct Stream Link (No server storage used)
90
+ st.link_button(f"⬇️ Click to Download {format_type}", download_link)
91
+
92
+ # Preview
93
+ if "Audio" not in format_type:
94
+ st.video(download_link)
95
+ else:
96
+ st.audio(download_link)
97
+
98
+ # Handle API Specific Errors
99
+ elif "text" in data:
100
+ st.error(f"API Error: {data['text']}")
101
+ else:
102
+ st.error("Unknown error. Try switching the server in the sidebar.")
103
+
104
+ except Exception as e:
105
+ st.error(f"Connection Failed: {str(e)}")
106
+ st.info("💡 Tip: Try selecting a different server in the Sidebar.")
107
 
108
  # ==========================================
109
+ # VIEW 2: WEBMASTER TOOLKIT (Existing)
110
  # ==========================================
111
  elif app_mode == "Webmaster Toolkit":
112
  st.title("⚡ Webmaster's Toolkit")
113
+
114
+ tab1, tab2 = st.tabs(["📝 Text Cleaner & SEO", "🖼️ Media Optimizer"])
115
+
116
  with tab1:
117
+ st.write("Paste your raw text or messy HTML below.")
118
+ raw_text = st.text_area("Input Text", height=200)
119
+ c1, c2, c3 = st.columns(3)
120
+ processed_text = ""
121
+
122
+ if c1.button("Strip HTML"):
123
+ soup = BeautifulSoup(raw_text, "html.parser")
124
+ processed_text = soup.get_text(separator=" ")
125
+ if c2.button("Fix Spacing"):
126
+ processed_text = re.sub(r'\s+', ' ', raw_text).strip()
127
+ if c3.button("MD to HTML"):
128
+ processed_text = markdown.markdown(raw_text)
129
+
130
+ if processed_text:
131
+ st.success("Done!")
132
+ st.text_area("Result", value=processed_text, height=200)
133
+
134
+ with tab2:
135
+ st.write("Convert heavy images to WebP.")
136
+ # Need to import PIL and io only here to save memory
137
+ from PIL import Image
138
+ import io
139
+
140
+ uploaded_file = st.file_uploader("Upload Image", type=['png', 'jpg', 'jpeg'])
141
+ if uploaded_file:
142
+ original_image = Image.open(uploaded_file)
143
+ st.image(original_image, caption="Original", use_container_width=True) # Updated for Streamlit 1.39+
144
+
145
+ if st.button("Convert to WebP"):
146
+ buffer = io.BytesIO()
147
+ original_image.save(buffer, format="WEBP", quality=80, optimize=True)
148
+ buffer.seek(0)
149
+ st.success("Converted!")
150
+ st.download_button("Download WebP", data=buffer, file_name="image.webp")